--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libraries/clogger/src/CloggerClient.cpp Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,822 @@
+// CloggerClient.cpp
+//
+// Copyright (c) 2006 - 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "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:
+// Accenture - Initial contribution
+//
+
+#include "clogger.h"
+#include "cliserv.h"
+#include "SensibleClient_Internals.h"
+#include "common.h"
+#include <badesca.h>
+#include <s32mem.h>
+#include <e32property.h>
+
+#define KFlagsMask 0x0FFFFFFF
+#define KTestTagEnabled 0x10000000
+#define KNoLogMask 0x80000000 // This is the log mask used internally if you call an overload which doesn't specify one
+
+#define iBody (*reinterpret_cast<RCloggerBody*>(&iPimpl))
+
+#ifndef PERFORMANCE_CRITICAL
+
+// declares RClogger* clogger
+#define CheckConnected() \
+ RClogger _cloggerHandle; \
+ RClogger* clogger = &_cloggerHandle; \
+ GetTls(clogger, ETrue); \
+ if (!clogger) return
+
+#define GetTlsOrConnect(aTag) \
+ RClogger _cloggerHandle; \
+ RClogger* clogger = &_cloggerHandle; \
+ TInt err; \
+ TBool isHandle = GetTls(clogger, ETrue, &aTag, &err)
+
+#define GetTlsOrNull() \
+ RClogger _cloggerHandle; \
+ RClogger* clogger = &_cloggerHandle; \
+ TBool isHandle = GetTls(clogger, EFalse)
+
+TBool RClogger::GetTls(RClogger*& aClogger, TBool aAutoConnect, const TDesC* aTag, TInt* aError)
+ {
+ TAny* tls = Dll::Tls();
+ if ((TUint)tls & 1)
+ {
+ // Then it's a handle
+ aClogger->SetHandle((TInt)((TUint)tls >> 1));
+ return ETrue;
+ }
+ else if (tls)
+ {
+ // Then it's a pointer
+ aClogger = (RClogger*)tls;
+ return EFalse;
+ }
+ else if (aAutoConnect)
+ {
+ TInt err = aClogger->Connect(aTag ? *aTag : KNullDesC);
+ aClogger->iFlags &= ~EUseHeapBuffer; // Don't (by default) use a buffer for static connections because we can't track it without upgrading TLS
+ if (err)
+ {
+ if (aError) *aError = err;
+ aClogger = NULL;
+ return ETrue;
+ }
+ __ASSERT_DEBUG((aClogger->Handle() & 0x80000000) == 0, User::Panic(_L("HandleTooBig"), 0));
+
+ err = Dll::SetTls((TAny*) ((aClogger->Handle() << 1) | 1));
+ if (err)
+ {
+ aClogger->Close();
+ if (aError) *aError = err;
+ aClogger = NULL;
+ }
+ return ETrue;
+ }
+ else
+ {
+ aClogger = NULL;
+ return ETrue;
+ }
+ }
+
+#endif // PERFORMANCE_CRITICAL
+
+NONSHARABLE_CLASS(RCloggerBody) : public RSensibleSessionBody
+ {
+public:
+ RCloggerBody(RClogger& aSession);
+ TInt DoCreateSession(const TDesC &aServer, const TVersion &aVersion, TInt aAsyncMessageSlots);
+ TInt DoSendReceive(TInt aFunction, const TIpcArgs &aArgs) const;
+ void DoSendReceive(TInt aFunction, const TIpcArgs &aArgs, TRequestStatus& aStatus) const;
+ void ServerDiedL();
+ void DispatchCallbackL(TServerCallback& aCallback, TCallbackParser& aParser);
+
+private:
+ friend class RClogger;
+ //RClogger& iSession; // No need to store this, we can calculate it from our this pointer since we know we are always embedded in an RClogger
+ };
+
+#define iSession (*(RClogger*)((TUint8*)this - _FOFF(RClogger, iPimpl)))
+
+RCloggerBody::RCloggerBody(RClogger& /*aSession*/)
+ : RSensibleSessionBody() //, iSession(aSession)
+ {}
+
+TInt RCloggerBody::DoCreateSession(const TDesC &aServer, const TVersion &aVersion, TInt aAsyncMessageSlots)
+ {
+ return iSession.CreateSession(aServer, aVersion, aAsyncMessageSlots);
+ }
+
+TInt RCloggerBody::DoSendReceive(TInt aFunction, const TIpcArgs &aArgs) const
+ {
+ return iSession.SendReceive(aFunction, aArgs);
+ }
+
+void RCloggerBody::DoSendReceive(TInt aFunction, const TIpcArgs &aArgs, TRequestStatus& aStatus) const
+ {
+ iSession.SendReceive(aFunction, aArgs, aStatus);
+ }
+
+EXPORT_C RClogger::RClogger()
+ : iFlags(0), iEnabled(EAllEnabled), iBuf(), iSequence(0)
+ {
+ __ASSERT_COMPILE(sizeof(iPimpl) >= sizeof(RCloggerBody));
+ __ASSERT_COMPILE(sizeof(RClogger) == 10*4); // This is the size we've published, it CANNOT change
+
+ // Initialise the body using placement new
+ new(iPimpl) RCloggerBody(*this);
+ }
+
+EXPORT_C RClogger::RClogger(TAny* aTls)
+ : iFlags(0), iEnabled(EAllEnabled), iBuf(), iSequence(0)
+ {
+ // This overload is only ever supposed to be used by the TlsLog inline functions, hence why it's private but still
+ // exported.
+ new(iPimpl) RCloggerBody(*this);
+ SetHandle(reinterpret_cast<TInt>(aTls));
+ }
+
+EXPORT_C TInt RClogger::Connect()
+ {
+ return Connect(KNullDesC);
+ }
+
+EXPORT_C TInt RClogger::Connect(const TDesC& aTag)
+ {
+ iFlags |= EUseHeapBuffer; // Set by default
+
+ TInt err = iBody.Connect(1, EFalse); // Only need 1 slot as we only have one async function (which is hidden within RSensibleSession)
+ if (!err)
+ {
+ err = ShareAuto();
+ }
+ if (!err)
+ {
+ TPckg<TUint32> enabledPkg(iEnabled);
+ TInt res = SendReceive(ESetTag, TIpcArgs(&aTag, NULL, &enabledPkg));
+ if (res >= 0)
+ {
+ iSequence = res;
+ }
+ else
+ {
+ err = res;
+ }
+ }
+ if (err)
+ {
+ Close();
+ }
+ return err;
+ }
+
+EXPORT_C TInt RClogger::StaticConnect()
+ {
+ return StaticConnect(KNullDesC);
+ }
+
+#ifndef PERFORMANCE_CRITICAL
+
+EXPORT_C TInt RClogger::StaticConnect(const TDesC& aTag)
+ {
+ GetTlsOrConnect(aTag);
+ if (clogger) return KErrNone;
+ else return err;
+ }
+
+EXPORT_C void RClogger::StaticClose()
+ {
+ GetTlsOrNull();
+ if (clogger)
+ {
+ clogger->Close();
+ if (!isHandle)
+ {
+ delete clogger;
+ }
+ Dll::SetTls(NULL);
+ Dll::FreeTls();
+ }
+ }
+
+#endif // PERFORMANCE_CRITICAL
+
+
+EXPORT_C void RClogger::Log(TRefByValue<const TDesC> aFmt, ...)
+ {
+ VA_LIST args;
+ VA_START(args, aFmt);
+ LogList(KNoLogMask, aFmt, args);
+ VA_END(args);
+ }
+
+EXPORT_C void RClogger::Log(TUint32 aLogMask, TRefByValue<const TDesC> aFmt, ...)
+ {
+ VA_LIST args;
+ VA_START(args, aFmt);
+ LogList(aLogMask, aFmt, args);
+ VA_END(args);
+ }
+
+EXPORT_C void RClogger::Log(TRefByValue<const TDesC8> aFmt, ...)
+ {
+ VA_LIST args;
+ VA_START(args, aFmt);
+ LogList(KNoLogMask, aFmt, args);
+ VA_END(args);
+ }
+
+EXPORT_C void RClogger::Log(TUint32 aLogMask, TRefByValue<const TDesC8> aFmt, ...)
+ {
+ VA_LIST args;
+ VA_START(args, aFmt);
+ LogList(aLogMask, aFmt, args);
+ VA_END(args);
+ }
+
+EXPORT_C void RClogger::Log(const char* aFmt, ...)
+ {
+ VA_LIST args;
+ VA_START(args, aFmt);
+ LogList(KNoLogMask, aFmt, args);
+ VA_END(args);
+ }
+
+EXPORT_C void RClogger::Log(TUint32 aLogMask, const char* aFmt, ...)
+ {
+ VA_LIST args;
+ VA_START(args, aFmt);
+ LogList(aLogMask, aFmt, args);
+ VA_END(args);
+ }
+
+EXPORT_C void RClogger::LogList(TRefByValue<const TDesC> aFmt, VA_LIST aList)
+ {
+ LogList(KNoLogMask, aFmt, aList);
+ }
+
+EXPORT_C void RClogger::LogList(TUint32 aLogMask, TRefByValue<const TDesC> aFmt, VA_LIST aList)
+ {
+ if (!Enabled(aLogMask)) return;
+ TUint32 tickCount = User::NTickCount();
+
+ TPtrC fmt(aFmt);
+ if (iFlags & ETrimTrailingNewlines)
+ {
+ TInt len = fmt.Length();
+ if (len && fmt[len-1] == '\n') fmt.Set(fmt.Left(len-1));
+ len = fmt.Length();
+ if (len && fmt[len-1] == '\r') fmt.Set(fmt.Left(len-1));
+ }
+ #define SF_FORMAT fmt
+ #define SF_LIST aList
+ #define SF_BUF iBuf
+ #define SF_ACTION(buf) SendReceive(ELog8, TIpcArgs(&buf, tickCount, aLogMask))
+ #define SF_WIDE
+ #define SF_STACKONLY (!(iFlags & EUseHeapBuffer))
+ #include "SensibleFormat.h"
+
+ //if (!(iFlags&ECacheClientBuffers)) iBuf.Close();
+ }
+
+EXPORT_C void RClogger::LogList(TRefByValue<const TDesC8> aFmt, VA_LIST aList)
+ {
+ LogList(KNoLogMask, aFmt, aList);
+ }
+
+EXPORT_C void RClogger::LogList(TUint32 aLogMask, TRefByValue<const TDesC8> aFmt, VA_LIST aList)
+ {
+ if (!Enabled(aLogMask)) return;
+ TUint32 tickCount = User::NTickCount();
+
+ TPtrC8 fmt(aFmt);
+ if (iFlags & ETrimTrailingNewlines)
+ {
+ TInt len = fmt.Length();
+ if (len && fmt[len-1] == '\n') fmt.Set(fmt.Left(len-1));
+ len = fmt.Length();
+ if (len && fmt[len-1] == '\r') fmt.Set(fmt.Left(len-1));
+ }
+ #define SF_FORMAT fmt
+ #define SF_LIST aList
+ #define SF_BUF iBuf
+ #define SF_ACTION(buf) SendReceive(ELog8, TIpcArgs(&buf, tickCount, aLogMask))
+ #define SF_STACKONLY (!(iFlags & EUseHeapBuffer))
+ #include "SensibleFormat.h"
+
+ //if (!(iFlags&ECacheClientBuffers)) iBuf.Close();
+ }
+
+EXPORT_C void RClogger::LogList(const char* aFmt, VA_LIST aList)
+ {
+ TPtrC8 ptr((const TUint8*)aFmt);
+ LogList(KNoLogMask, ptr, aList);
+ }
+
+EXPORT_C void RClogger::LogList(TUint32 aLogMask, const char* aFmt, VA_LIST aList)
+ {
+ TPtrC8 ptr((const TUint8*)aFmt);
+ LogList(aLogMask, ptr, aList);
+ }
+
+#ifndef PERFORMANCE_CRITICAL
+
+EXPORT_C void RClogger::Slog(TUint32 aLogMask, TRefByValue<const TDesC> aFmt, ...)
+ {
+ CheckConnected();
+ VA_LIST args;
+ VA_START(args, aFmt);
+ clogger->LogList(aLogMask, aFmt, args);
+ VA_END(args);
+ }
+
+EXPORT_C void RClogger::Slog(TUint32 aLogMask, TRefByValue<const TDesC8> aFmt, ...)
+ {
+ CheckConnected();
+ VA_LIST args;
+ VA_START(args, aFmt);
+ clogger->LogList(aLogMask, aFmt, args);
+ VA_END(args);
+ }
+
+EXPORT_C void RClogger::Slog(TUint32 aLogMask, const char* aFmt, ...)
+ {
+ CheckConnected();
+ VA_LIST args;
+ VA_START(args, aFmt);
+ clogger->LogList(aLogMask, aFmt, args);
+ VA_END(args);
+ }
+
+EXPORT_C void RClogger::Slog(TRefByValue<const TDesC> aFmt, ...)
+ {
+ CheckConnected();
+ VA_LIST args;
+ VA_START(args, aFmt);
+ clogger->LogList(KNoLogMask, aFmt, args);
+ VA_END(args);
+ }
+
+EXPORT_C void RClogger::Slog(TRefByValue<const TDesC8> aFmt, ...)
+ {
+ CheckConnected();
+ VA_LIST args;
+ VA_START(args, aFmt);
+ clogger->LogList(KNoLogMask, aFmt, args);
+ VA_END(args);
+ }
+
+EXPORT_C void RClogger::Slog(const char* aFmt, ...)
+ {
+ CheckConnected();
+ VA_LIST args;
+ VA_START(args, aFmt);
+ clogger->LogList(KNoLogMask, aFmt, args);
+ VA_END(args);
+ }
+
+EXPORT_C void RClogger::SlogList(TUint32 aLogMask, TRefByValue<const TDesC> aFmt, VA_LIST aList)
+ {
+ CheckConnected();
+ clogger->LogList(aLogMask, aFmt, aList);
+ }
+
+EXPORT_C void RClogger::SlogList(TUint32 aLogMask, TRefByValue<const TDesC8> aFmt, VA_LIST aList)
+ {
+ CheckConnected();
+ clogger->LogList(aLogMask, aFmt, aList);
+ }
+
+EXPORT_C void RClogger::SlogList(TUint32 aLogMask, const char* aFmt, VA_LIST aList)
+ {
+ CheckConnected();
+ clogger->LogList(aLogMask, aFmt, aList);
+ }
+
+EXPORT_C void RClogger::SlogList(TRefByValue<const TDesC> aFmt, VA_LIST aList)
+ {
+ CheckConnected();
+ clogger->LogList(KNoLogMask, aFmt, aList);
+ }
+
+EXPORT_C void RClogger::SlogList(TRefByValue<const TDesC8> aFmt, VA_LIST aList)
+ {
+ CheckConnected();
+ clogger->LogList(KNoLogMask, aFmt, aList);
+ }
+
+EXPORT_C void RClogger::SlogList(const char* aFmt, VA_LIST aList)
+ {
+ CheckConnected();
+ clogger->LogList(KNoLogMask, aFmt, aList);
+ }
+
+EXPORT_C void RClogger::SetStaticLogBehaviour(TUint aLogBehaviour)
+ {
+ GetTlsOrConnect(KNullDesC);
+ if (isHandle && (aLogBehaviour != 0))
+ {
+ // Then we need to upgrade from handle to pointer
+ TInt err = KErrNoMemory;
+ RClogger* ptr = new RClogger();
+ if (ptr)
+ {
+ ptr->SetHandle(clogger->Handle());
+ err = Dll::SetTls(ptr);
+ if (err) delete ptr;
+ }
+ if (err)
+ {
+ // Then log it.
+ _LIT(KErr, "RClogger couldn't upgrade handle to pointer, err %i");
+ clogger->Log(KErr(), err);
+
+ aLogBehaviour = 0; // Don't update flags if we failed to honour them
+ }
+ else
+ {
+ clogger = ptr;
+ }
+ }
+
+ clogger->SetLogBehaviour(aLogBehaviour);
+ }
+
+#endif // PERFORMANCE_CRITICAL
+
+EXPORT_C void RClogger::SetLogBehaviour(TUint aLogBehaviour)
+ {
+ iFlags = (iFlags & ~KFlagsMask) | (aLogBehaviour & KFlagsMask);
+
+ if (!(iFlags & EUseHeapBuffer)) iBuf.Close();
+
+ /* This is not needed any more
+ if (iFlags & EMonitorTagState)
+ {
+ iBody.StartCallbackDispatcher();
+ }
+ else
+ {
+ iBody.StopCallbackDispatcher();
+ }
+ */
+ }
+
+EXPORT_C TInt RClogger::SetEnabled(const TDesC& aTag, TUint32 aEnabledMask)
+ {
+ return SendReceive(ESetEnabled, TIpcArgs(&aTag, aEnabledMask));
+ }
+
+EXPORT_C TUint32 RClogger::IsEnabled(const TDesC& aTag)
+ {
+ TPckgBuf<TUint32> logMask;
+ TInt res = SendReceive(EIsEnabled, TIpcArgs(&aTag, &logMask));
+ return res < 0 ? EFalse : logMask();
+ }
+
+/*
+EXPORT_C void RClogger::TailLogFile(TInt aNumberOfChars)
+ {
+ SendReceive(ETailLogToRDebug, TIpcArgs(aNumberOfChars));
+ }
+
+EXPORT_C void RClogger::TailLogFile(TDes8& aBuf)
+ {
+ SendReceive(ETailLogToBuf, TIpcArgs(&aBuf));
+ }
+*/
+
+EXPORT_C void RClogger::SetGlobalOptions(TUint aGlobalOptions)
+ {
+ SendReceive(ESetGlobalOptions, TIpcArgs(aGlobalOptions));
+ }
+
+EXPORT_C TUint RClogger::GetGlobalOptions()
+ {
+ return SendReceive(EGetGlobalOptions, TIpcArgs());
+ }
+
+EXPORT_C TInt RClogger::GetRamBufferSize(TInt* aNumberOfBuffers)
+ {
+ TBuf8<8> buf;
+ buf.SetLength(8);
+ SendReceive(EGetRamBufferSize, TIpcArgs(&buf));
+ TInt* ptr = (TInt*)buf.Ptr();
+ TInt size = ptr[0];
+ if (aNumberOfBuffers)
+ {
+ *aNumberOfBuffers = ptr[1];
+ }
+ return size;
+ }
+
+EXPORT_C void RClogger::SetRamBufferSize(TInt aSize, TInt aNum)
+ {
+ SendReceive(ESetRamBufferSize, TIpcArgs(aSize, aNum));
+ }
+
+EXPORT_C TInt RClogger::Rotate()
+ {
+ return SendReceive(ERotate, TIpcArgs());
+ }
+
+EXPORT_C TInt RClogger::Rotate(TDes& aFileName)
+ {
+ aFileName.Zero();
+ return SendReceive(ERotate, TIpcArgs(&aFileName));
+ }
+
+EXPORT_C void RClogger::SetRotateBehaviour(TInt aNumberOfOldLogsToKeep, TUint aRotateBehaviour)
+ {
+ SendReceive(ESetRotateBehaviour, TIpcArgs(aNumberOfOldLogsToKeep, aRotateBehaviour));
+ }
+
+EXPORT_C TUint RClogger::GetRotateBehaviour(TInt* aNumberOfOldLogsToKeep)
+ {
+ TBuf8<8> buf;
+ buf.SetLength(8);
+ SendReceive(EGetRotateBehaviour, TIpcArgs(&buf));
+ TInt* ptr = (TInt*)buf.Ptr();
+ TUint behav = ptr[0];
+ if (aNumberOfOldLogsToKeep)
+ {
+ *aNumberOfOldLogsToKeep = ptr[1];
+ }
+ return behav;
+ }
+
+EXPORT_C void RClogger::PersistSettings()
+ {
+ SendReceive(EPersistSettings, TIpcArgs());
+ }
+
+EXPORT_C void RClogger::ResetSettings()
+ {
+ SendReceive(EResetSettings, TIpcArgs());
+ }
+
+EXPORT_C void RClogger::Close()
+ {
+ iBuf.Close();
+ iBody.Close();
+ RSessionBase::Close();
+ }
+
+void RCloggerBody::DispatchCallbackL(TServerCallback& aCallback, TCallbackParser& aParser)
+ {
+ switch (aCallback.iCode)
+ {
+ case ETagEnabledChanged:
+ {
+ iSession.iEnabled = aParser.NextUint();
+
+ /*
+ if (iSession.iFlags & KTestTagEnabled)
+ {
+ iSession.iFlags &= ~KTestTagEnabled;
+ CActiveScheduler::Stop();
+ }
+ */
+ break;
+ }
+ }
+ }
+
+void RCloggerBody::ServerDiedL()
+ {
+ }
+
+EXPORT_C void RClogger::GetTagStatesL(CDesCArray*& aTagNames, RBuf8& aEnabled)
+ {
+ aTagNames = NULL;
+ aEnabled.Close();
+
+ TServerCallback cb;
+ TPckg<TServerCallback> cbPkg(cb);
+ User::LeaveIfError(SendReceive(EGetTagStates1, TIpcArgs(&cbPkg)));
+
+ RBuf8 context;
+ CleanupClosePushL(context);
+ if (cb.iContextLength)
+ {
+ context.CreateL(cb.iContextLength);
+ User::LeaveIfError(SendReceive(EGetTagStates2, TIpcArgs(&context)));
+ }
+ TCallbackParser parser(cb);
+ parser.SetContext(context);
+
+ TPtrC8 enabledBuf = parser.NextDesC8();
+ TInt numTags = enabledBuf.Length() / 4; // 32 bits per tag
+
+ CDesCArrayFlat* tags = new(ELeave) CDesCArrayFlat(numTags);
+ CleanupStack::PushL(tags);
+ while (numTags--)
+ {
+ tags->AppendL(parser.NextDesC());
+ }
+
+ aEnabled.CreateL(enabledBuf);
+ CleanupStack::Pop(tags);
+ CleanupStack::PopAndDestroy(&context);
+ aTagNames = tags;
+ }
+
+EXPORT_C void RClogger::SetTagStatesL(const CDesCArray* aTagNames, const TDesC8& aEnabled)
+ {
+ __ASSERT_ALWAYS(aTagNames, User::Leave(KErrArgument));
+ TInt count = aTagNames->MdcaCount();
+ __ASSERT_ALWAYS(count * 4 == aEnabled.Size(), User::Leave(KErrArgument)); // Number of tags must equal the number of 4-byte entries in aEnabled
+
+ CBufFlat* buf = CBufFlat::NewL(4096);
+ CleanupStack::PushL(buf);
+ RBufWriteStream stream(*buf);
+ CleanupClosePushL(stream);
+ stream.WriteInt32L(count);
+ //stream.WriteL(aEnabled);
+ stream << aEnabled;
+ for (TInt i = 0; i < count; i++)
+ {
+ const TPtrC name = aTagNames->MdcaPoint(i);
+ stream << name;
+ }
+ CleanupStack::PopAndDestroy(&stream); // Calls close, flushes buffer (probably not necessary with a RBufWriteStream)
+ TPtrC8 bufPtr = buf->Ptr(0);
+ User::LeaveIfError(SendReceive(ESetTagStates, TIpcArgs(&bufPtr)));
+ CleanupStack::PopAndDestroy(buf);
+ }
+
+EXPORT_C TInt RClogger::Reserved(TInt aCode, TAny*& aArg, TAny* aArg2)
+ {
+ TInt res = KErrNone;
+ if (aCode == 0xF10C10)
+ {
+ res = iBody.Connect(2, EFalse); // Used by flogger shim to access internals of clogger that would otherwise be hidden to it
+ }
+ else if (aCode == 0xC0FFEE)
+ {
+ RChunk*& chunk = reinterpret_cast<RChunk*&>(aArg);
+ TInt size = reinterpret_cast<TInt>(aArg2);
+ res = SendReceive(ECreatePerformanceLoggingChunk, TIpcArgs(size));
+ if (res > 0)
+ {
+ chunk->SetHandle(res);
+ res = KErrNone;
+ }
+ if (res == KErrNotSupported)
+ {
+ // Getting the chunk from the server is only possible if the debug router LDD is included, because there's no API
+ // to pass a chunk from a server to a client (without doing it kernel side). So if the LDD isn't present, we need
+ // to fall back to constructing it on our side and passing it to the server.
+ res = chunk->CreateGlobal(KNullDesC, size, size);
+ if (res == KErrNone)
+ {
+ res = SendReceive(ERegisterPerformanceLoggingChunk, TIpcArgs(*chunk));
+ }
+ }
+ }
+ else if (aCode == 0x5e55)
+ {
+ res = SendReceive(EStartSessionWriterServer);
+ }
+ else
+ {
+ User::Panic(_L("CloggerClient"), 0);
+ }
+ return res;
+ }
+
+EXPORT_C TInt RClogger::StaticReserved(TInt aCode, TAny*& aArg, TAny* aArg2)
+ {
+ TInt res = KErrNone;
+ if (aCode == 0xD0715)
+ {
+ RClogger clogger;
+ res = clogger.Connect(*reinterpret_cast<const TDesC*>(aArg2));
+ if (res == KErrNone)
+ {
+ aArg = reinterpret_cast<TAny*>(clogger.Handle());
+ }
+ }
+ else
+ {
+ User::Panic(_L("CloggerClient"), 0);
+ }
+ return res;
+ }
+
+EXPORT_C void RClogger::HexDump(TUint32 aLogMask, const TDesC8& aHeader, const TDesC8& aData)
+ {
+ if (!(iEnabled & aLogMask)) return;
+
+ SendReceive(EHexDump, TIpcArgs(&aHeader, &aData, User::NTickCount(), aLogMask));
+ }
+
+EXPORT_C void RClogger::HexDump(const TDesC8& aHeader, const TDesC8& aData)
+ {
+ HexDump(KNoLogMask, aHeader, aData);
+ }
+
+#ifndef PERFORMANCE_CRITICAL
+
+EXPORT_C void RClogger::StaticHexDump(TUint32 aLogMask, const TDesC8& aHeader, const TDesC8& aData)
+ {
+ CheckConnected();
+ clogger->HexDump(aLogMask, aHeader, aData);
+ }
+
+EXPORT_C void RClogger::StaticHexDump(const TDesC8& aHeader, const TDesC8& aData)
+ {
+ CheckConnected();
+ clogger->HexDump(KNoLogMask, aHeader, aData);
+ }
+
+#endif // PERFORMANCE_CRITICAL
+
+inline TBool RClogger::Enabled(TUint32 aMask)
+ {
+ // First check if anything's changed
+ TInt seq = 0;
+ TInt err = RProperty::Get(KCloggerUid, ESequenceNumber, seq);
+ if (err == KErrNone && seq > iSequence)
+ {
+ UpdateEnabled(seq);
+ }
+
+ if (!(iEnabled & aMask)) return EFalse;
+
+ return ETrue;
+ }
+
+void RClogger::UpdateEnabled(TInt aSequence)
+ {
+ iSequence = aSequence;
+ TPckg<TUint32> buf(iEnabled);
+ SendReceive(EUpdateEnabledMask, TIpcArgs(&buf));
+ iFlags &= ~KTestTagEnabled;
+ }
+
+EXPORT_C RCloggerLogConsumer::RCloggerLogConsumer()
+ : iResultBufferPtr(NULL, 0)
+ {
+ }
+
+EXPORT_C TInt RCloggerLogConsumer::Connect()
+ {
+ RClogger clogger;
+ TInt res = clogger.Connect();
+ if (res) return res;
+
+ TAny* arg1 = NULL;
+ res = clogger.Reserved(0x5E55, arg1, NULL); // This requests clogger to start the session writer server
+ clogger.Close();
+ if (res != KErrNone && res != KErrAlreadyExists)
+ {
+ return res;
+ }
+
+ res = CreateSession(KSessionLogServer, TVersion(0,0,0), 2);
+ if (res) return res;
+
+ res = SendReceive(ERegisterForLogMessages);
+ if (res < 0) return res;
+ iSharedChunk.SetHandle(res);
+ return KErrNone;
+ }
+
+EXPORT_C void RCloggerLogConsumer::GetNextLog(TRequestStatus& aStatus, TPtrC8& aResultBuffer)
+ {
+ // Server will update aResultBuffer to point to the appropriate location in iSharedChunk.
+ // It can do this because we pass in effectively TPckg<TPtrC8>(aResultBuffer) and tell the server
+ // what the shared chunk's Base address is in our address space. The server then computes what
+ // aResultBuffer should look like and writes it back
+ iResultBufferPtr.Set((TUint8*)&aResultBuffer, sizeof(TPtrC8), sizeof(TPtrC8));
+ SendReceive(EGetNextLog, TIpcArgs(&iResultBufferPtr, iSharedChunk.Base()), aStatus);
+ }
+
+EXPORT_C void RCloggerLogConsumer::CancelGetNextLog()
+ {
+ SendReceive(ECancelGetNextLog);
+ }
+
+EXPORT_C void RCloggerLogConsumer::Close()
+ {
+ iSharedChunk.Close();
+ RSessionBase::Close();
+ }
+
+EXPORT_C void Clogger_Slog(const char* aFmt, ...)
+ {
+ VA_LIST list;
+ VA_START(list, aFmt);
+ TPtrC8 fmt((const TUint8*)aFmt);
+ RClogger::SlogList(fmt, list);
+ VA_END(list);
+ }