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