--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/traceservices/commsdebugutility/SSVR/comsdbgwriter.cpp Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,1045 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implements the Flogger server side data writing
+//
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include "comsdbgwriter.h"
+#include "comsdbgmessages.h"
+
+
+const TInt KHeapBufSize = 50000; // Maximum that the file buffer can grow to limit its impact somewhat
+
+
+// RDebug will truncate strings longer than the limit below
+const TInt KRDebugLimit = 0x100;
+
+
+// source strings, lengths and offsets
+_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.
+_LIT8(KDateChangedString,"# Date is now: dd/mm/yyyy.\r\n"); ///< Format specifier for subsequent date changes
+const TInt KLogStartedStringLength = 50;
+const TInt KLogStartedDayOffset = 20;
+const TInt KLogStartedMonthOffset = 23;
+const TInt KLogStartedYearOffset = 26;
+
+_LIT8(KUnableToLog, "#Logs lost since log file couldn't be written to");
+
+_LIT8(KClearLogString, "#Clear Log called by ");
+const TInt KClearLogStringLength = 21;
+
+_LIT8(KEolCharacters, "\r\n");
+const TInt KEolCharactersLength = 2;
+
+_LIT8(KLogPathTree,"\\");
+_LIT8(KLogFileExt,".");
+
+//Below const is... log string + 2 tags + 8 for the thread id + 3 tabs + EOL characters.
+const TInt KMaxFinalLogStringLength = KLogBufferSize+2*KMaxTagLength+8+3+KEolCharactersLength;
+
+_LIT8(KBadMediaString, "#Bad media setting in ini file.\r\n");
+_LIT8(KUnableToUpdateMedia, "#Unable to update logging media. Err code: %d\r\n");
+_LIT8(KUnableToLoadSerialDevices, "#Unable to load the LDD or PDD required for serial. Err code: %d\r\n");
+_LIT8(KUnableToOpenSerial, "#Unable to open the serial port. Err code: %d\r\n");
+_LIT8(KUnableToSetSerialConfig, "#Could not set serial port configuration after opening port. Err code: %d\r\n");
+
+// source characters
+_LIT8(KTabCharacter, "\t");
+_LIT8(KTypeIdentifierAscii, "a");
+_LIT8(KTypeIdentifierBinary, "b");
+
+// serial specs
+const TBps KFloggerSerialRate = EBps115200;
+const TInt KSerialRetryCount = 50;
+const TInt KSerialTimeoutInMicroSecs = 100000;
+
+// serial ports
+const TInt KSerialPort1 = 0;
+#if defined (__WINS__)
+const TInt KSerialPort2OnEmulator = 1;
+#else
+const TInt KSerialPort2OnTarget = 2;
+#endif
+
+#if defined (__WINS__)
+#define PDD_NAME _L("ECDRV.PDD")
+#define LDD_NAME _L("ECOMM.LDD")
+#else
+#define PDD_NAME _L("EUART1")
+#define LDD_NAME _L("ECOMM")
+#endif
+
+
+// log file specs
+_LIT(KLogFileName, "log.txt");
+_LIT(KLogDefaultFilePath, "C:\\logs\\");
+
+
+const TUint KZeroDate = 0; ///< The day to count forward from when determining date roll.
+const TUint KSecondsToWriteTimestampOnNoActivity = 5;
+
+#if defined (__WINS__)
+const TInt Win32DisplayStringLengthMax = 1024;
+#endif
+
+
+
+
+CLogManager* CLogManager::NewL(MLogArrayAccess& aArrayAccess)
+ {
+ CLogManager* self = new(ELeave) CLogManager(aArrayAccess);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+CLogManager::CLogManager(MLogArrayAccess& aArrayAccess)
+: iArrayAccess(aArrayAccess), iTimeString(KTimeFormat)
+{}
+
+CLogManager::~CLogManager()
+ {
+ delete iLogger;
+ }
+
+void CLogManager::ConstructL()
+/*
+ * Set the initial media to file and write there until the server has told us
+ * which media is in the ini file.
+ * Write the log started and date message.
+ */
+ {
+ iLogger = CFileWriter::NewL(); //File writer by default
+ iCurrentMediaSetting = KFileMedia;
+ iLoggingEnabled = EFalse;
+ }
+
+TInt CLogManager::ThreadEntryPoint(TAny* aPtr)
+ {
+ __UHEAP_MARK;
+
+ MLogArrayAccess* arrayAccess = static_cast<MLogArrayAccess*> (aPtr);
+
+ CTrapCleanup* cleanupStack = CTrapCleanup::New();
+ if (cleanupStack==NULL)
+ {
+ return KErrNoMemory;
+ }
+
+ TRAPD(err, CLogManager::DoRunThreadL(*arrayAccess));
+
+ delete cleanupStack;
+
+ __UHEAP_MARKEND;
+
+ return err;
+ }
+
+void CLogManager::DoRunThreadL(MLogArrayAccess& aArrayAccess)
+ {
+ CLogManager* self = CLogManager::NewL(aArrayAccess);
+ self->DoStart();
+ delete self;
+ }
+
+void CLogManager::DoStart()
+/**
+ * Second/consumer/slave/draining/dequeuer thread main loop.
+ * @note Continuously takes the log queue top message and processes it. Blocks on the "Get" if no messages.
+ * @note Completes when a shutdown message is processed from the queue. This message sets "iShutDown".
+ */
+ {
+ CLogMessageBase * message = NULL;
+
+ TInt ret = KErrNone;
+ RThread::Rendezvous(ret);
+
+ FOREVER
+ {
+ iArrayAccess.GetFirstMessageAndTakeOwnership(message);
+ __ASSERT_ALWAYS(message, User::Panic(KFloggerServerPanic, ENullMessageInArray));
+ message->Invoke(*this);
+ delete message;
+ // GetFirstMessage waits on the request semaphore, so to balance these each
+ // time a message is processed we must then signal the completion semaphore
+ // when in synchronous mode
+ iArrayAccess.SignalCompletionSemaphore();
+ if (iShutDown)
+ {
+ break;
+ }
+ }
+ }
+
+void CLogManager::WriteDateIntoLog(TBool firstTime)
+/**
+ * Write the date straight to the log output
+ * @param firstTime If ETrue then write a "log started" otherwise write a "date change" msg
+ */
+ {
+ if (!iLoggingEnabled)
+ {
+ return;
+ }
+ //Put a date stamp for when we've started logging
+ //Can't use TTime::FormatL since it gives unicode and we want narrow.
+ TTime time;
+ TBuf8<KLogStartedStringLength> logDateString;
+ time.HomeTime();
+ TDateTime dateTime(time.DateTime());
+ if (firstTime)
+ {
+ logDateString.Copy(KLogStartedString);
+ }
+ else
+ {
+ logDateString.Copy(KDateChangedString);
+ }
+ TBuf8<2> holdingBuf;
+ holdingBuf.NumFixedWidth(dateTime.Day()+1, EDecimal, 2);
+ logDateString.Replace(KLogStartedDayOffset,2,holdingBuf);
+ holdingBuf.NumFixedWidth(dateTime.Month()+1, EDecimal, 2);
+ logDateString.Replace(KLogStartedMonthOffset,2,holdingBuf);
+ TBuf8<4> holdingBuf2;
+ holdingBuf2.NumFixedWidth(dateTime.Year(), EDecimal, 4);
+ logDateString.Replace(KLogStartedYearOffset,4,holdingBuf2);
+ iLogger->LogString(logDateString);
+ }
+
+void CLogManager::ClearLog(const TFullName& aName)
+ {
+ if (!iLoggingEnabled)
+ {
+ return;
+ }
+ TRAP_IGNORE(iLogger->ClearLogL()); //if there is an error there is nothing we can do.
+ TBuf8<KMaxFullName+KClearLogStringLength+KEolCharactersLength> buf(KClearLogString);
+ buf.Append(aName);
+ buf.Append(KEolCharacters);
+ iLogger->LogString(buf);
+ WriteDateIntoLog(ETrue);
+ iTicksSinceLastLog=0;
+ }
+
+void CLogManager::SetTimeL(const TTime& aTime)
+ {
+ if (!iLoggingEnabled)
+ {
+ return;
+ }
+ //check whether date has rolled and write it to log if necessary
+ TTime currentMicrosecs;
+ TTimeIntervalDays newDate;
+ currentMicrosecs.HomeTime();
+ TTime zeroDate = TTime(TInt64(KZeroDate));
+ newDate = currentMicrosecs.DaysFrom(zeroDate);
+ if (newDate > iCurrentDate)
+ {
+ WriteDateIntoLog(EFalse);
+ iCurrentDate = newDate;
+ }
+
+ //Print the time to the log
+ //Have to do this stuff manually since TTime only provides Unicode formating
+ //which is not what we want.
+ // We format this each second regardless of whether it is used so that it is ready for use
+ // if a client logs since in normal use it would be rare for flogger not to log something each second.
+ TDateTime dateTime(aTime.DateTime());
+ TBuf8<2> holdingBuf;
+ holdingBuf.NumFixedWidth(dateTime.Hour(), EDecimal, 2);
+ iTimeString.Replace(KHourOffset,2,holdingBuf);
+ holdingBuf.NumFixedWidth(dateTime.Minute(), EDecimal, 2);
+ iTimeString.Replace(KMinuteOffset,2,holdingBuf);
+ holdingBuf.NumFixedWidth(dateTime.Second(), EDecimal, 2);
+ iTimeString.Replace(KSecondOffset,2,holdingBuf);
+ if (iTicksSinceLastLog++ < KSecondsToWriteTimestampOnNoActivity)
+ {
+ iLogger->LogString(iTimeString);
+ iLogger->FlushLogL();
+ }
+
+ }
+
+void CLogManager::LogString(const TDesC8& aLogString, const TDesC8& aSubSystem, const TDesC8& aComponent, const TThreadId& aThreadId)
+ {
+ if (!iLoggingEnabled)
+ {
+ return;
+ }
+ if (iTicksSinceLastLog > KSecondsToWriteTimestampOnNoActivity)
+ {
+ iLogger->LogString(iTimeString);
+ }
+ iTicksSinceLastLog=0;
+
+ TBuf8<KMaxFinalLogStringLength> buf;
+ buf.Append(aSubSystem);
+ buf.Append(KTabCharacter);
+ buf.Append(aComponent);
+ buf.Append(KTabCharacter);
+ buf.Append(KTypeIdentifierAscii);
+ buf.Append(KTabCharacter);
+ buf.AppendNum(aThreadId, EHex);
+ buf.Append(KTabCharacter);
+ buf.Append(aLogString);
+ // check whether last two bytes of string are eol chars, since some lines have cr/lf, some don't
+ TPtr8 ptr(&buf[buf.Length()-2], 2, 2);
+ if (ptr.Compare(KEolCharacters)!=0)
+ {
+ buf.Append(KEolCharacters);
+ }
+ iLogger->LogString(buf);
+ }
+
+void CLogManager::LogBinaryDump(const TDesC8& aBinaryString, const TDesC8& aSubSystem, const TDesC8& aComponent)
+ {
+ iLogger->LogBinaryDump(aBinaryString, aSubSystem, aComponent);
+ }
+
+void CLogManager::LogComment(const TDesC8& aComment)
+ {
+ if (iTicksSinceLastLog > KSecondsToWriteTimestampOnNoActivity)
+ {
+ iLogger->LogString(iTimeString);
+ }
+ iTicksSinceLastLog=0;
+
+ iLogger->LogString(aComment);
+ }
+
+void CLogManager::MediaUpdate(const TDesC8& aMediaSetting, const TBool aForceFlush, const TDesC8& aLogPathSetting)
+ {
+ TRAPD(err, DoMediaUpdateL(aMediaSetting,aForceFlush, aLogPathSetting));
+ if (err!=KErrNone)
+ {
+ TBuf8<KMaxFinalLogStringLength> buf;
+ buf.Format(KUnableToUpdateMedia,err);
+ iLogger->LogString(buf);
+ }
+ }
+
+void CLogManager::DoMediaUpdateL(const TDesC8& aMediaSetting,const TBool aForceFlush, const TDesC8& aLogPathSetting)
+ {
+ //We should NEVER have no media selected, media is set on construction
+ //and there should always be something set up.
+ __ASSERT_ALWAYS(iLogger, User::Panic(KFloggerServerPanic, ENoLoggingMediaSetUp));
+
+ if (aMediaSetting.Length() == 0)
+ {
+ return;
+ }
+
+ // if the ini file has been opened, the media setting will be either the default
+ // or some other string so we can allow logging. If we are only opening media now, output extra info.
+ TTime currentMicrosecs;
+ currentMicrosecs.HomeTime();
+ iCurrentDate = currentMicrosecs.DaysFrom(TTime(TInt64(KZeroDate)));
+
+ if (!iLoggingEnabled)
+ {
+ iLoggingEnabled = ETrue;
+ WriteDateIntoLog(ETrue);
+ }
+
+ //Media update is a best effort, if it fails we keep
+ //logging to the old media
+ //If bad media in ini file, carry on with old media and post message in log
+
+ if (aMediaSetting.CompareF(iCurrentMediaSetting)==0 && aLogPathSetting.CompareF(iLogPath) == 0)
+ {
+ //Media hasn't changed, so update flush status only
+ // ForceFlushing as far as media is concerned only applies to file since
+ // serial has no such buffer which needs flushing.
+ iLogger->SetForceFlush(aForceFlush);
+ return;
+ }
+ if (!aMediaSetting.CompareF(KFileMedia))
+ {
+ CLoggerMediaBase* media = CFileWriter::NewL();
+ delete iLogger;
+ iLogger = media;
+ // ForceFlushing only applies to file since serial has no such buffer
+ iLogger->SetForceFlush(aForceFlush);
+ if(aLogPathSetting.Length() != 0)
+ {
+ (static_cast<CFileWriter*>(iLogger))->SetLogPath(aLogPathSetting);
+ WriteDateIntoLog(ETrue);
+ }
+ }
+ else if (!aMediaSetting.CompareF(KSerial1Media))
+ {
+ // lots of things can go wrong when constructing the serial, so
+ // we set it up in stages, and log here if an error
+ // If we get an error in NewL - just let generic error given by
+ // SetMedia cover it
+ //CLoggerMediaBase* media = CSerialWriter::NewL();
+ CSerialWriter* serial = CSerialWriter::NewL();
+
+ TInt res = serial->LoadDevices();
+ if (res != KErrNone)
+ {
+ TBuf8<KMaxFinalLogStringLength> buf;
+ buf.Format(KUnableToLoadSerialDevices,res);
+ iLogger->LogString(buf);
+ delete serial;
+ User::Leave(res);
+ }
+ res = serial->OpenPort(KSerialPort1);
+ if (res != KErrNone)
+ {
+ TBuf8<KMaxFinalLogStringLength> buf;
+ buf.Format(KUnableToOpenSerial,res);
+ iLogger->LogString(buf);
+ delete serial;
+ User::Leave(res);
+ }
+
+ res = serial->SetPortConfig();
+ if (res != KErrNone)
+ {
+ TBuf8<KMaxFinalLogStringLength> buf;
+ buf.Format(KUnableToSetSerialConfig,res);
+ iLogger->LogString(buf);
+ delete serial;
+ User::Leave(res);
+ }
+ CLoggerMediaBase* media = serial;
+ delete iLogger;
+ iLogger = media;
+ WriteDateIntoLog(ETrue);
+ }
+ else if (!aMediaSetting.CompareF(KSerial2Media))
+ {
+ // lots of things can go wrong when constructing the serial, so
+ // we set it up in stages, and log here if an error.
+ // If we get an error in NewL - just let generic error given by
+ // SetMedia cover it
+
+ CSerialWriter* serial = CSerialWriter::NewL();
+
+ TInt res = serial->LoadDevices();
+ if (res != KErrNone)
+ {
+ TBuf8<KMaxFinalLogStringLength> buf;
+ buf.Format(KUnableToLoadSerialDevices,res);
+ iLogger->LogString(buf);
+ delete serial;
+ User::Leave(res);
+ }
+
+ #if defined (__WINS__)
+ res = serial->OpenPort(KSerialPort2OnEmulator);
+ #else
+ res = serial->OpenPort(KSerialPort2OnTarget);
+ #endif
+
+ if (res != KErrNone)
+ {
+ TBuf8<KMaxFinalLogStringLength> buf;
+ buf.Format(KUnableToOpenSerial,res);
+ iLogger->LogString(buf);
+ delete serial;
+ User::Leave(res);
+ }
+
+ res = serial->SetPortConfig();
+ if (res != KErrNone)
+ {
+ TBuf8<KMaxFinalLogStringLength> buf;
+ buf.Format(KUnableToSetSerialConfig,res);
+ iLogger->LogString(buf);
+ delete serial;
+ User::Leave(res);
+ }
+ CLoggerMediaBase* media = serial;
+ delete iLogger;
+ iLogger = media;
+ WriteDateIntoLog(ETrue);
+ }
+ else if (!aMediaSetting.CompareF(KRDebugMedia))
+ {
+ CLoggerMediaBase* media = CRDebugWriter::NewL();;
+ delete iLogger;
+ iLogger = media;
+ WriteDateIntoLog(ETrue);
+ }
+ else if (!aMediaSetting.CompareF(KOSTv2Media))
+ {
+ CLoggerMediaBase* media = COstv2Writer::NewL();;
+ delete iLogger;
+ iLogger = media;
+ WriteDateIntoLog(ETrue);
+ }
+ else //Bad setting in the media file, leave media as is and return.
+ {
+ iLogger->LogString(KBadMediaString);
+ return;
+ }
+ iCurrentMediaSetting = aMediaSetting;
+ iLogPath = aLogPathSetting;
+ }
+
+void CLogManager::ShutDown()
+ {
+ iShutDown = ETrue;
+ }
+
+//////////////////////////////////////////////////////////////////////////////
+
+void CFileWriter::LogString(const TDesC8& aString)
+ {
+ TPtr8 ptr(iHBuf->Des());
+ if (ptr.Length()+aString.Length() <=KHeapBufSize)
+ {
+ ptr.Append(aString);
+ }
+ else
+ {
+ TRAPD(err, DoFlushBufferToFileL());
+ if (err==KErrNone)
+ {
+ ptr.Zero();
+ ptr.Append(aString);
+ }
+ else
+ {
+ ptr.Zero();
+ ptr.Append(KUnableToLog);
+ ptr.Append(aString);
+ }
+ }
+ if (iForceBufferFlushAlways)
+ {
+ TRAPD(err, DoFlushBufferToFileL());
+ ptr.Zero();
+ if (err!=KErrNone)
+ {
+ ptr.Append(KUnableToLog);
+ }
+ }
+
+ }
+
+void CFileWriter::LogBinaryDump(const TDesC8& aBinaryString, const TDesC8& aSubSystem, const TDesC8& aComponent)
+ {
+ TRAPD(err, DoLogBinaryDumpL(aBinaryString, aSubSystem, aComponent));
+ if (err!=KErrNone)
+ {
+ LogString(KUnableToLog);
+ }
+ }
+
+void CFileWriter::DoLogBinaryDumpL(const TDesC8& aBinaryString, const TDesC8& aSubSystem, const TDesC8& aComponent)
+/**
+ * Place a chunk of raw binary into the log file
+ * @post Opens the output file, flushes the write buffer and then places some tags before writing
+ * the binary data.
+ */
+ {
+ RFile logFile;
+ TInt err = logFile.Open(iFs, iLogFileName, EFileWrite|EFileShareAny);
+ if(err == KErrPathNotFound)
+ {
+ TName filePath;
+ filePath.Copy(iLogPath);
+ User::LeaveIfError(iFs.MkDirAll(filePath));
+ }
+ if(err == KErrNotFound || err == KErrPathNotFound)
+ {
+ err = logFile.Create(iFs, iLogFileName, EFileWrite|EFileShareAny);
+ }
+ User::LeaveIfError(err);
+
+ CleanupClosePushL(logFile);
+ TInt filePos = 0;
+ User::LeaveIfError(logFile.Seek(ESeekEnd,filePos));
+ User::LeaveIfError(logFile.Write(*iHBuf));
+ TPtr8 ptr(iHBuf->Des());
+ ptr.Zero();
+
+ TUint32 length = static_cast<TUint32>(aBinaryString.Length());
+ TBuf8<sizeof(TUint32)> lengthString(4);
+ lengthString[0] = static_cast<TUint8>((length & 0x000000ff) >> 0);
+ lengthString[1] = static_cast<TUint8>((length & 0x0000ff00) >> 8);
+ lengthString[2] = static_cast<TUint8>((length & 0x00ff0000) >> 16);
+ lengthString[3] = static_cast<TUint8>((length & 0xff000000) >> 24);
+
+ User::LeaveIfError(logFile.Write(aSubSystem));
+ User::LeaveIfError(logFile.Write(KTabCharacter));
+ User::LeaveIfError(logFile.Write(aComponent));
+ User::LeaveIfError(logFile.Write(KTabCharacter));
+ User::LeaveIfError(logFile.Write(KTypeIdentifierBinary));
+ User::LeaveIfError(logFile.Write(KTabCharacter));
+ User::LeaveIfError(logFile.Write(lengthString));
+ User::LeaveIfError(logFile.Write(KTabCharacter));
+ User::LeaveIfError(logFile.Write(aBinaryString));
+ User::LeaveIfError(logFile.Write(KEolCharacters));
+
+ CleanupStack::PopAndDestroy(); //logFile
+ //LogString(KEolCharacters);
+ }
+
+void CFileWriter::ClearLogL()
+ {
+ User::LeaveIfError(iFs.Delete(iLogFileName));
+ RFile logFile;
+ User::LeaveIfError(logFile.Create(iFs, iLogFileName, EFileWrite|EFileShareAny));
+ logFile.Close();
+ TPtr8 ptr(iHBuf->Des());
+ ptr.Zero();
+ }
+
+void CFileWriter::DoFlushBufferToFileL()
+ {
+ //Check that the log file exists, if not create a blank one.
+ RFile logFile;
+ TBool writePathErrorCode = KErrNone;
+ TInt err = logFile.Open(iFs, iLogFileName, EFileWrite|EFileShareAny);
+ if (err==KErrPathNotFound)
+ {
+ TName filePath;
+ filePath.Copy(iLogPath);
+ User::LeaveIfError(iFs.MkDirAll(filePath));
+ }
+ else if (err == KErrBadName || err == KErrNotReady)
+ {
+ writePathErrorCode = err;
+ // duff pathspec in ini file
+ TName filePath;
+ filePath.Copy(KLogDefaultFilePath);
+ err = iFs.MkDirAll(filePath);
+ iLogFileName.Copy(KLogDefaultFilePath);
+ iLogFileName.Append(KLogFileName);
+ if (err == KErrAlreadyExists)
+ {
+ err = logFile.Open(iFs, iLogFileName, EFileWrite|EFileShareAny);
+ }
+ }
+
+ if (err==KErrNotFound||err==KErrPathNotFound||err==KErrBadName||err == KErrNotReady)
+ {
+ err = logFile.Create(iFs, iLogFileName, EFileWrite|EFileShareAny);
+ }
+ User::LeaveIfError(err);
+ CleanupClosePushL(logFile);
+ TInt filePos = 0;
+ User::LeaveIfError(logFile.Seek(ESeekEnd,filePos));
+ if (writePathErrorCode != KErrNone)
+ {
+ TBuf8<KMaxFinalLogStringLength> tmpBuf;
+ tmpBuf.Format(KUnableToUpdateMedia,writePathErrorCode);
+ User::LeaveIfError(logFile.Write(tmpBuf));
+ }
+ if (iHBuf)
+ {
+ User::LeaveIfError(logFile.Write(*iHBuf));
+ }
+ CleanupStack::PopAndDestroy(); //logFile
+ }
+
+void CFileWriter::FlushLogL()
+ {
+ DoFlushBufferToFileL();
+ if (iHBuf)
+ {
+ TPtr8 ptr(iHBuf->Des());
+ ptr.Zero();
+ }
+ }
+
+void CFileWriter::SetForceFlush(TBool aOn)
+ {
+ iForceBufferFlushAlways = aOn;
+ }
+
+void CFileWriter::SetLogPath(const TDesC8& aLogPathSetting)
+ {
+ iLogPath.Copy(aLogPathSetting);
+
+ //the path may be reconfigured, so check for '\'
+ //as its assumed to be at the end already
+ TPtr8 iTempStr = iLogPath.RightTPtr(1); //get last
+ TPtr8 iTempExt = iLogPath.RightTPtr(4); //get last 4
+
+ if( iTempStr == KLogPathTree)
+ {
+ //ends with '\', so ok to copy
+ iLogFileName.Copy(iLogPath);
+ iLogFileName.Append(KLogFileName);
+ }
+ else if(iTempExt.Find(KLogFileExt)==KErrNotFound)
+ {
+ //no file extension already set, so its just path
+ iLogPath.Append(KLogPathTree);
+ iLogFileName.Copy(iLogPath);
+ iLogFileName.Append(KLogFileName);
+ }
+ else
+ {
+ //already has all we need
+ iLogFileName.Copy(iLogPath);
+ }
+ }
+
+CFileWriter* CFileWriter::NewL()
+ {
+ CFileWriter* self = new(ELeave) CFileWriter;
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+void CFileWriter::ConstructL()
+ {
+ User::LeaveIfError(iFs.Connect());
+ //Create our buffer for logging into, at zero length but specify a maximum.
+ iHBuf = HBufC8::NewL(KHeapBufSize);
+ iForceBufferFlushAlways = EFalse;
+ iLogPath.Copy(KLogDefaultFilePath);
+ iLogFileName.Copy(iLogPath);
+ iLogFileName.Append(KLogFileName);
+ }
+
+CFileWriter::~CFileWriter()
+ {
+ // Don't attempt flushing when it's an OOM leave from NewL()
+ if (iHBuf)
+ {
+ TRAP_IGNORE(CFileWriter::FlushLogL()); //Ignore error. Nothing we can do now.
+ delete iHBuf;
+ }
+ iFs.Close();
+ }
+
+///////////////////////////////////////////////////////////////////////
+
+CSerialWriter* CSerialWriter::NewL()
+ {
+ CSerialWriter* self = new(ELeave) CSerialWriter;
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+void CSerialWriter::ConstructL()
+ {
+ User::LeaveIfError(iTimeoutTimer.CreateLocal());
+ }
+
+TInt CSerialWriter::LoadDevices()
+ {
+ // load the device drivers
+ TInt result = User::LoadPhysicalDevice(PDD_NAME);
+ if ((result != KErrNone) && (result != KErrAlreadyExists))
+ {
+ return result;
+ }
+
+ result = User::LoadLogicalDevice(LDD_NAME);
+ if ((result != KErrNone) && (result != KErrAlreadyExists))
+ {
+ return result;
+ }
+
+ return KErrNone;
+ }
+
+
+TInt CSerialWriter::OpenPort(TInt aPort)
+ {
+ return iSerialPort.Open(aPort);
+ }
+
+TInt CSerialWriter::SetPortConfig()
+ {
+ TCommConfig tComConfig;
+ TCommConfigV01 &tComConfigV = tComConfig();
+ iSerialPort.Config(tComConfig);
+ tComConfigV.iRate=KFloggerSerialRate;
+ tComConfigV.iDataBits=EData8;
+ tComConfigV.iStopBits=EStop1;
+ tComConfigV.iParity=EParityNone;
+ tComConfigV.iHandshake=0;
+ tComConfigV.iFifo = EFifoEnable;
+ return iSerialPort.SetConfig(tComConfig);
+ }
+
+
+
+CSerialWriter::~CSerialWriter()
+ {
+ iTimeoutTimer.Close();
+ iSerialPort.Close();
+ }
+
+void CSerialWriter::ClearLogL()
+/**
+ * @note: Nothing to do for serial
+ */
+ {}
+
+void CSerialWriter::FlushLogL()
+/**
+ * @note: Nothing to do for serial
+ */
+ {}
+
+void CSerialWriter::SetForceFlush(TBool)
+/**
+ * @note: Nothing to do for serial.
+ */
+ {
+ }
+
+
+void CSerialWriter::LogString(const TDesC8& aString)
+ {
+ //iInvalidcounter is used to dump packets if we fail to get a write through before the
+ //timer expires. It stops us getting backed up too much if there's a problem.
+ if (iInvalidCounter==0)
+ {
+ TRequestStatus writeStatus(KRequestPending);
+ TRequestStatus timeoutStatus(KRequestPending);
+ iSerialPort.Write(writeStatus, aString, aString.Length());
+ iTimeoutTimer.After(timeoutStatus,
+ TTimeIntervalMicroSeconds32(KSerialTimeoutInMicroSecs));
+ User::WaitForRequest(writeStatus, timeoutStatus);
+ if (writeStatus==KRequestPending)
+ {//OK, still not completed, better cancel send.
+ iSerialPort.WriteCancel();
+ iInvalidCounter=KSerialRetryCount;
+ }
+ else
+ {
+ iTimeoutTimer.Cancel();
+ }
+ User::WaitForAnyRequest();
+ }
+ else
+ --iInvalidCounter;
+ }
+
+void CSerialWriter::LogBinaryDump(const TDesC8& aBinaryString, const TDesC8& aSubSystem, const TDesC8& aComponent)
+ {
+ TUint32 length = static_cast<TUint32>(aBinaryString.Length());
+ TBuf8<sizeof(TUint32)> lengthString(4);
+ lengthString[0] = static_cast<TUint8>((length & 0x000000ff) >> 0);
+ lengthString[1] = static_cast<TUint8>((length & 0x0000ff00) >> 8);
+ lengthString[2] = static_cast<TUint8>((length & 0x00ff0000) >> 16);
+ lengthString[3] = static_cast<TUint8>((length & 0xff000000) >> 24);
+
+ LogString(aSubSystem);
+ LogString(KTabCharacter);
+ LogString(aComponent);
+ LogString(KTabCharacter);
+ LogString(KTypeIdentifierBinary);
+ LogString(KTabCharacter);
+ LogString(lengthString);
+ LogString(KTabCharacter);
+ LogString(aBinaryString);
+ LogString(KEolCharacters);
+ }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+//Don't strictly need a NewL. Doing it for consistency.
+CRDebugWriter* CRDebugWriter::NewL()
+ {
+ return new(ELeave) CRDebugWriter;
+ }
+
+CRDebugWriter::~CRDebugWriter()
+ {
+ }
+
+void CRDebugWriter::ClearLogL()
+/**
+ * @note: Nothing to do for RDebug
+ */
+ {}
+
+void CRDebugWriter::FlushLogL()
+/**
+ * @note: Nothing to do for RDebug
+ */
+ {}
+
+void CRDebugWriter::SetForceFlush(TBool)
+/**
+ * @note: Nothing to do for RDebug.
+ */
+ {
+ }
+
+
+void CRDebugWriter::LogString(const TDesC8& aString)
+ {
+
+ //RDebug truncates strings longer than a certain size
+ //To work around this we chop our string into palatable chunks
+ //and log those individually
+
+ const TUint8 *p = aString.Ptr();
+ TInt bytesSent(0);
+ TInt totalToSend = aString.Length();
+ TInt length(0);
+
+ do
+ {
+ bytesSent += KRDebugLimit;
+ if (bytesSent < totalToSend)
+ {
+ length = KRDebugLimit;
+ }
+ else
+ {
+ length = totalToSend - bytesSent + KRDebugLimit;
+ }
+
+ TPtrC8 ptr(p,length);
+ RDebug::RawPrint(ptr);
+ p += KRDebugLimit;
+ }
+ while(bytesSent < totalToSend);
+ }
+
+
+void CRDebugWriter::LogBinaryDump(const TDesC8& aBinaryString, const TDesC8& aSubSystem, const TDesC8& aComponent)
+ {
+ TUint32 length = static_cast<TUint32>(aBinaryString.Length());
+ TBuf8<sizeof(TUint32)> lengthString(4);
+ lengthString[0] = static_cast<TUint8>((length & 0x000000ff) >> 0);
+ lengthString[1] = static_cast<TUint8>((length & 0x0000ff00) >> 8);
+ lengthString[2] = static_cast<TUint8>((length & 0x00ff0000) >> 16);
+ lengthString[3] = static_cast<TUint8>((length & 0xff000000) >> 24);
+
+ RDebug::RawPrint(aSubSystem);
+ RDebug::RawPrint(KTabCharacter);
+ RDebug::RawPrint(aComponent);
+ RDebug::RawPrint(KTabCharacter);
+ RDebug::RawPrint(KTypeIdentifierBinary);
+ RDebug::RawPrint(KTabCharacter);
+ RDebug::RawPrint(lengthString);
+ RDebug::RawPrint(KTabCharacter);
+ LogString(aBinaryString);
+ RDebug::RawPrint(KEolCharacters);
+
+ }
+
+
+///////////////////////////////////////////////////////////////////////
+
+#if defined (__WINS__)
+#include <emulator.h>
+
+CDebugPortProtocol* CDebugPortProtocol::NewL()
+ {
+ CDebugPortProtocol* protocol = new(ELeave) CDebugPortProtocol;
+ CleanupStack::PushL(protocol);
+ protocol->ConstructL();
+ CleanupStack::Pop(protocol);
+ return protocol;
+ }
+
+void CDebugPortProtocol::ConstructL()
+ {
+ iDebugWriter = CDebugPortWriter::NewL();
+ }
+
+CDebugPortProtocol::~CDebugPortProtocol()
+ {
+ delete iDebugWriter;
+ }
+void CDebugPortProtocol::ClearLog(const TFullName& /*aName*/)
+ {
+ }
+void CDebugPortProtocol::SetTimeL(const TTime& /*aTime*/)
+ {
+ }
+void CDebugPortProtocol::LogString(const TDesC8& aLogString, const TDesC8& aSubSystem, const TDesC8& aComponent, const TThreadId& aThreadId)
+ {
+ TBuf8<KMaxFinalLogStringLength> buf;
+ buf.Append(aSubSystem);
+ buf.Append(KTabCharacter);
+ buf.Append(aComponent);
+ buf.Append(KTabCharacter);
+ buf.Append(KTypeIdentifierAscii);
+ buf.Append(KTabCharacter);
+ buf.AppendNum(aThreadId, EHex);
+ buf.Append(KTabCharacter);
+ buf.Append(aLogString);
+ // check whether last two bytes of string are eol chars, since some lines have cr/lf, some don't
+ TPtr8 ptr(&buf[buf.Length()-2], 2, 2);
+ if (ptr.Compare(KEolCharacters) !=0 )
+ {
+ buf.Append(KEolCharacters);
+ }
+ iDebugWriter->LogString(buf);
+ }
+void CDebugPortProtocol::LogBinaryDump(const TDesC8& aBinaryString, const TDesC8& aSubSystem, const TDesC8& aComponent)
+ {
+ iDebugWriter->LogBinaryDump(aBinaryString, aSubSystem, aComponent);
+ }
+void CDebugPortProtocol::LogComment(const TDesC8& aComment)
+ {
+ iDebugWriter->LogString(aComment);
+ }
+void CDebugPortProtocol::MediaUpdate(const TDesC8& /*aMediaSetting*/, const TBool /*aForceFlushOn*/, const TDesC8& /*aLogPathSetting*/)
+ {
+ }
+void CDebugPortProtocol::ShutDown()
+ {
+ }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+CDebugPortWriter* CDebugPortWriter::NewL()
+ {
+ return new(ELeave) CDebugPortWriter;
+ }
+
+
+void CDebugPortWriter::LogString(const TDesC8& aString)
+ {
+ char str[Win32DisplayStringLengthMax];
+ int len = Min(sizeof(str) - 1, aString.Length());
+ Mem::Copy(str, aString.Ptr(), len);
+ str[len] = '\0';
+ Emulator::Lock();
+ ::OutputDebugStringA(str);
+ Emulator::Unlock();
+ }
+void CDebugPortWriter::ClearLogL()
+ {
+ }
+void CDebugPortWriter::FlushLogL()
+ {
+ }
+void CDebugPortWriter::LogBinaryDump(const TDesC8& /*aBinaryString*/, const TDesC8& /*aSubSystem*/, const TDesC8& /*aComponent*/)
+ {
+ }
+void CDebugPortWriter::SetForceFlush(const TBool /*aOn*/)
+ {
+ }
+
+#endif //(__WINS__)