--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btlogger/btsnoophcilogger/src/hciloggerbtsnoop.cpp Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,310 @@
+// Copyright (c) 2004-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:
+//
+
+#include "hciloggerbtsnoop.h"
+
+static const TInt KSnoopLogFileHeaderSize = 16; // bytes
+static const TInt KSnoopLogRecordHeaderSize = 24; // bytes
+static const TUint KSnoopLogVersion = 1;
+
+static const TInt KHCILoggerFileCloseTime = 5000000; // 5 seconds
+
+_LIT8(KSnoopLogBlankDescriptor, "");
+_LIT8(KSnoopLogFileHeaderFormat, "btsnoop\0%M%M");
+_LIT8(KSnoopLogRecordHeaderFormat, "%M%M%M%M%M%M");
+
+#ifdef __WINS__
+_LIT(KSnoopLogFileH1, "\\shared\\hcilogger\\hcilog_H1.log");
+_LIT(KSnoopLogFileH4, "\\shared\\hcilogger\\hcilog_H4.log");
+_LIT(KSnoopLogFileBCSP, "\\shared\\hcilogger\\hcilog_Bcsp.log");
+_LIT(KSnoopLogFileH5, "\\shared\\hcilogger\\hcilog_H5.log");
+_LIT(KSnoopLogFileDefault, "\\shared\\hcilogger\\hcilog_unknown.log");
+#else
+_LIT(KSnoopLogFileH1, "e:\\shared\\hcilogger\\hcilog_H1.log");
+_LIT(KSnoopLogFileH4, "e:\\shared\\hcilogger\\hcilog_H4.log");
+_LIT(KSnoopLogFileBCSP, "e:\\shared\\hcilogger\\hcilog_Bcsp.log");
+_LIT(KSnoopLogFileH5, "e:\\shared\\hcilogger\\hcilog_H5.log");
+_LIT(KSnoopLogFileDefault, "e:\\shared\\hcilogger\\hcilog_unknown.log");
+#endif //__WINS__
+
+#ifndef EKA2
+GLDEF_C TInt E32Dll(TDllReason)
+#else
+GLDEF_C TInt E32Dll()
+#endif
+ {
+ return KErrNone;
+ }
+
+CHCILoggerBtSnoop* CHCILoggerBtSnoop::NewLC()
+ {
+ CHCILoggerBtSnoop* self = new (ELeave) CHCILoggerBtSnoop;
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+CHCILoggerBtSnoop::CHCILoggerBtSnoop()
+ {
+ }
+
+void CHCILoggerBtSnoop::ConstructL()
+ {
+ iFileCloseTimer = CHCILoggerFileCloseTimer::NewL(iLogFile);
+ for (TInt i = 0; i <= TInt(KHCILoggerControllerToHost | KHCILoggerCommandOrEvent); i++)
+ {
+ CHCILoggerBufferedFrame* temp = new(ELeave) CHCILoggerBufferedFrame;
+ iBuffers.Append(temp); // array now "owns" temp
+ }
+ }
+
+void CHCILoggerBtSnoop::DoInitialise(TInt aType)
+ {
+ iDatalinkType = aType;
+ iFs.Connect();
+ OpenFile(); // if it fails, just ignore it - try later when writing
+ }
+
+CHCILoggerBtSnoop::~CHCILoggerBtSnoop()
+ {
+ iBuffers.ResetAndDestroy();
+ iLogFile.Close();
+ iFs.Close();
+ delete iFileCloseTimer;
+ }
+
+void CHCILoggerBtSnoop::LogFrame(TUint aFrameFlags, const TDesC8& aDesc)
+ {
+ TInt packetFlags = aFrameFlags & (KHCILoggerControllerToHost | KHCILoggerCommandOrEvent);
+ CHCILoggerBufferedFrame* buffer = iBuffers[packetFlags];
+ if (aFrameFlags & KHCILoggerFrameFragmented)
+ {
+ buffer->BufferData(aDesc);
+ return;
+ }
+
+ TBtSnoopPacketRecord record;
+ record.iOriginalLength = aDesc.Length();
+ record.iIncludedLength = record.iOriginalLength;
+ record.iPacketFlags = aFrameFlags;
+ record.iCumulativeDrops = iCumulativeDrops;
+ iCurrentTime.HomeTime();
+ record.iTimestampMicroseconds = iCurrentTime.Int64();
+
+ // if the file is not open, try to open it
+ if (!iLogFile.SubSessionHandle())
+ {
+ if (OpenFile() != KErrNone)
+ {
+ return;
+ }
+ }
+
+ record.iOriginalLength += buffer->OriginalLength();
+ TDesC8& des = buffer->Buffer();
+ if (buffer->OriginalLength() > des.Length())
+ { // some data lost
+ record.iIncludedLength = des.Length();
+ FileWriteRecord(record, des);
+ }
+ else
+ { // no data lost
+ record.iIncludedLength = record.iOriginalLength;
+ FileWriteRecord(record, des, aDesc);
+ }
+ buffer->Reset();
+ }
+
+TInt CHCILoggerBtSnoop::OpenFile()
+ {
+ TPtrC fileName;
+ switch (iDatalinkType)
+ {
+ case KHCILoggerDatalinkTypeH1:
+ fileName.Set(KSnoopLogFileH1);
+ break;
+ case KHCILoggerDatalinkTypeH4:
+ fileName.Set(KSnoopLogFileH4);
+ break;
+ case KHCILoggerDatalinkTypeBCSP:
+ fileName.Set(KSnoopLogFileBCSP);
+ break;
+ case KHCILoggerDatalinkTypeH5:
+ fileName.Set(KSnoopLogFileH5);
+ break;
+ default:
+ fileName.Set(KSnoopLogFileDefault);
+ break;
+ };
+
+ TInt err = iLogFile.Open(iFs, fileName, EFileWrite | EFileShareAny);
+ if (err == KErrNotFound)
+ { // if it doesn't already exist, create it
+ //Note that the potential KErrPathNotFound error is deliberately not handled,
+ //since the shared\hcilogger directory not being present is used to indicate
+ //that logging is not desired.
+ err = iLogFile.Create(iFs, fileName, EFileWrite | EFileShareAny);
+ }
+ TInt size = 0;
+ if (err == KErrNone)
+ {
+ err = iLogFile.Size(size);
+ }
+ if (err == KErrNone)
+ {
+ if (size < KSnoopLogFileHeaderSize)
+ {
+ err = FileWriteHeader(); // write will automatically start at pos 0,
+ } // hence overwriting the file
+ else
+ { // want to append the data to the current file
+ TInt writePos = KSnoopLogFileHeaderSize; // KSnoopLogFileHeaderSize is const, so can't pass in Seek()
+ iLogFile.Seek(ESeekEnd, writePos);
+ }
+ }
+ if (err)
+ {
+ iLogFile.Close(); // just in case
+ }
+ return err;
+ }
+
+TInt CHCILoggerBtSnoop::FileWriteHeader()
+ {
+ TBuf8<KSnoopLogFileHeaderSize> buf;
+ buf.Format(KSnoopLogFileHeaderFormat, KSnoopLogVersion, iDatalinkType);
+ TInt err = iLogFile.Write(buf);
+ iFileCloseTimer->ResetTimer();
+ return err;
+ }
+
+void CHCILoggerBtSnoop::FileWriteRecord(const TBtSnoopPacketRecord& aRecord, const TDesC8& aBufferedData, const TDesC8& aNewData)
+ {
+ TBuf8<KSnoopLogRecordHeaderSize> buf;
+ buf.Format(KSnoopLogRecordHeaderFormat, aRecord.iOriginalLength,
+ aRecord.iIncludedLength,
+ aRecord.iPacketFlags,
+ aRecord.iCumulativeDrops,
+ I64HIGH(aRecord.iTimestampMicroseconds),
+ I64LOW(aRecord.iTimestampMicroseconds));
+
+ // if these fail, just ignore them
+ iLogFile.Write(buf); // header
+ iLogFile.Write(aBufferedData); // data
+ iLogFile.Write(aNewData); // data
+ iFileCloseTimer->ResetTimer();
+ }
+
+void CHCILoggerBtSnoop::FileWriteRecord(const TBtSnoopPacketRecord& aRecord, const TDesC8& aNewData)
+ {
+ FileWriteRecord(aRecord, KSnoopLogBlankDescriptor, aNewData);
+ }
+
+// CHCILoggerFileCloseTimer functions //
+
+CHCILoggerFileCloseTimer* CHCILoggerFileCloseTimer::NewL(RFile& aLogFile)
+ {
+ CHCILoggerFileCloseTimer* self = new(ELeave) CHCILoggerFileCloseTimer(aLogFile);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CHCILoggerFileCloseTimer::CHCILoggerFileCloseTimer(RFile& aLogFile)
+: CTimer(EPriorityStandard), iLogFile(aLogFile)
+ {
+ }
+
+void CHCILoggerFileCloseTimer::ConstructL()
+ {
+ CTimer::ConstructL();
+ CActiveScheduler::Add(this);
+ }
+
+void CHCILoggerFileCloseTimer::ResetTimer()
+ {
+ if (IsActive())
+ {
+ Cancel();
+ }
+ After(TTimeIntervalMicroSeconds32(KHCILoggerFileCloseTime));
+ }
+
+void CHCILoggerFileCloseTimer::RunL()
+ {
+ iLogFile.Close();
+ }
+
+void CHCILoggerFileCloseTimer::DoCancel()
+ {
+ CTimer::DoCancel();
+ }
+
+CHCILoggerFileCloseTimer::~CHCILoggerFileCloseTimer()
+ {
+ Cancel();
+ }
+
+CHCILoggerBufferedFrame::CHCILoggerBufferedFrame()
+ {
+ iBuffer = HBufC8::New(0);
+ }
+
+CHCILoggerBufferedFrame::~CHCILoggerBufferedFrame()
+ {
+ delete iBuffer;
+ }
+
+void CHCILoggerBufferedFrame::BufferData(const TDesC8& aDesc)
+ {
+ if (iOriginalLength == iBuffer->Length())
+ { // then no allocations have failed so far
+ TInt newLength = iOriginalLength + aDesc.Length();
+ // add aDesc to buffer
+ HBufC8* buf = iBuffer;
+ if(buf != NULL)
+ {
+ if(newLength > buf->Des().MaxLength())
+ {
+ buf = buf->ReAlloc(newLength);
+ }
+ if(buf != NULL)
+ { // successful allocation
+ buf->Des().Append(aDesc);
+ iBuffer = buf;
+ }
+ // else if it failed, iBuffer stays the same
+ }
+ }
+ iOriginalLength += aDesc.Length(); // add this on anyway
+ }
+
+void CHCILoggerBufferedFrame::Reset()
+ {
+ iBuffer->Des().Zero();
+ iOriginalLength = 0;
+ }
+
+TInt CHCILoggerBufferedFrame::OriginalLength() const
+ {
+ return iOriginalLength;
+ }
+
+TDesC8& CHCILoggerBufferedFrame::Buffer() const
+ {
+ return *iBuffer;
+ }
+