diff -r 000000000000 -r 08ec8eefde2f traceservices/commsdebugutility/SSVR/comsdbgwriter.cpp --- /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 (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 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 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 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 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(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 buf; + buf.Format(KUnableToLoadSerialDevices,res); + iLogger->LogString(buf); + delete serial; + User::Leave(res); + } + res = serial->OpenPort(KSerialPort1); + if (res != KErrNone) + { + TBuf8 buf; + buf.Format(KUnableToOpenSerial,res); + iLogger->LogString(buf); + delete serial; + User::Leave(res); + } + + res = serial->SetPortConfig(); + if (res != KErrNone) + { + TBuf8 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 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 buf; + buf.Format(KUnableToOpenSerial,res); + iLogger->LogString(buf); + delete serial; + User::Leave(res); + } + + res = serial->SetPortConfig(); + if (res != KErrNone) + { + TBuf8 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(aBinaryString.Length()); + TBuf8 lengthString(4); + lengthString[0] = static_cast((length & 0x000000ff) >> 0); + lengthString[1] = static_cast((length & 0x0000ff00) >> 8); + lengthString[2] = static_cast((length & 0x00ff0000) >> 16); + lengthString[3] = static_cast((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 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(aBinaryString.Length()); + TBuf8 lengthString(4); + lengthString[0] = static_cast((length & 0x000000ff) >> 0); + lengthString[1] = static_cast((length & 0x0000ff00) >> 8); + lengthString[2] = static_cast((length & 0x00ff0000) >> 16); + lengthString[3] = static_cast((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(aBinaryString.Length()); + TBuf8 lengthString(4); + lengthString[0] = static_cast((length & 0x000000ff) >> 0); + lengthString[1] = static_cast((length & 0x0000ff00) >> 8); + lengthString[2] = static_cast((length & 0x00ff0000) >> 16); + lengthString[3] = static_cast((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 + +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 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__)