traceservices/commsdebugutility/SSVR/comsdbgwriter.cpp
changeset 0 08ec8eefde2f
child 1 c084286672be
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implements the Flogger server side data writing
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalComponent
       
    21 */
       
    22 
       
    23 #include "comsdbgwriter.h"
       
    24 #include "comsdbgmessages.h"
       
    25 
       
    26 
       
    27 const TInt KHeapBufSize = 50000;   // Maximum that the file buffer can grow to limit its impact somewhat
       
    28 
       
    29 
       
    30 // RDebug will truncate strings longer than the limit below
       
    31 const TInt KRDebugLimit = 0x100;
       
    32 
       
    33 
       
    34 // source strings, lengths and offsets
       
    35 _LIT8(KLogStartedString, "#Logging started on dd/mm/yyyy. Output version 2\r\n");	///< Format specifier for the very first line written. The output version is printed so tools processing the log output can determine the expected format of the output.
       
    36 _LIT8(KDateChangedString,"#      Date is now: dd/mm/yyyy.\r\n");	///< Format specifier for subsequent date changes
       
    37 const TInt KLogStartedStringLength = 50;
       
    38 const TInt KLogStartedDayOffset = 20;
       
    39 const TInt KLogStartedMonthOffset = 23;
       
    40 const TInt KLogStartedYearOffset = 26;
       
    41 
       
    42 _LIT8(KUnableToLog, "#Logs lost since log file couldn't be written to");
       
    43 
       
    44 _LIT8(KClearLogString, "#Clear Log called by ");
       
    45 const TInt KClearLogStringLength = 21;
       
    46 
       
    47 _LIT8(KEolCharacters, "\r\n");
       
    48 const TInt KEolCharactersLength = 2;
       
    49 
       
    50 _LIT8(KLogPathTree,"\\");	
       
    51 _LIT8(KLogFileExt,".");
       
    52 
       
    53 //Below const is... log string + 2 tags + 8 for the thread id + 3 tabs + EOL characters.
       
    54 const TInt KMaxFinalLogStringLength = KLogBufferSize+2*KMaxTagLength+8+3+KEolCharactersLength;
       
    55 
       
    56 _LIT8(KBadMediaString, "#Bad media setting in ini file.\r\n");
       
    57 _LIT8(KUnableToUpdateMedia, "#Unable to update logging media. Err code: %d\r\n");
       
    58 _LIT8(KUnableToLoadSerialDevices, "#Unable to load the LDD or PDD required for serial. Err code: %d\r\n");
       
    59 _LIT8(KUnableToOpenSerial, "#Unable to open the serial port. Err code: %d\r\n");
       
    60 _LIT8(KUnableToSetSerialConfig, "#Could not set serial port configuration after opening port. Err code: %d\r\n");
       
    61 
       
    62 // source characters
       
    63 _LIT8(KTabCharacter, "\t");
       
    64 _LIT8(KTypeIdentifierAscii, "a");
       
    65 _LIT8(KTypeIdentifierBinary, "b");
       
    66 
       
    67 // serial specs
       
    68 const TBps KFloggerSerialRate = EBps115200;
       
    69 const TInt KSerialRetryCount = 50;
       
    70 const TInt KSerialTimeoutInMicroSecs = 100000;
       
    71 
       
    72 // serial ports
       
    73 const TInt KSerialPort1 = 0;
       
    74 #if defined (__WINS__)
       
    75 const TInt KSerialPort2OnEmulator = 1;
       
    76 #else
       
    77 const TInt KSerialPort2OnTarget = 2;
       
    78 #endif
       
    79 
       
    80 #if defined (__WINS__)
       
    81 #define PDD_NAME _L("ECDRV.PDD")
       
    82 #define LDD_NAME _L("ECOMM.LDD")
       
    83 #else
       
    84 #define PDD_NAME _L("EUART1")
       
    85 #define LDD_NAME _L("ECOMM")
       
    86 #endif
       
    87 
       
    88 
       
    89 // log file specs
       
    90 _LIT(KLogFileName, "log.txt");
       
    91 _LIT(KLogDefaultFilePath, "C:\\logs\\");
       
    92 
       
    93 
       
    94 const TUint KZeroDate = 0;  ///< The day to count forward from when determining date roll.
       
    95 const TUint KSecondsToWriteTimestampOnNoActivity = 5;
       
    96 
       
    97 #if defined (__WINS__)
       
    98 const TInt Win32DisplayStringLengthMax = 1024; 
       
    99 #endif
       
   100 
       
   101 
       
   102 
       
   103 
       
   104 CLogManager* CLogManager::NewL(MLogArrayAccess& aArrayAccess)
       
   105 	{
       
   106 	CLogManager* self = new(ELeave) CLogManager(aArrayAccess);
       
   107 	CleanupStack::PushL(self);
       
   108 	self->ConstructL();
       
   109 	CleanupStack::Pop(self);
       
   110 	return self;
       
   111 	}
       
   112 
       
   113 
       
   114 CLogManager::CLogManager(MLogArrayAccess& aArrayAccess)
       
   115 : iArrayAccess(aArrayAccess), iTimeString(KTimeFormat)
       
   116 {}
       
   117 
       
   118 CLogManager::~CLogManager()
       
   119 	{
       
   120 	delete iLogger;
       
   121 	}
       
   122 
       
   123 void CLogManager::ConstructL()
       
   124 /*
       
   125  * Set the initial media to file and write there until the server has told us
       
   126  * which media is in the ini file.
       
   127  * Write the log started and date message. 
       
   128  */
       
   129 	{
       
   130 	iLogger = CFileWriter::NewL();	//File writer by default
       
   131 	iCurrentMediaSetting = KFileMedia;
       
   132 	iLoggingEnabled = EFalse;
       
   133 	}
       
   134 
       
   135 TInt CLogManager::ThreadEntryPoint(TAny* aPtr)
       
   136 	{
       
   137 	__UHEAP_MARK;
       
   138 
       
   139 	MLogArrayAccess* arrayAccess = static_cast<MLogArrayAccess*> (aPtr);
       
   140 
       
   141 	CTrapCleanup* cleanupStack = CTrapCleanup::New();
       
   142 	if (cleanupStack==NULL)
       
   143 		{
       
   144 		return KErrNoMemory;
       
   145 		}
       
   146 
       
   147 	TRAPD(err, CLogManager::DoRunThreadL(*arrayAccess));
       
   148 
       
   149 	delete cleanupStack;
       
   150 
       
   151 	__UHEAP_MARKEND;
       
   152 
       
   153 	return err;
       
   154 	}
       
   155 
       
   156 void CLogManager::DoRunThreadL(MLogArrayAccess& aArrayAccess)
       
   157 	{
       
   158 	CLogManager* self = CLogManager::NewL(aArrayAccess);
       
   159 	self->DoStart();
       
   160 	delete self;
       
   161 	}
       
   162 
       
   163 void CLogManager::DoStart()
       
   164 /**
       
   165  * Second/consumer/slave/draining/dequeuer thread main loop.
       
   166  * @note Continuously takes the log queue top message and processes it. Blocks on the "Get" if no messages.
       
   167  * @note Completes when a shutdown message is processed from the queue. This message sets "iShutDown".
       
   168  */
       
   169 	{
       
   170 	CLogMessageBase * message = NULL;
       
   171 
       
   172 	TInt ret = KErrNone;
       
   173 	RThread::Rendezvous(ret);
       
   174 
       
   175 	FOREVER
       
   176 		{
       
   177 		iArrayAccess.GetFirstMessageAndTakeOwnership(message);
       
   178 		__ASSERT_ALWAYS(message, User::Panic(KFloggerServerPanic, ENullMessageInArray));
       
   179 		message->Invoke(*this);
       
   180 		delete message;
       
   181         // GetFirstMessage waits on the request semaphore, so to balance these each 
       
   182 		// time a message is processed we must then signal the completion semaphore
       
   183 		// when in synchronous mode
       
   184 		iArrayAccess.SignalCompletionSemaphore();
       
   185 		if (iShutDown)
       
   186 			{
       
   187 			break;
       
   188 			}
       
   189 		}
       
   190 	}
       
   191 
       
   192 void CLogManager::WriteDateIntoLog(TBool firstTime)
       
   193 /**
       
   194  * Write the date straight to the log output
       
   195  * @param firstTime If ETrue then write a "log started" otherwise write a "date change" msg
       
   196  */
       
   197 	{
       
   198 	if (!iLoggingEnabled) 
       
   199 	   {
       
   200 	   return;
       
   201 	   }
       
   202 	//Put a date stamp for when we've started logging
       
   203 	//Can't use TTime::FormatL since it gives unicode and we want narrow.
       
   204 	TTime time;
       
   205 	TBuf8<KLogStartedStringLength> logDateString;
       
   206 	time.HomeTime();
       
   207 	TDateTime dateTime(time.DateTime());
       
   208 	if (firstTime)
       
   209 		{
       
   210 		logDateString.Copy(KLogStartedString);
       
   211 		}
       
   212 	else
       
   213 		{
       
   214 		logDateString.Copy(KDateChangedString);
       
   215 		}
       
   216 	TBuf8<2> holdingBuf;
       
   217 	holdingBuf.NumFixedWidth(dateTime.Day()+1, EDecimal, 2);
       
   218 	logDateString.Replace(KLogStartedDayOffset,2,holdingBuf);
       
   219 	holdingBuf.NumFixedWidth(dateTime.Month()+1, EDecimal, 2);
       
   220 	logDateString.Replace(KLogStartedMonthOffset,2,holdingBuf);
       
   221 	TBuf8<4> holdingBuf2;
       
   222 	holdingBuf2.NumFixedWidth(dateTime.Year(), EDecimal, 4);
       
   223 	logDateString.Replace(KLogStartedYearOffset,4,holdingBuf2);
       
   224 	iLogger->LogString(logDateString);
       
   225 	}
       
   226 
       
   227 void CLogManager::ClearLog(const TFullName& aName)
       
   228 	{
       
   229 	if (!iLoggingEnabled) 
       
   230 	   {
       
   231 	   return;
       
   232 	   }
       
   233 	TRAP_IGNORE(iLogger->ClearLogL());	//if there is an error there is nothing we can do.
       
   234 	TBuf8<KMaxFullName+KClearLogStringLength+KEolCharactersLength> buf(KClearLogString);
       
   235 	buf.Append(aName);
       
   236 	buf.Append(KEolCharacters);
       
   237 	iLogger->LogString(buf);
       
   238 	WriteDateIntoLog(ETrue);
       
   239 	iTicksSinceLastLog=0;
       
   240 	}
       
   241 
       
   242 void CLogManager::SetTimeL(const TTime& aTime)
       
   243 	{
       
   244 	if (!iLoggingEnabled) 
       
   245 	   {
       
   246 	   return;
       
   247 	   }
       
   248 	//check whether date has rolled and write it to log if necessary
       
   249 	TTime currentMicrosecs;
       
   250 	TTimeIntervalDays newDate;
       
   251 	currentMicrosecs.HomeTime();
       
   252 	TTime zeroDate = TTime(TInt64(KZeroDate));
       
   253 	newDate = currentMicrosecs.DaysFrom(zeroDate);
       
   254 	if (newDate > iCurrentDate)
       
   255 		{
       
   256 		WriteDateIntoLog(EFalse);
       
   257 		iCurrentDate = newDate;
       
   258 		}
       
   259 	
       
   260 	//Print the time to the log
       
   261 	//Have to do this stuff manually since TTime only provides Unicode formating
       
   262 	//which is not what we want.
       
   263 	// We format this each second regardless of whether it is used so that it is ready for use
       
   264 	// if a client logs since in normal use it would be rare for flogger not to log something each second.
       
   265 	TDateTime dateTime(aTime.DateTime());
       
   266 	TBuf8<2> holdingBuf;
       
   267 	holdingBuf.NumFixedWidth(dateTime.Hour(), EDecimal, 2);
       
   268 	iTimeString.Replace(KHourOffset,2,holdingBuf);
       
   269 	holdingBuf.NumFixedWidth(dateTime.Minute(), EDecimal, 2);
       
   270 	iTimeString.Replace(KMinuteOffset,2,holdingBuf);
       
   271 	holdingBuf.NumFixedWidth(dateTime.Second(), EDecimal, 2);
       
   272 	iTimeString.Replace(KSecondOffset,2,holdingBuf);
       
   273 	if (iTicksSinceLastLog++ < KSecondsToWriteTimestampOnNoActivity)
       
   274 		{
       
   275 		iLogger->LogString(iTimeString);
       
   276 		iLogger->FlushLogL();
       
   277 		}
       
   278 		
       
   279 	}
       
   280 
       
   281 void CLogManager::LogString(const TDesC8& aLogString, const TDesC8& aSubSystem, const TDesC8& aComponent, const TThreadId& aThreadId)
       
   282 	{
       
   283 	if (!iLoggingEnabled) 
       
   284 	   {
       
   285 	   return;
       
   286 	   }
       
   287 	if (iTicksSinceLastLog > KSecondsToWriteTimestampOnNoActivity)
       
   288 		{
       
   289 		iLogger->LogString(iTimeString);
       
   290 		}
       
   291 	iTicksSinceLastLog=0;
       
   292 
       
   293 	TBuf8<KMaxFinalLogStringLength> buf;
       
   294 	buf.Append(aSubSystem);
       
   295 	buf.Append(KTabCharacter);
       
   296 	buf.Append(aComponent);
       
   297 	buf.Append(KTabCharacter);
       
   298 	buf.Append(KTypeIdentifierAscii);
       
   299 	buf.Append(KTabCharacter);
       
   300 	buf.AppendNum(aThreadId, EHex);
       
   301 	buf.Append(KTabCharacter);
       
   302 	buf.Append(aLogString);
       
   303 	// check whether last two bytes of string are eol chars, since some lines have cr/lf, some don't
       
   304 	TPtr8 ptr(&buf[buf.Length()-2], 2, 2);
       
   305 	if (ptr.Compare(KEolCharacters)!=0)
       
   306 		{
       
   307 		buf.Append(KEolCharacters);
       
   308 		}
       
   309 	iLogger->LogString(buf);
       
   310 	}
       
   311 
       
   312 void CLogManager::LogBinaryDump(const TDesC8& aBinaryString, const TDesC8& aSubSystem, const TDesC8& aComponent)
       
   313 	{
       
   314 	iLogger->LogBinaryDump(aBinaryString, aSubSystem, aComponent);
       
   315 	}
       
   316 
       
   317 void CLogManager::LogComment(const TDesC8& aComment)
       
   318 	{
       
   319 	if (iTicksSinceLastLog > KSecondsToWriteTimestampOnNoActivity)
       
   320 		{
       
   321 		iLogger->LogString(iTimeString);
       
   322 		}
       
   323 	iTicksSinceLastLog=0;
       
   324 
       
   325 	iLogger->LogString(aComment);
       
   326 	}
       
   327 
       
   328 void CLogManager::MediaUpdate(const TDesC8& aMediaSetting, const TBool aForceFlush, const TDesC8& aLogPathSetting)
       
   329 	{
       
   330 	TRAPD(err, DoMediaUpdateL(aMediaSetting,aForceFlush, aLogPathSetting));
       
   331 	if (err!=KErrNone)
       
   332 		{
       
   333 		TBuf8<KMaxFinalLogStringLength> buf;
       
   334 		buf.Format(KUnableToUpdateMedia,err);
       
   335 		iLogger->LogString(buf);
       
   336 		}
       
   337 	}
       
   338 
       
   339 void CLogManager::DoMediaUpdateL(const TDesC8& aMediaSetting,const TBool aForceFlush, const TDesC8& aLogPathSetting)
       
   340 	{
       
   341 	//We should NEVER have no media selected, media is set on construction
       
   342 	//and there should always be something set up.
       
   343 	__ASSERT_ALWAYS(iLogger, User::Panic(KFloggerServerPanic, ENoLoggingMediaSetUp));
       
   344 
       
   345 	if (aMediaSetting.Length() == 0)
       
   346 		{
       
   347 		return;
       
   348 		}
       
   349 		
       
   350 	// if the ini file has been opened, the media setting will be either the default
       
   351 	// or some other string so we can allow logging. If we are only opening media now, output extra info.
       
   352 	TTime currentMicrosecs;
       
   353 	currentMicrosecs.HomeTime();
       
   354 	iCurrentDate = currentMicrosecs.DaysFrom(TTime(TInt64(KZeroDate)));
       
   355 	
       
   356 	if (!iLoggingEnabled)
       
   357 		{
       
   358 		iLoggingEnabled = ETrue;
       
   359 		WriteDateIntoLog(ETrue);
       
   360 		}
       
   361 	
       
   362 	//Media update is a best effort, if it fails we keep
       
   363 	//logging to the old media
       
   364 	//If bad media in ini file, carry on with old media and post message in log
       
   365 
       
   366 	if (aMediaSetting.CompareF(iCurrentMediaSetting)==0 && aLogPathSetting.CompareF(iLogPath) == 0)
       
   367 		{
       
   368 		//Media hasn't changed, so update flush status only
       
   369 		// ForceFlushing as far as media is concerned only applies to file since 
       
   370 		// serial has no such buffer which needs flushing.
       
   371 		iLogger->SetForceFlush(aForceFlush);
       
   372 		return;
       
   373 		}
       
   374 	if (!aMediaSetting.CompareF(KFileMedia))
       
   375 		{
       
   376 		CLoggerMediaBase* media = CFileWriter::NewL();
       
   377 		delete iLogger;
       
   378 		iLogger = media;
       
   379 		// ForceFlushing only applies to file since serial has no such buffer
       
   380 		iLogger->SetForceFlush(aForceFlush);
       
   381 		if(aLogPathSetting.Length() != 0)
       
   382 			{
       
   383 			(static_cast<CFileWriter*>(iLogger))->SetLogPath(aLogPathSetting);
       
   384 			WriteDateIntoLog(ETrue);
       
   385 			}
       
   386 		}
       
   387 	else if (!aMediaSetting.CompareF(KSerial1Media))
       
   388 		{
       
   389 		// lots of things can go wrong when constructing the serial, so
       
   390 		// we set it up in stages, and log here if an error
       
   391 		// If we get an error in NewL - just let generic error given by
       
   392 		// SetMedia cover it
       
   393 		//CLoggerMediaBase* media = CSerialWriter::NewL();
       
   394 		CSerialWriter* serial = CSerialWriter::NewL();
       
   395 
       
   396 		TInt res = serial->LoadDevices();
       
   397 		if (res != KErrNone)
       
   398 			{
       
   399 			TBuf8<KMaxFinalLogStringLength> buf;
       
   400 			buf.Format(KUnableToLoadSerialDevices,res);
       
   401 			iLogger->LogString(buf);
       
   402 			delete serial;
       
   403 			User::Leave(res);
       
   404 			}
       
   405 		res = serial->OpenPort(KSerialPort1);
       
   406 		if (res != KErrNone)
       
   407 			{
       
   408 			TBuf8<KMaxFinalLogStringLength> buf;
       
   409 			buf.Format(KUnableToOpenSerial,res);
       
   410 			iLogger->LogString(buf);
       
   411 			delete serial;
       
   412 			User::Leave(res);
       
   413 			}
       
   414 
       
   415 		res = serial->SetPortConfig();
       
   416 		if (res != KErrNone)
       
   417 			{
       
   418 			TBuf8<KMaxFinalLogStringLength> buf;
       
   419 			buf.Format(KUnableToSetSerialConfig,res);
       
   420 			iLogger->LogString(buf);
       
   421 			delete serial;
       
   422 			User::Leave(res);
       
   423 			}
       
   424 		CLoggerMediaBase* media = serial;
       
   425 		delete iLogger;
       
   426 		iLogger = media;
       
   427 		WriteDateIntoLog(ETrue);
       
   428 		}
       
   429 	else if (!aMediaSetting.CompareF(KSerial2Media))
       
   430 		{
       
   431 		// lots of things can go wrong when constructing the serial, so
       
   432 		// we set it up in stages, and log here if an error.
       
   433 		// If we get an error in NewL - just let generic error given by
       
   434 		// SetMedia cover it
       
   435 
       
   436 		CSerialWriter* serial = CSerialWriter::NewL();
       
   437 
       
   438 		TInt res = serial->LoadDevices();
       
   439 		if (res != KErrNone)
       
   440 			{
       
   441 			TBuf8<KMaxFinalLogStringLength> buf;
       
   442 			buf.Format(KUnableToLoadSerialDevices,res);
       
   443 			iLogger->LogString(buf);
       
   444 			delete serial;
       
   445 			User::Leave(res);
       
   446 			}
       
   447 
       
   448 		#if defined (__WINS__)
       
   449 		res = serial->OpenPort(KSerialPort2OnEmulator);
       
   450 		#else
       
   451 		res = serial->OpenPort(KSerialPort2OnTarget);
       
   452 		#endif
       
   453 
       
   454 		if (res != KErrNone)
       
   455 			{
       
   456 			TBuf8<KMaxFinalLogStringLength> buf;
       
   457 			buf.Format(KUnableToOpenSerial,res);
       
   458 			iLogger->LogString(buf);
       
   459 			delete serial;
       
   460 			User::Leave(res);
       
   461 			}
       
   462 
       
   463 		res = serial->SetPortConfig();
       
   464 		if (res != KErrNone)
       
   465 			{
       
   466 			TBuf8<KMaxFinalLogStringLength> buf;
       
   467 			buf.Format(KUnableToSetSerialConfig,res);
       
   468 			iLogger->LogString(buf);
       
   469 			delete serial;
       
   470 			User::Leave(res);
       
   471 			}
       
   472 		CLoggerMediaBase* media = serial;
       
   473 		delete iLogger;
       
   474 		iLogger = media;
       
   475 		WriteDateIntoLog(ETrue);
       
   476 		}
       
   477 	else if (!aMediaSetting.CompareF(KRDebugMedia))
       
   478 		{
       
   479 		CLoggerMediaBase* media = CRDebugWriter::NewL();;
       
   480 		delete iLogger;
       
   481 		iLogger = media;
       
   482 		WriteDateIntoLog(ETrue);
       
   483 		}
       
   484 	else if (!aMediaSetting.CompareF(KOSTv2Media))
       
   485 		{
       
   486 		CLoggerMediaBase* media = COstv2Writer::NewL();;
       
   487 		delete iLogger;
       
   488 		iLogger = media;
       
   489 		WriteDateIntoLog(ETrue);
       
   490 		}
       
   491 	else	//Bad setting in the media file, leave media as is and return.
       
   492 		{
       
   493 		iLogger->LogString(KBadMediaString);
       
   494 		return;	
       
   495 		}
       
   496 	iCurrentMediaSetting = aMediaSetting;
       
   497 	iLogPath = aLogPathSetting;
       
   498 	}
       
   499 
       
   500 void CLogManager::ShutDown()
       
   501 	{
       
   502 	iShutDown = ETrue;
       
   503 	}
       
   504 
       
   505 //////////////////////////////////////////////////////////////////////////////
       
   506 
       
   507 void CFileWriter::LogString(const TDesC8& aString)
       
   508 	{
       
   509 	TPtr8 ptr(iHBuf->Des());
       
   510 	if (ptr.Length()+aString.Length() <=KHeapBufSize)
       
   511 		{
       
   512 		ptr.Append(aString);
       
   513 		}
       
   514 	else
       
   515 		{
       
   516 		TRAPD(err, DoFlushBufferToFileL());
       
   517 		if (err==KErrNone)
       
   518 			{
       
   519 			ptr.Zero();
       
   520 			ptr.Append(aString);
       
   521 			}
       
   522 		else
       
   523 			{
       
   524 			ptr.Zero();
       
   525 			ptr.Append(KUnableToLog);
       
   526 			ptr.Append(aString);
       
   527 			}
       
   528 		}
       
   529 	if (iForceBufferFlushAlways)
       
   530 		{
       
   531 		TRAPD(err, DoFlushBufferToFileL());
       
   532 		ptr.Zero();
       
   533 		if (err!=KErrNone)
       
   534 			{
       
   535 			ptr.Append(KUnableToLog);
       
   536 			}
       
   537 		}
       
   538 
       
   539 	}
       
   540 
       
   541 void CFileWriter::LogBinaryDump(const TDesC8& aBinaryString, const TDesC8& aSubSystem, const TDesC8& aComponent)
       
   542 	{
       
   543 	TRAPD(err, DoLogBinaryDumpL(aBinaryString, aSubSystem, aComponent));
       
   544 	if (err!=KErrNone)
       
   545 		{
       
   546 		LogString(KUnableToLog);
       
   547 		}
       
   548 	}
       
   549 
       
   550 void CFileWriter::DoLogBinaryDumpL(const TDesC8& aBinaryString, const TDesC8& aSubSystem, const TDesC8& aComponent)
       
   551 /**
       
   552  * Place a chunk of raw binary into the log file
       
   553  * @post Opens the output file, flushes the write buffer and then places some tags before writing
       
   554  *   the binary data.
       
   555  */
       
   556 	{
       
   557 	RFile logFile;
       
   558 	TInt err = logFile.Open(iFs, iLogFileName, EFileWrite|EFileShareAny);
       
   559 	if(err == KErrPathNotFound)
       
   560 		{
       
   561 		TName filePath;
       
   562 		filePath.Copy(iLogPath);
       
   563 		User::LeaveIfError(iFs.MkDirAll(filePath));
       
   564 		}
       
   565 	if(err == KErrNotFound || err == KErrPathNotFound)
       
   566 		{
       
   567 		err = logFile.Create(iFs, iLogFileName, EFileWrite|EFileShareAny);
       
   568 		}
       
   569 	User::LeaveIfError(err);
       
   570 	
       
   571 	CleanupClosePushL(logFile);
       
   572 	TInt filePos = 0;
       
   573 	User::LeaveIfError(logFile.Seek(ESeekEnd,filePos));
       
   574 	User::LeaveIfError(logFile.Write(*iHBuf));
       
   575 	TPtr8 ptr(iHBuf->Des());
       
   576 	ptr.Zero();
       
   577 
       
   578 	TUint32 length = static_cast<TUint32>(aBinaryString.Length());
       
   579 	TBuf8<sizeof(TUint32)> lengthString(4);
       
   580 	lengthString[0] = static_cast<TUint8>((length & 0x000000ff) >> 0);
       
   581 	lengthString[1] = static_cast<TUint8>((length & 0x0000ff00) >> 8);
       
   582 	lengthString[2] = static_cast<TUint8>((length & 0x00ff0000) >> 16);
       
   583 	lengthString[3] = static_cast<TUint8>((length & 0xff000000) >> 24);
       
   584 
       
   585 	User::LeaveIfError(logFile.Write(aSubSystem));
       
   586 	User::LeaveIfError(logFile.Write(KTabCharacter));
       
   587 	User::LeaveIfError(logFile.Write(aComponent));
       
   588 	User::LeaveIfError(logFile.Write(KTabCharacter));
       
   589 	User::LeaveIfError(logFile.Write(KTypeIdentifierBinary));
       
   590 	User::LeaveIfError(logFile.Write(KTabCharacter));
       
   591 	User::LeaveIfError(logFile.Write(lengthString));
       
   592 	User::LeaveIfError(logFile.Write(KTabCharacter));
       
   593 	User::LeaveIfError(logFile.Write(aBinaryString));
       
   594 	User::LeaveIfError(logFile.Write(KEolCharacters));
       
   595 	
       
   596 	CleanupStack::PopAndDestroy();	//logFile
       
   597 	//LogString(KEolCharacters);
       
   598 	}
       
   599 
       
   600 void CFileWriter::ClearLogL()
       
   601 	{
       
   602 	User::LeaveIfError(iFs.Delete(iLogFileName));
       
   603 	RFile logFile;
       
   604 	User::LeaveIfError(logFile.Create(iFs, iLogFileName, EFileWrite|EFileShareAny));
       
   605 	logFile.Close();
       
   606 	TPtr8 ptr(iHBuf->Des());
       
   607 	ptr.Zero();
       
   608 	}
       
   609 
       
   610 void CFileWriter::DoFlushBufferToFileL()
       
   611 	{
       
   612 	//Check that the log file exists, if not create a blank one.
       
   613 	RFile logFile;
       
   614 	TBool writePathErrorCode = KErrNone;
       
   615 	TInt err = logFile.Open(iFs, iLogFileName, EFileWrite|EFileShareAny);
       
   616 	if (err==KErrPathNotFound)
       
   617 		{
       
   618 		TName filePath;
       
   619 		filePath.Copy(iLogPath);
       
   620 		User::LeaveIfError(iFs.MkDirAll(filePath));
       
   621 		}
       
   622 	else if (err == KErrBadName || err == KErrNotReady)
       
   623 		{
       
   624 		writePathErrorCode = err;			
       
   625 		// duff pathspec in ini file
       
   626 		TName filePath;
       
   627 		filePath.Copy(KLogDefaultFilePath);
       
   628 		err = iFs.MkDirAll(filePath);
       
   629 		iLogFileName.Copy(KLogDefaultFilePath);
       
   630 		iLogFileName.Append(KLogFileName);			
       
   631 		if (err == KErrAlreadyExists)
       
   632 			{
       
   633 			err = logFile.Open(iFs, iLogFileName, EFileWrite|EFileShareAny);
       
   634 			}
       
   635 		}
       
   636 		
       
   637 	if (err==KErrNotFound||err==KErrPathNotFound||err==KErrBadName||err == KErrNotReady)
       
   638 		{
       
   639 		err = logFile.Create(iFs, iLogFileName, EFileWrite|EFileShareAny);
       
   640 		}
       
   641 	User::LeaveIfError(err);
       
   642 	CleanupClosePushL(logFile);
       
   643 	TInt filePos = 0;
       
   644 	User::LeaveIfError(logFile.Seek(ESeekEnd,filePos));
       
   645 	if (writePathErrorCode != KErrNone)
       
   646 		{
       
   647 		TBuf8<KMaxFinalLogStringLength> tmpBuf;
       
   648 		tmpBuf.Format(KUnableToUpdateMedia,writePathErrorCode);
       
   649 		User::LeaveIfError(logFile.Write(tmpBuf));
       
   650 		}
       
   651 	if (iHBuf)
       
   652 		{
       
   653 		User::LeaveIfError(logFile.Write(*iHBuf));
       
   654 		}
       
   655 	CleanupStack::PopAndDestroy();	//logFile
       
   656 	}
       
   657 
       
   658 void CFileWriter::FlushLogL()
       
   659 	{
       
   660 	DoFlushBufferToFileL();
       
   661 	if (iHBuf)
       
   662 		{
       
   663 		TPtr8 ptr(iHBuf->Des());
       
   664 		ptr.Zero();
       
   665 		}
       
   666 	}
       
   667 
       
   668 void CFileWriter::SetForceFlush(TBool aOn)
       
   669 	{
       
   670 	iForceBufferFlushAlways = aOn;
       
   671 	}
       
   672 
       
   673 void CFileWriter::SetLogPath(const TDesC8& aLogPathSetting)
       
   674 	{
       
   675 	iLogPath.Copy(aLogPathSetting);
       
   676 	
       
   677 	//the path may be reconfigured, so check for '\' 
       
   678 	//as its assumed to be at the end already
       
   679 	TPtr8 iTempStr = iLogPath.RightTPtr(1);	//get last
       
   680 	TPtr8 iTempExt = iLogPath.RightTPtr(4);	//get last 4
       
   681 
       
   682 	if( iTempStr == KLogPathTree)
       
   683 		{
       
   684 			//ends with '\', so ok to copy
       
   685 			iLogFileName.Copy(iLogPath);
       
   686 			iLogFileName.Append(KLogFileName);
       
   687 		}	
       
   688 	else if(iTempExt.Find(KLogFileExt)==KErrNotFound)
       
   689 		{
       
   690 			//no file extension already set, so its just path
       
   691 			iLogPath.Append(KLogPathTree);
       
   692 			iLogFileName.Copy(iLogPath);
       
   693 			iLogFileName.Append(KLogFileName);
       
   694 		}
       
   695 	else
       
   696 		{
       
   697 			//already has all we need
       
   698 			iLogFileName.Copy(iLogPath);
       
   699 		}
       
   700 	}
       
   701 
       
   702 CFileWriter* CFileWriter::NewL()
       
   703 	{
       
   704 	CFileWriter* self = new(ELeave) CFileWriter;
       
   705 	CleanupStack::PushL(self);
       
   706 	self->ConstructL();
       
   707 	CleanupStack::Pop(self);
       
   708 	return self;
       
   709 	}
       
   710 
       
   711 void CFileWriter::ConstructL()
       
   712 	{
       
   713 	User::LeaveIfError(iFs.Connect());
       
   714 	//Create our buffer for logging into, at zero length but specify a maximum.
       
   715 	iHBuf = HBufC8::NewL(KHeapBufSize);
       
   716 	iForceBufferFlushAlways = EFalse;
       
   717 	iLogPath.Copy(KLogDefaultFilePath);
       
   718 	iLogFileName.Copy(iLogPath);
       
   719 	iLogFileName.Append(KLogFileName);
       
   720 	}
       
   721 
       
   722 CFileWriter::~CFileWriter()
       
   723 	{
       
   724 	// Don't attempt flushing when it's an OOM leave from NewL()
       
   725 	if (iHBuf)
       
   726 		{
       
   727 		TRAP_IGNORE(CFileWriter::FlushLogL());	//Ignore error. Nothing we can do now.
       
   728 		delete iHBuf;
       
   729 		}
       
   730 	iFs.Close();
       
   731 	}
       
   732 
       
   733 ///////////////////////////////////////////////////////////////////////
       
   734 
       
   735 CSerialWriter* CSerialWriter::NewL()
       
   736 	{
       
   737 	CSerialWriter* self = new(ELeave) CSerialWriter;
       
   738 	CleanupStack::PushL(self);
       
   739 	self->ConstructL();
       
   740 	CleanupStack::Pop(self);
       
   741 	return self;
       
   742 	}
       
   743 
       
   744 void CSerialWriter::ConstructL()
       
   745 	{
       
   746 	User::LeaveIfError(iTimeoutTimer.CreateLocal());
       
   747 	}
       
   748 
       
   749 TInt CSerialWriter::LoadDevices()
       
   750 	{
       
   751 	// load the device drivers
       
   752 	TInt result = User::LoadPhysicalDevice(PDD_NAME);
       
   753 	if ((result != KErrNone) && (result != KErrAlreadyExists))
       
   754 		{
       
   755 		 return result;
       
   756 		}
       
   757 
       
   758 	result = User::LoadLogicalDevice(LDD_NAME);
       
   759 	if ((result != KErrNone) && (result != KErrAlreadyExists))
       
   760 		{
       
   761 		return result;
       
   762 		}
       
   763 
       
   764 	return KErrNone;
       
   765 	}
       
   766 
       
   767 
       
   768 TInt CSerialWriter::OpenPort(TInt aPort)
       
   769 	{
       
   770 	return iSerialPort.Open(aPort);
       
   771 	}
       
   772 
       
   773 TInt CSerialWriter::SetPortConfig()
       
   774 	{
       
   775 	TCommConfig tComConfig;
       
   776 	TCommConfigV01 &tComConfigV = tComConfig();
       
   777 	iSerialPort.Config(tComConfig);
       
   778 	tComConfigV.iRate=KFloggerSerialRate;
       
   779 	tComConfigV.iDataBits=EData8;
       
   780 	tComConfigV.iStopBits=EStop1;
       
   781 	tComConfigV.iParity=EParityNone;
       
   782 	tComConfigV.iHandshake=0;
       
   783 	tComConfigV.iFifo = EFifoEnable;
       
   784 	return iSerialPort.SetConfig(tComConfig);
       
   785 	}
       
   786 
       
   787 
       
   788 
       
   789 CSerialWriter::~CSerialWriter()
       
   790 	{
       
   791 	iTimeoutTimer.Close();
       
   792 	iSerialPort.Close();
       
   793 	}
       
   794 
       
   795 void CSerialWriter::ClearLogL()
       
   796 /**
       
   797  * @note: Nothing to do for serial
       
   798  */
       
   799 	{}
       
   800 
       
   801 void CSerialWriter::FlushLogL()
       
   802 /**
       
   803  * @note: Nothing to do for serial
       
   804  */
       
   805 	{}
       
   806 
       
   807 void CSerialWriter::SetForceFlush(TBool)
       
   808 /**
       
   809  * @note: Nothing to do for serial.
       
   810  */
       
   811 	{
       
   812 	}
       
   813 
       
   814 
       
   815 void CSerialWriter::LogString(const TDesC8& aString)
       
   816 	{
       
   817 	//iInvalidcounter is used to dump packets if we fail to get a write through before the
       
   818 	//timer expires. It stops us getting backed up too much if there's a problem.
       
   819 	if (iInvalidCounter==0)
       
   820 		{
       
   821 		TRequestStatus writeStatus(KRequestPending);
       
   822 		TRequestStatus timeoutStatus(KRequestPending);
       
   823 		iSerialPort.Write(writeStatus, aString, aString.Length());
       
   824 		iTimeoutTimer.After(timeoutStatus, 
       
   825 			TTimeIntervalMicroSeconds32(KSerialTimeoutInMicroSecs));
       
   826 		User::WaitForRequest(writeStatus, timeoutStatus);
       
   827 		if (writeStatus==KRequestPending)
       
   828 			{//OK, still not completed, better cancel send.
       
   829 			iSerialPort.WriteCancel();
       
   830 			iInvalidCounter=KSerialRetryCount;
       
   831 			}
       
   832 		else
       
   833 			{
       
   834 			iTimeoutTimer.Cancel();
       
   835 			}
       
   836 		User::WaitForAnyRequest();
       
   837 		}
       
   838 	else
       
   839 		--iInvalidCounter;
       
   840 	}
       
   841 
       
   842 void CSerialWriter::LogBinaryDump(const TDesC8& aBinaryString, const TDesC8& aSubSystem, const TDesC8& aComponent)
       
   843 	{
       
   844 	TUint32 length = static_cast<TUint32>(aBinaryString.Length());
       
   845 	TBuf8<sizeof(TUint32)> lengthString(4);
       
   846 	lengthString[0] = static_cast<TUint8>((length & 0x000000ff) >> 0);
       
   847 	lengthString[1] = static_cast<TUint8>((length & 0x0000ff00) >> 8);
       
   848 	lengthString[2] = static_cast<TUint8>((length & 0x00ff0000) >> 16);
       
   849 	lengthString[3] = static_cast<TUint8>((length & 0xff000000) >> 24);
       
   850 
       
   851 	LogString(aSubSystem);
       
   852 	LogString(KTabCharacter);
       
   853 	LogString(aComponent);
       
   854 	LogString(KTabCharacter);
       
   855 	LogString(KTypeIdentifierBinary);
       
   856 	LogString(KTabCharacter);
       
   857 	LogString(lengthString);
       
   858 	LogString(KTabCharacter);
       
   859 	LogString(aBinaryString);
       
   860 	LogString(KEolCharacters);
       
   861 	}
       
   862 
       
   863 ///////////////////////////////////////////////////////////////////////////////////////////////////
       
   864 
       
   865 //Don't strictly need a NewL. Doing it for consistency.
       
   866 CRDebugWriter* CRDebugWriter::NewL()
       
   867 	{
       
   868 	return new(ELeave) CRDebugWriter;
       
   869 	}
       
   870 
       
   871 CRDebugWriter::~CRDebugWriter()
       
   872 	{
       
   873 	}
       
   874 
       
   875 void CRDebugWriter::ClearLogL()
       
   876 /**
       
   877  * @note: Nothing to do for RDebug
       
   878  */
       
   879 	{}
       
   880 
       
   881 void CRDebugWriter::FlushLogL()
       
   882 /**
       
   883  * @note: Nothing to do for RDebug
       
   884  */
       
   885 	{}
       
   886 
       
   887 void CRDebugWriter::SetForceFlush(TBool)
       
   888 /**
       
   889  * @note: Nothing to do for RDebug.
       
   890  */
       
   891 	{
       
   892 	}
       
   893 
       
   894 
       
   895 void CRDebugWriter::LogString(const TDesC8& aString)
       
   896 	{
       
   897 	
       
   898 	//RDebug truncates strings longer than a certain size
       
   899 	//To work around this we chop our string into palatable chunks
       
   900 	//and log those individually
       
   901 	
       
   902 	const TUint8 *p = aString.Ptr();
       
   903 	TInt bytesSent(0);
       
   904 	TInt totalToSend = aString.Length();
       
   905 	TInt length(0);
       
   906 	
       
   907 	do
       
   908 		{
       
   909 		bytesSent += KRDebugLimit;
       
   910 		if (bytesSent < totalToSend)
       
   911 			{
       
   912 			length = KRDebugLimit;
       
   913 			}
       
   914 		else
       
   915 			{
       
   916 			length = totalToSend - bytesSent + KRDebugLimit;
       
   917 			}
       
   918 		
       
   919 		TPtrC8 ptr(p,length);
       
   920 		RDebug::RawPrint(ptr);		
       
   921 		p += KRDebugLimit;
       
   922 		}
       
   923 	while(bytesSent < totalToSend);
       
   924 	}
       
   925 
       
   926 
       
   927 void CRDebugWriter::LogBinaryDump(const TDesC8& aBinaryString, const TDesC8& aSubSystem, const TDesC8& aComponent)
       
   928 	{
       
   929 	TUint32 length = static_cast<TUint32>(aBinaryString.Length());
       
   930 	TBuf8<sizeof(TUint32)> lengthString(4);
       
   931 	lengthString[0] = static_cast<TUint8>((length & 0x000000ff) >> 0);
       
   932 	lengthString[1] = static_cast<TUint8>((length & 0x0000ff00) >> 8);
       
   933 	lengthString[2] = static_cast<TUint8>((length & 0x00ff0000) >> 16);
       
   934 	lengthString[3] = static_cast<TUint8>((length & 0xff000000) >> 24);
       
   935 
       
   936 	RDebug::RawPrint(aSubSystem);
       
   937 	RDebug::RawPrint(KTabCharacter);
       
   938 	RDebug::RawPrint(aComponent);
       
   939 	RDebug::RawPrint(KTabCharacter);
       
   940 	RDebug::RawPrint(KTypeIdentifierBinary);
       
   941 	RDebug::RawPrint(KTabCharacter);
       
   942 	RDebug::RawPrint(lengthString);
       
   943 	RDebug::RawPrint(KTabCharacter);
       
   944 	LogString(aBinaryString);	
       
   945 	RDebug::RawPrint(KEolCharacters);
       
   946 
       
   947 	}
       
   948 
       
   949 
       
   950 ///////////////////////////////////////////////////////////////////////
       
   951 
       
   952 #if defined (__WINS__)
       
   953 #include <emulator.h>
       
   954 
       
   955 CDebugPortProtocol* CDebugPortProtocol::NewL()
       
   956 	{
       
   957 	CDebugPortProtocol* protocol = new(ELeave) CDebugPortProtocol;
       
   958 	CleanupStack::PushL(protocol);
       
   959 	protocol->ConstructL();
       
   960 	CleanupStack::Pop(protocol);
       
   961 	return protocol;
       
   962 	}
       
   963 	
       
   964 void CDebugPortProtocol::ConstructL()
       
   965 	{
       
   966 	iDebugWriter = CDebugPortWriter::NewL();
       
   967 	}
       
   968 	
       
   969 CDebugPortProtocol::~CDebugPortProtocol()
       
   970 	{
       
   971 	delete iDebugWriter;
       
   972 	}
       
   973 void CDebugPortProtocol::ClearLog(const TFullName& /*aName*/)
       
   974 	{
       
   975 	}
       
   976 void CDebugPortProtocol::SetTimeL(const TTime& /*aTime*/)
       
   977 	{
       
   978 	}
       
   979 void CDebugPortProtocol::LogString(const TDesC8& aLogString, const TDesC8& aSubSystem, const TDesC8& aComponent, const TThreadId& aThreadId)
       
   980 	{
       
   981 	TBuf8<KMaxFinalLogStringLength> buf;
       
   982 	buf.Append(aSubSystem);
       
   983 	buf.Append(KTabCharacter);
       
   984 	buf.Append(aComponent);
       
   985 	buf.Append(KTabCharacter);
       
   986 	buf.Append(KTypeIdentifierAscii);
       
   987 	buf.Append(KTabCharacter);
       
   988 	buf.AppendNum(aThreadId, EHex);
       
   989 	buf.Append(KTabCharacter);
       
   990 	buf.Append(aLogString);
       
   991 	// check whether last two bytes of string are eol chars, since some lines have cr/lf, some don't
       
   992 	TPtr8 ptr(&buf[buf.Length()-2], 2, 2);
       
   993 	if (ptr.Compare(KEolCharacters) !=0 )
       
   994 		{
       
   995 		buf.Append(KEolCharacters);
       
   996 		}
       
   997 	iDebugWriter->LogString(buf);
       
   998 	}
       
   999 void CDebugPortProtocol::LogBinaryDump(const TDesC8& aBinaryString, const TDesC8& aSubSystem, const TDesC8& aComponent)
       
  1000 	{
       
  1001 	iDebugWriter->LogBinaryDump(aBinaryString, aSubSystem, aComponent);
       
  1002 	}
       
  1003 void CDebugPortProtocol::LogComment(const TDesC8& aComment)
       
  1004 	{
       
  1005 	iDebugWriter->LogString(aComment);
       
  1006 	}
       
  1007 void CDebugPortProtocol::MediaUpdate(const TDesC8& /*aMediaSetting*/, const TBool /*aForceFlushOn*/, const TDesC8& /*aLogPathSetting*/)
       
  1008 	{
       
  1009 	}
       
  1010 void CDebugPortProtocol::ShutDown()
       
  1011 	{
       
  1012 	}
       
  1013 
       
  1014 ///////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1015 
       
  1016 CDebugPortWriter* CDebugPortWriter::NewL()
       
  1017 	{
       
  1018 	return new(ELeave) CDebugPortWriter;
       
  1019 	}
       
  1020 	
       
  1021 
       
  1022 void CDebugPortWriter::LogString(const TDesC8& aString)
       
  1023 	{
       
  1024 	char str[Win32DisplayStringLengthMax];
       
  1025 	int len = Min(sizeof(str) - 1, aString.Length());
       
  1026 	Mem::Copy(str, aString.Ptr(), len);
       
  1027 	str[len] = '\0';
       
  1028 	Emulator::Lock();
       
  1029 	::OutputDebugStringA(str);
       
  1030 	Emulator::Unlock();
       
  1031 	}
       
  1032 void CDebugPortWriter::ClearLogL()
       
  1033 	{
       
  1034 	}
       
  1035 void CDebugPortWriter::FlushLogL()
       
  1036 	{
       
  1037 	}
       
  1038 void CDebugPortWriter::LogBinaryDump(const TDesC8& /*aBinaryString*/, const TDesC8& /*aSubSystem*/, const TDesC8& /*aComponent*/)
       
  1039 	{
       
  1040 	}
       
  1041 void CDebugPortWriter::SetForceFlush(const TBool /*aOn*/)
       
  1042 	{
       
  1043 	}
       
  1044 
       
  1045 #endif  //(__WINS__)