kerneltest/e32test/debug/d_logtofile.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32test\debug\d_logtofile.cpp
       
    15 // d_logtofile.ldd is kernel side of t_logtofile application that tests *
       
    16 // trace handler hook (TTraceHandler). See t_logtofile.cpp for details. *
       
    17 // 
       
    18 //
       
    19 
       
    20 #include "d_logtofile.h"
       
    21 #include <kernel/kern_priv.h>
       
    22 
       
    23 _LIT(PatternInfo, "Pattern:");
       
    24 _LIT(BufferInfo, "Buffer Size:");
       
    25 _LIT(FastCounterInfo, "Fast couner freq:");
       
    26 const TInt MaxLogSize=300;
       
    27 ///////////////////////////////////////////////////////////////////////
       
    28 class DLogToFile : public DLogicalChannelBase
       
    29 	{
       
    30 public:
       
    31 	DLogToFile();
       
    32 	~DLogToFile();
       
    33 	static TBool Handler (const TDesC8& aText, TTraceSource aTraceSource);
       
    34 protected:
       
    35 	virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
       
    36 	virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2);
       
    37 private:
       
    38 	TInt CreateChunk();
       
    39 	void Start();
       
    40 	TInt Stop();
       
    41 	void RemoveChunk();
       
    42 
       
    43 private:
       
    44     DChunk* iChunk;					/**Shared chunk*/
       
    45     TLinAddr iChunkKernelAddr;		/**Kernel base address of the chunk*/
       
    46     TUint32 iChunkMapAttr;			/**Mapping attributes of the chunk*/
       
    47 	TBool iBufferFull;				/**Chunk full indication*/
       
    48 	TText8* iCurrent;				/**Current pointer to the chunk space*/
       
    49 	TChunkCreateStr iChunkCreateStr;/**Input arguments(matching pattern and the chunk size) from user side*/
       
    50 	TTraceHandler iOldHook;			/**Previous trace logging hook*/
       
    51 	};
       
    52 
       
    53 DLogToFile* Logger;
       
    54 
       
    55 DLogToFile::DLogToFile() 
       
    56 	{
       
    57 	}
       
    58 
       
    59 DLogToFile::~DLogToFile()
       
    60 	{
       
    61 	Logger = NULL;
       
    62 	}
       
    63 
       
    64 /*
       
    65 Trace handler hook.
       
    66 Should be able to run in any content (including ISR).
       
    67 @return EFalse, always and that way suppresses debug logging to serial port.
       
    68 */
       
    69 TBool DLogToFile::Handler (const TDesC8& aText, TTraceSource aTraceSource)
       
    70 	{
       
    71 	if(Logger->iBufferFull)
       
    72 		return ETrue;
       
    73 
       
    74 	TInt irq=NKern::DisableAllInterrupts(); //Disable interrupts to prevent loggings overlapping each other.
       
    75 
       
    76 	if (aText.Length() < Logger->iChunkCreateStr.iPattern.Length())
       
    77 		{
       
    78 		NKern::RestoreInterrupts(irq);
       
    79 		return ETrue; //The log is too short to match the pattern
       
    80 		}
       
    81 	TPtrC8 ptr( aText.Ptr(), Logger->iChunkCreateStr.iPattern.Length());
       
    82 	if (ptr != Logger->iChunkCreateStr.iPattern) //Compare the pattern against the start of the log
       
    83 		{
       
    84 		NKern::RestoreInterrupts(irq);
       
    85 		return ETrue; //Does not match
       
    86 		}
       
    87 
       
    88 	TBuf8<20> fcBuffer;
       
    89 	fcBuffer.AppendNum(NKern::FastCounter());//If it was a real tool, we should not do this here.
       
    90 
       
    91 	memcpy (Logger->iCurrent, fcBuffer.Ptr(), fcBuffer.Length());
       
    92 	Logger->iCurrent+=fcBuffer.Length();
       
    93 	*(Logger->iCurrent++) = '\t';
       
    94 
       
    95 	switch(aTraceSource)
       
    96 		{
       
    97 		case EKernelTrace:
       
    98 			{
       
    99 			*(Logger->iCurrent++) = 'K';
       
   100 			*(Logger->iCurrent++) = '\t';
       
   101 			memcpy (Logger->iCurrent, aText.Ptr(),aText.Length());
       
   102 			break;	
       
   103 			}
       
   104 
       
   105 		case EPlatSecTrace:
       
   106 			{
       
   107 			*(Logger->iCurrent++) = 'P';
       
   108 			*(Logger->iCurrent++) = '\t';
       
   109 			//PlatSec log could be of any size. Additional checking required:
       
   110 			if ((TInt)Logger->iCurrent > (TInt)(Logger->iChunkKernelAddr + Logger->iChunkCreateStr.iSize - aText.Length()))
       
   111 				{
       
   112 				Logger->iBufferFull = ETrue;
       
   113 				break;
       
   114 				}
       
   115 			memcpy (Logger->iCurrent, aText.Ptr(),aText.Length());
       
   116 			break;	
       
   117 			}
       
   118 		
       
   119 		case EUserTrace:
       
   120 			{
       
   121 			*(Logger->iCurrent++) = 'U';
       
   122 			*(Logger->iCurrent++) = '\t';
       
   123 			memcpy(Logger->iCurrent, aText.Ptr(),aText.Length());
       
   124 			break;	
       
   125 			}
       
   126 		
       
   127 		default:
       
   128 			break;
       
   129 		}
       
   130 
       
   131 	Logger->iCurrent+=aText.Length();
       
   132 	*(Logger->iCurrent++) = '\n';
       
   133 
       
   134 	if ((TInt)Logger->iCurrent > (TInt)(Logger->iChunkKernelAddr + Logger->iChunkCreateStr.iSize - MaxLogSize))
       
   135 		Logger->iBufferFull = ETrue;
       
   136 
       
   137 	NKern::RestoreInterrupts(irq);
       
   138 
       
   139 	return ETrue;
       
   140 	}
       
   141 
       
   142 /**
       
   143 Creates the channel
       
   144 */
       
   145 TInt DLogToFile::DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& /*aVer*/)
       
   146 	{
       
   147 	return KErrNone;
       
   148 	}
       
   149 
       
   150 /*
       
   151 Creates chunk and opens another chunk handle for user side.
       
   152 Returns user side handle.
       
   153 */
       
   154 TInt DLogToFile::CreateChunk()
       
   155 {
       
   156 	TInt r;
       
   157     TChunkCreateInfo info;
       
   158     info.iType         = TChunkCreateInfo::ESharedKernelSingle;
       
   159     info.iMaxSize      = iChunkCreateStr.iSize;//This is hard coded to 64K. No need to round to page size.
       
   160 #ifdef __EPOC32__
       
   161     info.iMapAttr      = (TInt)EMapAttrFullyBlocking; // Full caching
       
   162 #endif
       
   163     info.iOwnsMemory   = ETrue; // Use memory from system's free pool
       
   164     info.iDestroyedDfc = NULL;
       
   165 
       
   166 	NKern::ThreadEnterCS();
       
   167     if (KErrNone != (r = Kern::ChunkCreate(info, iChunk, iChunkKernelAddr, iChunkMapAttr)))
       
   168 		{
       
   169 		NKern::ThreadLeaveCS();
       
   170 		return r;
       
   171 		}
       
   172 	r = Kern::ChunkCommit(iChunk,0,iChunkCreateStr.iSize);
       
   173     if(r!=KErrNone)
       
   174         {
       
   175 		Kern::ChunkClose(iChunk);
       
   176 		NKern::ThreadLeaveCS();
       
   177 		return r;
       
   178 		}
       
   179 	r = Kern::MakeHandleAndOpen(NULL, iChunk); 
       
   180     if(r < KErrNone)
       
   181         {
       
   182 		Kern::ChunkClose(iChunk);
       
   183 		NKern::ThreadLeaveCS();
       
   184 		return r;
       
   185 		}
       
   186 	NKern::ThreadLeaveCS();
       
   187 	iCurrent = (TText8*)iChunkKernelAddr;
       
   188 	return r;
       
   189 }
       
   190 
       
   191 
       
   192 /*
       
   193 Logs input parameters info into chunk and starts logging.
       
   194 */
       
   195 void DLogToFile::Start()
       
   196 	{
       
   197 	//Log pattern info
       
   198 	memcpy (Logger->iCurrent, ((const TDesC&)PatternInfo).Ptr(), ((const TDesC&)PatternInfo).Length());
       
   199 	iCurrent+=((const TDesC&)PatternInfo).Length();
       
   200 	*(Logger->iCurrent++) = '\t';
       
   201 	memcpy (Logger->iCurrent, iChunkCreateStr.iPattern.Ptr(), iChunkCreateStr.iPattern.Length());
       
   202 	Logger->iCurrent += iChunkCreateStr.iPattern.Length();
       
   203 	*(iCurrent++) = '\n';
       
   204 
       
   205 	//Log buffern info
       
   206 	memcpy (iCurrent, ((const TDesC&)BufferInfo).Ptr(), ((const TDesC&)BufferInfo).Length());
       
   207 	iCurrent+=((const TDesC&)BufferInfo).Length();
       
   208 	*(Logger->iCurrent++) = '\t';
       
   209 	TBuf8<20> buf;
       
   210 	buf.AppendNum(iChunkCreateStr.iSize);
       
   211 	memcpy (iCurrent, buf.Ptr(), buf.Length());
       
   212 	iCurrent+=buf.Length();
       
   213 	*(iCurrent++) = '\n';
       
   214 
       
   215 	//Log fast counter info
       
   216 	memcpy (iCurrent, ((const TDesC&)FastCounterInfo).Ptr(), ((const TDesC&)FastCounterInfo).Length());
       
   217 	iCurrent+=((const TDesC&)FastCounterInfo).Length();
       
   218 	*(iCurrent++) = '\t';
       
   219 	buf.SetLength(0);
       
   220 	buf.AppendNum(NKern::FastCounterFrequency());
       
   221 	memcpy (iCurrent, buf.Ptr(), buf.Length());
       
   222 	iCurrent+=buf.Length();
       
   223 	*(iCurrent++) = '\n';
       
   224 
       
   225 	//Start logging	
       
   226 	iOldHook = Kern::SetTraceHandler(DLogToFile::Handler);
       
   227 	}
       
   228 
       
   229 /*
       
   230 Stops logging into chunk. Returns the size of the log.
       
   231 */
       
   232 TInt DLogToFile::Stop()
       
   233 	{
       
   234 	//Setting the old hook is always risky. Is the old hook still valid?
       
   235 	//We'll do it for the sake of testing.
       
   236 	Kern::SetTraceHandler(iOldHook);
       
   237 	return (TInt)Logger->iCurrent  - Logger->iChunkKernelAddr;
       
   238 	}
       
   239 
       
   240 /*
       
   241 Closes the shared chunk
       
   242 */
       
   243 void DLogToFile::RemoveChunk()
       
   244 {
       
   245 	NKern::ThreadEnterCS();
       
   246 	//It has been a while since we removed the hook. It should be safe to close the chunk now. 
       
   247 	Kern::ChunkClose(iChunk);
       
   248 	NKern::ThreadLeaveCS();
       
   249 }
       
   250 
       
   251 /**
       
   252 User side request entry point.
       
   253 */
       
   254 TInt DLogToFile::Request(TInt aFunction, TAny* a1, TAny* /*a2*/)
       
   255 	{
       
   256 	TInt r = KErrNone;
       
   257 	switch (aFunction)
       
   258 	{
       
   259 		case RLogToFileDevice::EControlCreateChunk:
       
   260 			{
       
   261 			kumemget(&iChunkCreateStr, a1,sizeof(TChunkCreateStr));
       
   262 			r = CreateChunk();
       
   263 			break;
       
   264 			}
       
   265 		case RLogToFileDevice::EControlStart:
       
   266 			{
       
   267 			Start();
       
   268 			break;
       
   269 			}
       
   270 		case RLogToFileDevice::EControlStop:
       
   271 			{
       
   272 			r = Stop();
       
   273 			break;
       
   274 			}
       
   275 		case RLogToFileDevice::EControlRemoveChunk:
       
   276 			{
       
   277 			RemoveChunk();
       
   278 			break;
       
   279 			}
       
   280 		default:
       
   281 			r=KErrNotSupported;
       
   282 			break;
       
   283 		}
       
   284 	return r;
       
   285 	}
       
   286 
       
   287 //////////////////////////////////////////
       
   288 class DTestFactory : public DLogicalDevice
       
   289 	{
       
   290 public:
       
   291 	DTestFactory();
       
   292 	// from DLogicalDevice
       
   293 	virtual TInt Install();
       
   294 	virtual void GetCaps(TDes8& aDes) const;
       
   295 	virtual TInt Create(DLogicalChannelBase*& aChannel);
       
   296 	};
       
   297 
       
   298 DTestFactory::DTestFactory()
       
   299     {
       
   300     iParseMask = KDeviceAllowUnit;
       
   301     iUnitsMask = 0x3;
       
   302     }
       
   303 
       
   304 TInt DTestFactory::Create(DLogicalChannelBase*& aChannel)
       
   305     {
       
   306 	Logger = new DLogToFile;
       
   307 	aChannel = Logger;
       
   308 	return (aChannel ? KErrNone : KErrNoMemory);
       
   309     }
       
   310 
       
   311 TInt DTestFactory::Install()
       
   312     {
       
   313     return SetName(&KLogToFileName);
       
   314     }
       
   315 
       
   316 void DTestFactory::GetCaps(TDes8& /*aDes*/) const
       
   317     {
       
   318     }
       
   319 
       
   320 DECLARE_STANDARD_LDD()
       
   321 	{
       
   322     return new DTestFactory;
       
   323 	}