diff -r 000000000000 -r a41df078684a kerneltest/e32test/debug/d_traceredirect.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/debug/d_traceredirect.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,252 @@ +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "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: +// e32test\debug\d_traceredirect.cpp +// Trace redirection LDD +// This device driver captures RDebug::Prints from user side code using the +// debug event handler. +// The text can be retrieved with the RTraceRedirect::NextTrace() function +// TODO: Modify this LDD to use asynchronous retrieval. +// +// + +#include +#include +#include "d_traceredirect.h" + +_LIT(KLddName,"D_TRACEREDIRECT"); + +const TInt KMajorVersionNumber = 0; +const TInt KMinorVersionNumber = 1; +const TInt KBuildVersionNumber = 1; + +const TInt KMaxTraceEventLength=100; +const TInt KTraceBufferSize=256; +const TInt KTraceBufferSizeMask=0xff; + + +class TTraceEvent + { +public: + TInt iLength; + TUint16 iText[KMaxTraceEventLength]; + }; + +class DTraceRedirect; + +class DTraceEventHandler : public DKernelEventHandler + { +public: + DTraceEventHandler() + : DKernelEventHandler(HandleEvent, this) {} + TInt Create(DLogicalDevice* aDevice); + ~DTraceEventHandler(); + TInt GetNextEvent(TAny *outdes); +private: + static TUint HandleEvent(TKernelEvent aEvent, TAny* a1, TAny* a2, TAny* aThis); + void HandleUserTrace(TText* aStr, TInt aLen); +public: + DTraceRedirect *iChannel; + TTraceEvent *iTraceBuffer; + TInt iFront; + TInt iBack; + DMutex* iLock; // serialise calls to handler + DLogicalDevice* iDevice; // open reference to LDD for avoiding lifetime issues + }; + +class DTraceRedirectFactory : public DLogicalDevice + { +public: + DTraceRedirectFactory(); + virtual TInt Install(); + virtual void GetCaps(TDes8& aDes) const; + virtual TInt Create(DLogicalChannelBase*& aChannel); + }; + +class DTraceRedirect : public DLogicalChannelBase + { +public: + virtual ~DTraceRedirect(); +protected: + virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); + virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2); + TInt NextTrace(TAny *outdes); +public: + DTraceEventHandler *iEventHandler; + }; + + + +DECLARE_STANDARD_LDD() + { + return new DTraceRedirectFactory; + } + +// +// DTraceRedirectFactory +// + +DTraceRedirectFactory::DTraceRedirectFactory() + { + iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); + } + +TInt DTraceRedirectFactory::Create(DLogicalChannelBase*& aChannel) +/** + Create a new DSchedhookTest on this logical device +*/ + { + aChannel=new DTraceRedirect; + return aChannel ? KErrNone : KErrNoMemory; + } + +TInt DTraceRedirectFactory::Install() +/** + Install the LDD - overriding pure virtual +*/ + { + return SetName(&KLddName); + } + +void DTraceRedirectFactory::GetCaps(TDes8& aDes) const +/** + Get capabilities - overriding pure virtual +*/ + { + TCapsTestV01 b; + b.iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); + Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b)); + } + + +// +// DSchedhookTest +// + +TInt DTraceRedirect::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer) +/** + Create channel +*/ + { + if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer)) + return KErrNotSupported; + + iEventHandler=new DTraceEventHandler; + if (iEventHandler == NULL) + return KErrNoMemory; + return iEventHandler->Create(iDevice); + } + +DTraceRedirect::~DTraceRedirect() + { + iEventHandler->Close(); + } + +TInt DTraceEventHandler::Create(DLogicalDevice* aDevice) + { + TInt r; + r = aDevice->Open(); + if (r != KErrNone) + return r; + iDevice = aDevice; + iFront=0; + iBack=0; + iTraceBuffer=new TTraceEvent[KTraceBufferSize]; + if (iTraceBuffer == NULL) + return KErrNoMemory; + _LIT(KDataMutexName, "EventHandlerMutex"); + r = Kern::MutexCreate(iLock, KDataMutexName, KMutexOrdDebug); + if (r != KErrNone) + return r; + return Add(); + } + +DTraceEventHandler::~DTraceEventHandler() + { + if (iLock) + iLock->Close(NULL); + delete [] iTraceBuffer; + if (iDevice) + iDevice->Close(NULL); + } + +TUint DTraceEventHandler::HandleEvent(TKernelEvent aEvent, TAny* a1, TAny* a2, TAny* aThis) + { + if (aEvent==EEventUserTrace) + { + ((DTraceEventHandler*)aThis)->HandleUserTrace((TText*)a1, (TInt)a2); + return ETraceHandled; + } + return ERunNext; + } + +// called in CS +void DTraceEventHandler::HandleUserTrace(TText* aStr, TInt aLen) + { + Kern::MutexWait(*iLock); + TInt frontplus1=(iFront+1)&KTraceBufferSizeMask; + if (frontplus1!=iBack) // check overflow + { + TTraceEvent *e=&iTraceBuffer[iFront]; + XTRAPD(r, XT_DEFAULT, kumemget(e->iText, aStr, aLen*2)); + if (r == KErrNone) + e->iLength=aLen; + else + e->iLength = -1; // an error will be reported in GetNextEvent() + iFront=frontplus1; + } + Kern::MutexSignal(*iLock); + } + +TInt DTraceEventHandler::GetNextEvent(TAny *outdes) + { + + if (iBack==iFront) + { // buffer empty + return KErrNone; + } + TTraceEvent *e=&iTraceBuffer[iBack]; + if (e->iLength == -1) + return KErrCorrupt; // earlier error when copying trace data from userland + TPtr ptr((TUint8*)e->iText, e->iLength, e->iLength); + TInt r=KErrNone; + Kern::KUDesPut(*(TDes *)outdes, ptr); + iBack=(iBack+1)&KTraceBufferSizeMask; + return r; + } + +TInt DTraceRedirect::NextTrace(TAny *outdes) + { + + TInt r=iEventHandler->GetNextEvent(outdes); + return r; + } + +TInt DTraceRedirect::Request(TInt aFunction, TAny* a1, TAny* /*a2*/) +/** + Handle requests from the test program +*/ + { + TInt r=KErrNone; + switch (aFunction) + { + case RTraceRedirect::ENextTrace: + r=NextTrace(a1); + break; + default: + r=KErrNotSupported; + break; + } + return r; + } +