tracesrv/tracecore/btrace_handler/src/BTraceOstCategoryHandler.cpp
changeset 56 aa2539c91954
equal deleted inserted replaced
54:a151135b0cf9 56:aa2539c91954
       
     1 // Copyright (c) 2007-2010 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 "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 // Trace Core 
       
    15 //
       
    16 
       
    17 #include "TraceCore.h"
       
    18 #include "BTraceOstCategoryHandler.h"
       
    19 #include "BTraceOstCategoryBitmap.h"
       
    20 #include "TraceCoreWriter.h"
       
    21 #include "TraceCoreDebug.h"
       
    22 #include "TraceCoreConstants.h"
       
    23 #include "OstTraceDefinitions.h"
       
    24 #ifdef OST_TRACE_COMPILER_IN_USE
       
    25 #include "BTraceOstCategoryHandlerTraces.h"
       
    26 #endif
       
    27 
       
    28 #ifndef __SMP__
       
    29 /**
       
    30  * Length of Trace group ID + Trace ID in the MultiPart traces data part
       
    31  */
       
    32 const TUint KTraceGroupIdLen = 4;
       
    33 
       
    34 /**
       
    35  * Length of BTrace header
       
    36  */
       
    37 const TUint KBTraceHeaderLen = 4;
       
    38 
       
    39 /**
       
    40  * Length of single BTrace variable
       
    41  */
       
    42 const TUint KBTraceVariableLen = 4;
       
    43 
       
    44 /**
       
    45  * Four bytes
       
    46  */
       
    47 const TUint KFourBytes = 4;
       
    48 
       
    49 #endif // !__SMP__
       
    50 /**
       
    51  * Group value in GroupId
       
    52  */
       
    53 const TUint32 KGroupMask = 0xffff0000;
       
    54 
       
    55 
       
    56 /**
       
    57  * Constructor
       
    58  */
       
    59 DBTraceOstCategoryHandler::DBTraceOstCategoryHandler()
       
    60 : iAllTracesDeactivated( ETrue )
       
    61 , iCacheItem1( iComponentGroupCache )   // One "cache" item contains ComponentId, groupId, and activation info (3*32bit)
       
    62 , iCacheItem2( iComponentGroupCache+3 ) //CodForChk_Dis_Magic
       
    63 , iCacheItem3( iComponentGroupCache+6 ) //CodForChk_Dis_Magic
       
    64 , iCacheItem4( iComponentGroupCache+9 ) //CodForChk_Dis_Magic
       
    65 , iOstTraceBitmap( NULL )
       
    66     {
       
    67     }
       
    68 
       
    69 
       
    70 /**
       
    71  * Destructor
       
    72  */
       
    73 DBTraceOstCategoryHandler::~DBTraceOstCategoryHandler()
       
    74     {
       
    75 	// Delete trace bitmap
       
    76 	delete iOstTraceBitmap;
       
    77     }
       
    78 
       
    79 
       
    80 /**
       
    81  * Initializes this handler
       
    82  *
       
    83  * @param aHandler The BTrace handler
       
    84  */
       
    85 TInt DBTraceOstCategoryHandler::Init()
       
    86     {    
       
    87     TInt ret = KErrNone;
       
    88 
       
    89 #ifdef __SMP__	    
       
    90     for( TInt i = 0; i<MAX_MULTIPART_TRACES; i++ )
       
    91         {
       
    92         iMultipartArray[i].iMultiPartId = 0xffffffff;
       
    93         iFreeList[i] = 1; // Set Free
       
    94         }
       
    95 #endif // __SMP__
       
    96     
       
    97     for (TUint category = KMaxKernelCategory + 1; category <= KMaxCategory; category++)
       
    98     	{
       
    99     	if (category != KCategoryNokiaBranchCoverage) // Is this exception needed? 
       
   100     		{
       
   101     		ret = AddCategory( category );
       
   102         	if (ret != KErrNone)
       
   103         		{
       
   104         		break;
       
   105         		}
       
   106     		}
       
   107     	}
       
   108     
       
   109     if (ret == KErrNone)
       
   110     	{    
       
   111 		iOstTraceBitmap = new DBTraceOstCategoryBitmap( this );	
       
   112 		if ( iOstTraceBitmap != NULL )
       
   113 			{
       
   114 			// Initialize TraceBitmap
       
   115 			ret = iOstTraceBitmap->Init();
       
   116 			if ( ret == KErrNone )
       
   117 				{
       
   118 				ret = iOstTraceBitmap->RegisterActivationNotification( *this );
       
   119 				if ( ret == KErrNone )
       
   120 					{
       
   121 	                ret = Register();
       
   122 	                if ( ret == KErrNone )
       
   123 	                    {
       
   124 	                    TC_TRACE( ETraceLevelNormal, Kern::Printf( 
       
   125 	                            "DBTraceAutogenCategoryHandler::Init - Register OK" ) );
       
   126 	                    }
       
   127 	                // Register failed
       
   128 	                else
       
   129 						{
       
   130 						ret = KErrGeneral;
       
   131 						}
       
   132 					}
       
   133 				// RegisterActivationNotification failed
       
   134 				else
       
   135 					{
       
   136 					ret = KErrGeneral;
       
   137 					}
       
   138 				}
       
   139 			}
       
   140 		// Memory allocation failed
       
   141 		else
       
   142 			{
       
   143 			TC_TRACE( ETraceLevelError, Kern::Printf( "DBTraceOstCategoryHandler::Init - Memory allocation failed" ) );
       
   144 			ret = KErrNoMemory;
       
   145 			}
       
   146     	}
       
   147     TC_TRACE( ETraceLevelError, Kern::Printf( "<DBTraceOstCategoryHandler::Init() - %d", ret ) );  
       
   148     return ret;
       
   149     }
       
   150     
       
   151 /**
       
   152  * Set settings
       
   153  * 
       
   154  * @param aSettings Settings
       
   155  */
       
   156 void DBTraceOstCategoryHandler::SetSettings( DTraceCoreSettings* aSettings )
       
   157 	{
       
   158     OstTrace1( TRACE_FLOW, DBTRACEOSTCATEGORYHANDLER_SETSETTINGS_ENTRY, "> DBTraceOstCategoryHandler::SetSettings 0x%x", ( TUint )( aSettings ) );
       
   159     DBTraceCategoryHandler::SetSettings( aSettings );
       
   160     if ( iOstTraceBitmap != NULL && aSettings != NULL )
       
   161         {
       
   162         // Reads the bitmap configuration from settings
       
   163         iOstTraceBitmap->ReadFromSettings( *aSettings );
       
   164         }
       
   165 	}
       
   166 
       
   167 /**
       
   168  * Notification that the activation state has changed.
       
   169  * 
       
   170  * @param aActivation the activation interface that was updated
       
   171  * @param aFromSettings ETrue if activation was due to settings read, EFalse if from some other source
       
   172  * @param aComponentId Component ID of the activation
       
   173  */
       
   174 void DBTraceOstCategoryHandler::ActivationChanged( MTraceCoreActivation& aActivation, TBool aFromSettings,
       
   175         TUint32 /*aComponentId*/)
       
   176     {
       
   177     OstTrace1( TRACE_FLOW, DBTRACEOSTCATEGORYHANDLER_ACTIVATIONCHANGED_ENTRY, "> DBTraceOstCategoryHandler::ActivationChanged 0x%x", ( TUint )&( aActivation ) );
       
   178     
       
   179     // Call the bitmap to write changes to settings saver
       
   180     if ( !aFromSettings )
       
   181         {
       
   182         if ( iSettings != NULL )
       
   183             {
       
   184             aActivation.WriteToSettings( *iSettings );
       
   185             }
       
   186         }
       
   187     }
       
   188 
       
   189 /**
       
   190  * Handler for KCategoryNokiaOst
       
   191  *
       
   192  * @param aHeader BTrace header
       
   193  * @param aHeader2 Extra header data
       
   194  * @param aContext The thread context in which this function was called
       
   195  * @param a1 The first trace parameter
       
   196  * @param a2 The second trace parameter
       
   197  * @param a3 The third trace parameter
       
   198  * @param aExtra Extra trace data
       
   199  * @param aPc The program counter value
       
   200  * @return ETrue if trace was processed, EFalse if not
       
   201  */
       
   202 TBool DBTraceOstCategoryHandler::HandleFrame( TUint32 aHeader, TUint32 aHeader2, const TUint32 aContext, 
       
   203                                               const TUint32 a1, const TUint32 a2, const TUint32 a3, 
       
   204                                               const TUint32 aExtra, const TUint32 aPc )
       
   205     {
       
   206     TBool retval(EFalse);
       
   207     if ( iWriter != NULL && !iAllTracesDeactivated )
       
   208         {
       
   209         __ASSERT_DEBUG( iOstTraceBitmap != NULL, 
       
   210                 Kern::Fault( "DBTraceOstCategoryHandler::HandleFrame - NULL", KErrGeneral ) );
       
   211         
       
   212         // Check if tracing is certified
       
   213         DTraceCore* tracecore = DTraceCore::GetInstance();
       
   214         if (!tracecore || !tracecore->IsTraceCertified())
       
   215             {
       
   216             return EFalse;
       
   217             }
       
   218         
       
   219         // Check if the trace is a multipart trace
       
   220         TBool isMultiPart = CheckMultiPart(aHeader, aHeader2);
       
   221         
       
   222         if (isMultiPart)
       
   223             {
       
   224 		
       
   225 #ifdef __SMP__
       
   226             // Handle the multipart trace
       
   227             retval = HandleMultiPart(aHeader, aHeader2, aContext, a1, a2, a3, aExtra, aPc);
       
   228 #else
       
   229             // Handle the multipart trace. Returns EFalse if trace is not activated.
       
   230             TBool isActivatedMultiPart = HandleMultiPart(aHeader, aHeader2, aContext, a1, a2, a3, aExtra, aPc);
       
   231             if (isActivatedMultiPart)
       
   232                 {
       
   233                 retval = ETrue;    
       
   234                 }
       
   235             else
       
   236                 {
       
   237                 retval = EFalse;
       
   238                 }
       
   239 #endif // __SMP__
       
   240 
       
   241             }
       
   242         // Not a multipart trace
       
   243         else
       
   244             {
       
   245         
       
   246             // Take group and leave trace id away
       
   247             TUint32 group = a2 & KGroupMask;
       
   248 
       
   249             if ((*iCacheItem1) == a1 && (*(iCacheItem1 + 1)) == group)
       
   250                 {
       
   251                 retval = *(iCacheItem1 + 2); //CodForChk_Dis_Magic
       
   252                 }
       
   253             else if ((*iCacheItem2) == a1 && (*(iCacheItem2 + 1)) == group)
       
   254                 {
       
   255                 retval = *(iCacheItem2 + 2); //CodForChk_Dis_Magic
       
   256                 }
       
   257             else if ((*iCacheItem3) == a1 && (*(iCacheItem3 + 1)) == group)
       
   258                 {
       
   259                 retval = *(iCacheItem3 + 2); //CodForChk_Dis_Magic
       
   260                 }
       
   261             else if ((*iCacheItem4) == a1 && (*(iCacheItem4 + 1)) == group)
       
   262                 {
       
   263                 retval = *(iCacheItem4 + 2); //CodForChk_Dis_Magic
       
   264                 }
       
   265             else
       
   266                 {
       
   267                 retval = iOstTraceBitmap->IsTraceActivated(a1, a2);
       
   268 
       
   269                 iTemp = iCacheItem1;
       
   270                 iCacheItem1 = iCacheItem4;
       
   271                 iCacheItem4 = iCacheItem3;
       
   272                 iCacheItem3 = iCacheItem2;
       
   273                 iCacheItem2 = iTemp;
       
   274                 *iCacheItem1 = a1;
       
   275                 *(iCacheItem1 + 1) = group;
       
   276                 *(iCacheItem1 + 2) = retval;
       
   277 
       
   278                 }
       
   279                 
       
   280             if ( ( ( aHeader >> ( BTrace::ESubCategoryIndex * KByteSize ) ) & KByteMask ) == EOstTraceActivationQuery )
       
   281                 {
       
   282                 //Trace from here is not allowed
       
   283                 }
       
   284             else if ( retval )
       
   285                 {                
       
   286                 CheckDroppedTrace( aHeader ); // Update header if there is a dropped trace
       
   287                 TUint8 recordSize = static_cast< TUint8 >( ( aHeader >> ( BTrace::ESizeIndex * KByteSize ) ) & KByteMask );
       
   288                 iWriter->WriteTraceCoreFrame( a1, a2, aHeader, aHeader2, aContext, a1, a2, a3, aExtra, aPc, recordSize );
       
   289                 }
       
   290             }
       
   291         }
       
   292     else
       
   293         {        
       
   294         if( iWriter == NULL )
       
   295             {
       
   296             //Trace from here is not allowed
       
   297             retval = EFalse;
       
   298             }
       
   299             
       
   300         }
       
   301 
       
   302     //Trace from here is not allowed
       
   303     return retval;
       
   304     }
       
   305    
       
   306 /**
       
   307  * Checks if the given trace is a Multipart trace
       
   308  *
       
   309  * @param aHeader Header data
       
   310  * @param aHeader2 Extra header data
       
   311  * @return ETrue if trace is a Multipart trace, EFalse if not
       
   312  */
       
   313 inline TBool DBTraceOstCategoryHandler::CheckMultiPart( TUint32 aHeader, TUint32 aHeader2 )
       
   314     {
       
   315     TBool retval = EFalse;
       
   316     TUint8 flags = static_cast< TUint8 >( ( aHeader >> ( BTrace::EFlagsIndex * KByteSize ) ) & KByteMask );
       
   317     if (flags & BTrace::EHeader2Present)
       
   318         {
       
   319         // First, middle or last part of Multipart trace
       
   320         if (aHeader2 & BTrace::EMultipartFlagMask)
       
   321             {
       
   322             retval = ETrue;
       
   323             }
       
   324         }
       
   325     
       
   326     //Trace from here is not allowed
       
   327     return retval;
       
   328     }
       
   329 
       
   330 /**
       
   331  * Checks if there is a dropped trace and updates header if so
       
   332  *
       
   333  * @param aHeader Header data
       
   334  */
       
   335 inline TBool DBTraceOstCategoryHandler::CheckDroppedTrace( TUint32& aHeader )
       
   336     {
       
   337     TBool ret(EFalse);
       
   338     
       
   339     DTraceCore* tracecore = DTraceCore::GetInstance();
       
   340     if (tracecore && (tracecore->PreviousTraceDropped())) //if previous trace was dropped 
       
   341         {
       
   342         //set flags back to EFalse first
       
   343         tracecore->SetPreviousTraceDropped(EFalse);
       
   344         
       
   345         //set missing flag in BTrace
       
   346         aHeader |= BTrace::EMissingRecord<<(BTrace::EFlagsIndex * KByteSize);
       
   347         
       
   348         ret = ETrue;
       
   349         }
       
   350     
       
   351     return ret;
       
   352     }
       
   353 
       
   354 #ifdef __SMP__
       
   355 
       
   356 
       
   357 TInt DBTraceOstCategoryHandler::Find( TUint32 aMultiPartId )
       
   358     {
       
   359     TInt ret(KErrNotFound);
       
   360     for( TInt i = 0; i<MAX_MULTIPART_TRACES; i++ )
       
   361         {
       
   362         if( iMultipartArray[i].iMultiPartId == aMultiPartId )
       
   363             {
       
   364             ret = i;
       
   365             break;
       
   366             }
       
   367         }
       
   368     return ret;
       
   369     }
       
   370     
       
   371 void DBTraceOstCategoryHandler::Remove( TUint32 aIndex )
       
   372     {
       
   373     iMultipartArray[aIndex].iMultiPartId = 0xffffffff;    
       
   374     iFreeList[aIndex] = 1; // Set free
       
   375     }
       
   376     
       
   377     /**
       
   378      * 
       
   379      * @return KErrNone if added, otherwise KErrNotFound.
       
   380      */
       
   381 TInt DBTraceOstCategoryHandler::InsertIfNotExist( TMultiPartActivationInfo &aMultiPartTrace )
       
   382     {
       
   383     TInt ret = Find( aMultiPartTrace.iMultiPartId );
       
   384     if( ret == KErrNotFound )
       
   385         {
       
   386         // Find free slot
       
   387         for( TInt freeIndex = 0; freeIndex<MAX_MULTIPART_TRACES; freeIndex++ )
       
   388             {
       
   389             if( iFreeList[freeIndex] )
       
   390                 {
       
   391                 iFreeList[freeIndex] = 0; // Set reserved
       
   392                 iMultipartArray[freeIndex].iComponentId = aMultiPartTrace.iComponentId;
       
   393                 iMultipartArray[freeIndex].iTraceWord = aMultiPartTrace.iTraceWord;
       
   394                 iMultipartArray[freeIndex].iMultiPartId = aMultiPartTrace.iMultiPartId;
       
   395                 ret = KErrNone;
       
   396                 break;
       
   397                 }
       
   398             }
       
   399 
       
   400         }
       
   401     return ret;
       
   402     }
       
   403  
       
   404 
       
   405 /**
       
   406  * Handles this Multipart trace
       
   407  *
       
   408  * @param aHeader BTrace header
       
   409  * @param aHeader2 Extra header data
       
   410  * @param aContext The thread context in which this function was called
       
   411  * @param a1 First parameter
       
   412  * @param a2 Second parameter
       
   413  * @param aData The data
       
   414  * @param aExtra Extra trace data
       
   415  * @param aPc The program counter value
       
   416  * @return ETrue if trace is activated
       
   417  */
       
   418 TBool DBTraceOstCategoryHandler::HandleMultiPart( TUint32 aHeader, TUint32 aHeader2, const TUint32 aContext,
       
   419                    const TUint32 a1, const TUint32 a2, const TUint32 aData, const TUint32 aExtra,
       
   420                    const TUint32 aPc)
       
   421     {
       
   422     TBool retval = ETrue;
       
   423     TInt multiPartOffset = aHeader2 & BTrace::EMultipartFlagMask;
       
   424     TUint8 recordSize = static_cast< TUint8 >( ( aHeader >> ( BTrace::ESizeIndex * KByteSize ) ) & KByteMask );
       
   425     
       
   426     // First part of multipart trace
       
   427     if (multiPartOffset == BTrace::EMultipartFirst)
       
   428         {
       
   429         // Create new MultiPart activation info and save it to the array
       
   430         TMultiPartActivationInfo activationInfo;
       
   431         activationInfo.iComponentId = a2;
       
   432         
       
   433         // This should be safe operation as if there is not enough data, the trace should not
       
   434         // be first part of multipart trace
       
   435         TUint32* ptr = reinterpret_cast< TUint32* >(aData);
       
   436         activationInfo.iTraceWord = *ptr++;
       
   437         activationInfo.iMultiPartId = aExtra;
       
   438         retval = iOstTraceBitmap->IsTraceActivated( activationInfo.iComponentId, activationInfo.iTraceWord );
       
   439         
       
   440         if (retval)
       
   441             {
       
   442             // Insert the item to the array        
       
   443             TInt ret = InsertIfNotExist( activationInfo );
       
   444 			
       
   445             if (KErrNone == ret)
       
   446                 {
       
   447                 CheckDroppedTrace( aHeader ); // Update header if there is a dropped trace
       
   448                 
       
   449                 // Write the trace. Skip first 4 bytes as it's the traceWord which is given in different parameter
       
   450                 iWriter->WriteTraceCoreFrame( activationInfo.iComponentId, activationInfo.iTraceWord, 
       
   451                         aHeader, aHeader2, aContext, activationInfo.iComponentId, 
       
   452                         activationInfo.iTraceWord, aData + 4, aExtra, aPc, recordSize - 4 );
       
   453                 }
       
   454             else
       
   455                 {
       
   456                 retval = EFalse;
       
   457                 }
       
   458             }
       
   459         }
       
   460     // Middle or last part of multipart trace
       
   461     else if (multiPartOffset == BTrace::EMultipartMiddle || multiPartOffset == BTrace::EMultipartLast)
       
   462         {
       
   463         // Check index of component id in array
       
   464         TMultiPartActivationInfo tempInfo;
       
   465         tempInfo.iMultiPartId = aExtra;
       
   466         
       
   467 		TInt index = Find( aExtra );
       
   468         
       
   469         if (index != KErrNotFound)
       
   470             {
       
   471             CheckDroppedTrace( aHeader ); // Update header if there is a dropped trace
       
   472         
       
   473             TMultiPartActivationInfo activationInfo;
       
   474             activationInfo.iComponentId = iMultipartArray[index].iComponentId;
       
   475             activationInfo.iTraceWord = iMultipartArray[index].iTraceWord;
       
   476             activationInfo.iMultiPartId = iMultipartArray[index].iMultiPartId;
       
   477             
       
   478             // Write the trace
       
   479             iWriter->WriteTraceCoreFrame( activationInfo.iComponentId, activationInfo.iTraceWord, aHeader, aHeader2, 
       
   480                     aContext, activationInfo.iComponentId, activationInfo.iTraceWord, aData, aExtra, aPc, recordSize );
       
   481             
       
   482             // Last part, remove the item from the array
       
   483             if (multiPartOffset == BTrace::EMultipartLast)
       
   484                 {
       
   485                 Remove(index);
       
   486                 }
       
   487             }
       
   488         }
       
   489     
       
   490     //Trace from here is not allowed
       
   491         
       
   492     return retval;
       
   493     }
       
   494 
       
   495 #else // __SMP__
       
   496 
       
   497 /**
       
   498  * Handles this Multipart trace
       
   499  *
       
   500  * @param aHeader BTrace header
       
   501  * @param aHeader2 Extra header data
       
   502  * @param aContext The thread context in which this function was called
       
   503  * @param a1 First parameter
       
   504  * @param a2 Second parameter
       
   505  * @param aData The data
       
   506  * @param aExtra Extra trace data
       
   507  * @param aPc The program counter value
       
   508  * @return ETrue if trace was processed, EFalse if not
       
   509  */
       
   510 TBool DBTraceOstCategoryHandler::HandleMultiPart( TUint32 aHeader, TUint32 aHeader2, const TUint32 aContext,
       
   511                    const TUint32 a1, const TUint32 a2, const TUint32 aData, const TUint32 aExtra,
       
   512                    const TUint32 aPc)
       
   513     {
       
   514     TBool retval = EFalse;
       
   515     
       
   516     if (iMultiPartTrace.iMultiPartId == 0 || iMultiPartTrace.iMultiPartId == aExtra)
       
   517         {    
       
   518         // First part of multipart trace
       
   519         if ((aHeader2 & BTrace::EMultipartFlagMask) == BTrace::EMultipartFirst)
       
   520             {
       
   521             TUint32 componentId = a2;
       
   522             TUint32* ptr = ( TUint32* )aData;
       
   523             TUint32 traceWord = *ptr++;
       
   524             retval = iOstTraceBitmap->IsTraceActivated( componentId, traceWord );
       
   525             if (retval)
       
   526                 {
       
   527                 CheckDroppedTrace( aHeader ); // Update header if there is a dropped trace
       
   528             
       
   529                 // Set values
       
   530                 iMultiPartTrace.iMultiPartId = aExtra;
       
   531                 iMultiPartTrace.iComponentId = componentId;
       
   532                 iMultiPartTrace.iTraceWord = traceWord;
       
   533                 iMultiPartTrace.iContext = aContext;
       
   534                 iMultiPartTrace.iPc = aPc;
       
   535                 iMultiPartTrace.iHeader = aHeader;
       
   536                 
       
   537                 // Remove the multipart information from the header2
       
   538                 aHeader2 &= ~BTrace::EMultipartFlagMask;
       
   539                 iMultiPartTrace.iHeader2 = aHeader2;
       
   540     
       
   541                 // Copy the data
       
   542                 TUint8 recordSize = static_cast< TUint8 >( ( aHeader >> ( BTrace::ESizeIndex * KByteSize ) ) & KByteMask );
       
   543                 TUint32 dataSize = recordSize - CalculateDataStartOffset(aHeader);
       
   544                 memcpy(iMultiPartTrace.iData, (TUint8*)aData + KTraceGroupIdLen, dataSize - KTraceGroupIdLen);
       
   545                 iMultiPartTrace.iDataInserted = dataSize - KTraceGroupIdLen;
       
   546                 }
       
   547             }      
       
   548         // Middle part of multipart trace
       
   549         else if ((aHeader2 & BTrace::EMultipartFlagMask) == BTrace::EMultipartMiddle)
       
   550             {
       
   551             retval = ETrue;
       
   552             // Add to the data buffer
       
   553             TUint8 recordSize = static_cast< TUint8 >( ( aHeader >> ( BTrace::ESizeIndex * KByteSize ) ) & KByteMask );
       
   554             TUint32 dataSize = recordSize - CalculateDataStartOffset(aHeader);
       
   555             
       
   556             // Check that trace is not too big
       
   557             if (iMultiPartTrace.iDataInserted + dataSize < MAX_TRACE_DATA_SIZE)
       
   558                 {
       
   559                 CheckDroppedTrace( aHeader ); // Update header if there is a dropped trace
       
   560                 memcpy(iMultiPartTrace.iData + iMultiPartTrace.iDataInserted, (TUint8*)aData, dataSize);
       
   561                 iMultiPartTrace.iDataInserted += dataSize;
       
   562                 }
       
   563             }
       
   564         // Last part of multipart trace
       
   565         else if ((aHeader2 & BTrace::EMultipartFlagMask) == BTrace::EMultipartLast)
       
   566             {
       
   567             retval = ETrue;
       
   568             TUint32 totalDataLen = a1;
       
   569             TUint32 offset = a2;
       
   570             
       
   571             // Add to the data buffer
       
   572             TUint32 partLen = totalDataLen - offset;
       
   573             TUint32 dataStartOffset = CalculateDataStartOffset(iMultiPartTrace.iHeader);
       
   574                            
       
   575             // Check that trace is not too big
       
   576             if (iMultiPartTrace.iDataInserted + partLen <= MAX_TRACE_DATA_SIZE)
       
   577                 {
       
   578                 CheckDroppedTrace( aHeader ); // Update header if there is a dropped trace
       
   579                 
       
   580                 // If the last part contains only last four bytes, it's a value instead of pointer
       
   581                 if (partLen == KFourBytes)
       
   582                     {
       
   583                     iMultiPartTrace.iData[iMultiPartTrace.iDataInserted] = aData & KByteMask;
       
   584                     iMultiPartTrace.iData[iMultiPartTrace.iDataInserted + 1] = (aData >> 8) & KByteMask; //CodForChk_Dis_Magic
       
   585                     iMultiPartTrace.iData[iMultiPartTrace.iDataInserted + 2] = (aData >> 16) & KByteMask; //CodForChk_Dis_Magic
       
   586                     iMultiPartTrace.iData[iMultiPartTrace.iDataInserted + 3] = (aData >> 24) & KByteMask; //CodForChk_Dis_Magic
       
   587                     }
       
   588                 else 
       
   589                     {
       
   590                     memcpy(iMultiPartTrace.iData + iMultiPartTrace.iDataInserted, (TUint8*)aData, partLen);   
       
   591                     }
       
   592                     
       
   593                 // Total data length. Four bytes is taken out because it was parsed out from the data
       
   594                 // array when parsing first part of the trace
       
   595                 totalDataLen = totalDataLen + dataStartOffset - KFourBytes;    
       
   596                     
       
   597                 }
       
   598             else
       
   599                 {
       
   600                 	// Total data length. Four bytes is taken out because it was parsed out from the data
       
   601                   // array when parsing first part of the trace
       
   602                 	totalDataLen = iMultiPartTrace.iDataInserted + dataStartOffset - KFourBytes;
       
   603                 }
       
   604                 	
       
   605             // Write the trace
       
   606             iWriter->WriteTraceCoreFrame( iMultiPartTrace.iComponentId, iMultiPartTrace.iTraceWord,
       
   607             iMultiPartTrace.iHeader, iMultiPartTrace.iHeader2, iMultiPartTrace.iContext,
       
   608             iMultiPartTrace.iComponentId, iMultiPartTrace.iTraceWord, (TUint32)iMultiPartTrace.iData,
       
   609             iMultiPartTrace.iMultiPartId, iMultiPartTrace.iPc, totalDataLen);
       
   610                 
       
   611             iMultiPartTrace.iMultiPartId = 0;
       
   612             }
       
   613         }
       
   614 
       
   615     return retval;
       
   616     }
       
   617 
       
   618 /**
       
   619  * Calculates data start offset
       
   620  *
       
   621  * @param aHeader BTrace header
       
   622  */
       
   623 TUint32 DBTraceOstCategoryHandler::CalculateDataStartOffset( TUint32 aHeader )
       
   624     {
       
   625     TUint32 offset = 0;
       
   626     TUint8 flags = static_cast< TUint8 >( ( aHeader >> ( BTrace::EFlagsIndex * KByteSize ) ) & KByteMask );
       
   627     
       
   628     // First add header length
       
   629     offset += KBTraceHeaderLen;
       
   630     
       
   631     // Header2 is present
       
   632     if ( flags & BTrace::EHeader2Present )
       
   633         {
       
   634         offset += KBTraceVariableLen;
       
   635         }
       
   636     // Timestamp is present
       
   637     if ( flags & BTrace::ETimestampPresent )
       
   638         {
       
   639         offset += KBTraceVariableLen;
       
   640         }
       
   641     // Timestamp2 is present
       
   642     if ( flags & BTrace::ETimestamp2Present )
       
   643         {
       
   644         offset += KBTraceVariableLen;
       
   645         }
       
   646     // Context ID is present
       
   647     if ( flags & BTrace::EContextIdPresent )
       
   648         {
       
   649         offset += KBTraceVariableLen;
       
   650         }
       
   651     // Program counter is present
       
   652     if ( flags & BTrace::EPcPresent )
       
   653         {
       
   654         offset += KBTraceVariableLen;
       
   655         }
       
   656     // Extra value is present
       
   657     if ( flags & BTrace::EExtraPresent )
       
   658         {
       
   659         offset += KBTraceVariableLen;
       
   660         }
       
   661     
       
   662     // Next 8 bytes came with first and second parameter of the multipart trace
       
   663     offset += KFourBytes;
       
   664     offset += KFourBytes;
       
   665     
       
   666     return offset;
       
   667     }
       
   668 	
       
   669 #endif // !__SMP__
       
   670 
       
   671 // End of File