dbgagents/trkagent/engine/TrkDispatchLayer.cpp
changeset 0 c6b0df440bee
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbgagents/trkagent/engine/TrkDispatchLayer.cpp	Tue Mar 02 10:33:16 2010 +0530
@@ -0,0 +1,3577 @@
+/*
+* Copyright (c) 2004 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 "TrkEngine.h"
+#include "TrkDispatchLayer.h"
+#include "DateTimeConverter.h"
+
+#ifndef __TEXT_SHELL__
+#include "TrkSwInstall.h"
+#endif
+
+//
+// Macros
+//
+
+//
+// Version Information
+//
+
+#define MAJOR_VERSION_NUMBER	3
+#define MINOR_VERSION_NUMBER	2
+#define BUILD_NUMBER			4
+
+
+//
+// Support Information
+//
+
+#define DS_SUPPORT_MASK_00_07	0x7E	// kDSConnect, kDSDisconnect, kDSReset, kDSVersions, kDSSupportMask, kDSCPUType */
+#define DS_SUPPORT_MASK_08_0F	0x00
+#define DS_SUPPORT_MASK_10_17	0x4f	// R/W Memory, R/W Registers, FlushCache
+#define DS_SUPPORT_MASK_18_1F	0x5f	// kDSContinue, kDSStep, kDSStop, kDSSetBreak, kDSClearBreak
+#define DS_SUPPORT_MASK_20_27	0x01	// kDSNotifyFileInput
+#define DS_SUPPORT_MASK_28_2F	0x00
+#define DS_SUPPORT_MASK_30_37	0x00
+#define DS_SUPPORT_MASK_38_3F	0x00
+#define DS_SUPPORT_MASK_40_47	0x0f	// OS Create/Delete Item, OS Read/Write Info
+#define DS_SUPPORT_MASK_48_4F	0x1f	// OS Read/Write/Open/Close/Position File
+#define DS_SUPPORT_MASK_50_57	0x00
+#define DS_SUPPORT_MASK_58_5F	0x00
+#define DS_SUPPORT_MASK_60_67	0x00
+#define DS_SUPPORT_MASK_68_6F	0x00
+#define DS_SUPPORT_MASK_70_77	0x00
+#define DS_SUPPORT_MASK_78_7F	0x00
+#define DS_SUPPORT_MASK_80_87	0x01	// kDSReplyACK
+#define DS_SUPPORT_MASK_88_8F	0x00
+#define DS_SUPPORT_MASK_90_97	0x11	// kDSNotifyStopped, kDSNotifyStopped2
+#define DS_SUPPORT_MASK_98_9F	0x00
+#define DS_SUPPORT_MASK_A0_A7	0x03	// kDSOSNotifyCreated, kDSOSNotifyDeleted
+#define DS_SUPPORT_MASK_A8_AF	0x00
+#define DS_SUPPORT_MASK_B0_B7	0x00
+#define DS_SUPPORT_MASK_B8_BF	0x00
+#define DS_SUPPORT_MASK_C0_C7	0x00
+#define DS_SUPPORT_MASK_C8_CF	0x00
+#define DS_SUPPORT_MASK_D0_D7	0x03	// kDSWriteFile, kDSReadFile
+#define DS_SUPPORT_MASK_D8_DF	0x00
+#define DS_SUPPORT_MASK_E0_E7	0x00
+#define DS_SUPPORT_MASK_E8_EF	0x00
+#define DS_SUPPORT_MASK_F0_F7	0x00
+#define DS_SUPPORT_MASK_F8_FF	0x80	// kDSReplyNAK
+
+#define KProcessKilled 0x4B696C6C // "Kill"
+
+#ifdef EKA2
+#define EUSER_LIBPATH _L("Z:\\Sys\\Bin\\euser.dll")
+#else
+#define EUSER_LIBPATH _L("Z:\\System\\Libs\\euser.dll")
+#endif
+
+#ifdef __OEM_TRK__
+#define TRK_TYPE_DESCRIPTION _L8("System TRK")
+#else
+#define TRK_TYPE_DESCRIPTION _L8("Application TRK")
+#endif
+
+
+//
+// Swap2
+//
+// Byte-swaps a 2-byte value.  Used to convert to/from little/big endian.
+//
+static TUint16 Swap2(TUint16 aSource)
+{
+	TUint16 dest = 0;
+	for (TInt i=0; i<2; i++)
+	{
+		dest <<= 8;
+		dest |= aSource & 0xFF;
+		aSource >>= 8;
+	}
+	
+	return dest;
+} 
+
+//
+// Swap4
+//
+// Byte-swaps a 4-byte value.  Used to convert to/from little/big endian.
+//
+static TUint32 Swap4(TUint32 aSource)
+{
+	TUint32 dest = 0;
+	for (TInt i=0; i<4; i++)
+	{
+		dest <<= 8;
+		dest |= aSource & 0xFF;
+		aSource >>= 8;
+	}
+	
+	return dest;
+} 
+
+//
+// Swap4xN
+//
+//	Byte-swaps N 4-byte values *in place*.  Used to convert to/from little/big endian.
+//
+void Swap4xN(TUint32 *aSource, TInt aCount)
+{
+	while (aCount--)
+	{
+		TUint32 temp = Swap4(*aSource);
+		*aSource++ = temp;
+	}
+} 
+
+
+//
+//
+// CExitTrapper implementation
+//
+//
+
+//
+// CExitTrapper constructor
+//
+// Accepts CTrkDispatchLayer interface and the process ID of the
+// process to watch
+//
+CExitTrapper::CExitTrapper(CTrkDispatchLayer *aDispatch, TUint32 aProcessId)
+	: CActive(EPriorityStandard),
+	  iProcessId(aProcessId),
+	  iDispatch(aDispatch)
+{
+	CActiveScheduler::Add(this);
+
+	TInt error = iProcess.Open(iProcessId);
+	if (KErrNone != error)
+		User::Panic(_L("Unable to open process"), __LINE__);
+}
+
+//
+// CExitTrapper destructor
+//
+CExitTrapper::~CExitTrapper()
+{
+	Cancel();
+	Deque();
+	iProcess.Close();
+}
+
+//
+// CExitTrapper::Watch
+//
+// Watch for the process to exit
+//
+void CExitTrapper::Watch()
+{
+	iProcess.Logon(iStatus);
+	SetActive();
+}
+
+//
+// CExitTrapper::RunL
+//
+// Called when the process exits
+//
+void CExitTrapper::RunL()
+{
+	// sometimes this is run when the process has yet to exit
+	if (iProcess.ExitType() == EExitPending)
+	{
+		iProcess.LogonCancel(iStatus);
+		Watch();
+	}
+	else
+	{
+		iDispatch->DoNotifyProcessDiedL(iProcessId, iProcess.ExitReason());
+	}
+}
+
+//
+// CExitTrapper::DoCancel
+//
+// Stop waiting for this process to exit
+//
+void CExitTrapper::DoCancel()
+{
+	iProcess.LogonCancel(iStatus);
+}
+
+
+//
+//
+// CEventTrapper implementation
+//
+//
+
+//
+// CEventTrapper constructor
+//
+// Accepts CTrkDispatchLayer interface
+//
+CEventTrapper::CEventTrapper(CTrkDispatchLayer *aDispatch)
+	: CActive(CActive::EPriorityStandard),
+	  iDispatch(aDispatch)
+{
+	CActiveScheduler::Add(this);
+}
+
+//
+// CEventTrapper destructor
+//
+CEventTrapper::~CEventTrapper()
+{
+	Cancel();
+	Deque();
+}
+
+//
+// CEventTrapper::Watch
+//
+// Start listening for events
+//
+void CEventTrapper::Watch()
+{
+	iDispatch->iKernelDriver.GetEvent(iStatus, iEventInfo);
+	SetActive();
+}
+
+//
+// CEventTrapper::RunL
+//
+// Called when an event occurs
+//
+void CEventTrapper::RunL()
+{
+	// determine the type of event and handle accordingly
+	switch (iEventInfo.iEventType)
+	{
+		case SEventInfo::EThreadBreakPoint:
+		{
+			iDispatch->DoNotifyStoppedL(iEventInfo.iProcessId, iEventInfo.iThreadId, iEventInfo.iCurrentPC, KNullDesC8);
+			break;
+		}
+		case SEventInfo::EThreadException:
+		{
+			TBuf8<100> buf;
+			
+			switch(iEventInfo.iExceptionNumber)
+			{
+				case EExcIntegerDivideByZero:
+				{
+					buf.Format(_L8("An integer divide by zero exception has occurred."));
+					break;
+				}
+				case EExcIntegerOverflow:
+				{
+					buf.Format(_L8("An integer overflow exception has occurred."));
+					break;
+				}
+				case EExcBoundsCheck:
+				{
+					buf.Format(_L8("An bounds check exception has occurred."));
+					break;
+				}
+				case EExcInvalidOpCode:
+				{
+					buf.Format(_L8("An invalid instruction exception has occurred."));
+					break;
+				}
+				case EExcDoubleFault:
+				{
+					buf.Format(_L8("A double fault exception has occurred."));
+					break;
+				}
+				case EExcStackFault:
+				{
+					buf.Format(_L8("A stack fault exception has occurred."));
+					break;
+				}
+				case EExcAccessViolation:
+				{
+					buf.Format(_L8("An access violation exception has occurred."));
+					break;
+				}
+				case EExcPrivInstruction:
+				{
+					buf.Format(_L8("A priveledged instruction exception has occurred."));
+					break;
+				}
+				case EExcAlignment:
+				{
+					buf.Format(_L8("An alignment exception has occurred."));
+					break;
+				}
+				case EExcPageFault:
+				{
+					buf.Format(_L8("A page fault exception has occurred."));
+					break;
+				}
+				case EExcFloatDenormal:
+				case EExcFloatDivideByZero:
+				case EExcFloatInexactResult:
+				case EExcFloatInvalidOperation:
+				case EExcFloatOverflow:
+				case EExcFloatStackCheck:
+				case EExcFloatUnderflow:
+				{
+					buf.Format(_L8("A floating point exception has occurred."));
+					break;
+				}
+				case EExcAbort:
+				{
+					buf.Format(_L8("An abort exception has occurred."));
+					break;
+				}
+				case EExcUserInterrupt:
+				{
+					buf.Format(_L8("A user interrupt exception has occurred."));
+					break;
+				}
+				case EExcDataAbort:
+				{
+					buf.Format(_L8("A data abort exception has occurred."));
+					break;
+				}
+				case EExcCodeAbort:
+				{
+					buf.Format(_L8("A code abort exception has occurred."));
+					break;
+				}				
+				case EExcGeneral:
+				case EExcSingleStep:
+				case EExcBreakPoint:
+				case EExcKill:
+				case EExcMaxNumber:
+				case EExcInvalidVector:
+				default:
+				{
+					buf.Format(_L8("An unknown exception (%d) has occurred."), iEventInfo.iExceptionNumber);
+					break;				
+				}
+			}
+			
+			iDispatch->DoNotifyStoppedL(iEventInfo.iProcessId, iEventInfo.iThreadId, iEventInfo.iCurrentPC, buf);
+			break;
+		}
+		case SEventInfo::EThreadPanic:
+		{
+			TBuf8<100> buf;
+//			buf.Format(_L8("Thread 0x%x has panicked.\nCategory: %S\nReason: %d"), iEventInfo.iThreadId, &iEventInfo.iPanicCategory, iEventInfo.iExceptionNumber);
+			buf.Format(_L8("Thread 0x%x has panicked. Category: %S; Reason: %d"), iEventInfo.iThreadId, &iEventInfo.iPanicCategory, iEventInfo.iPanicReason);
+			
+			iDispatch->DoNotifyStoppedL(iEventInfo.iProcessId, iEventInfo.iThreadId, iEventInfo.iCurrentPC, buf, true, iEventInfo.iExceptionNumber);
+			break;
+		}
+		case SEventInfo::EProcessPanic:
+		{
+			TBuf8<100> buf;
+			buf.Format(_L8("Process 0x%x has panicked.\nCategory: %S\nReason: %d"), iEventInfo.iProcessId, &iEventInfo.iPanicCategory, iEventInfo.iExceptionNumber);
+			
+			iDispatch->DoNotifyStoppedL(iEventInfo.iProcessId, iEventInfo.iThreadId, iEventInfo.iCurrentPC, buf);
+			break;
+		}
+		case SEventInfo::ELibraryLoaded:
+		{
+			// a library has been loaded.  we get statically linked library loaded notifications
+			// the very first time the process is created.  we want to ignore these because we
+			// handle static libs in another way.  if the process the library was loaded for is
+			// not being debugging, just resume the thread and ignore the event.  if the process
+			// is being debugged but it hasn't yet been created, then this must be a static lib
+			// and we ignore it.  note that we do not bother resuming the thread since it has not
+			// been started yet!
+
+			TBool created = EFalse;
+			TBool found = EFalse;
+					
+			for (TInt i=0; i<iDispatch->iDebugProcessList.Count(); i++)
+			{
+				if (iDispatch->iDebugProcessList[i]->ProcessId() == iEventInfo.iProcessId)
+				{
+					created = iDispatch->iDebugProcessList[i]->iReadyForLibraryLoadNotification;
+					found = ETrue;
+					break;
+				}
+			}
+
+		#ifndef EKA2
+			if (!iEventInfo.iCodeAddress)
+			{
+				TBuf<KMaxPath> libName;
+				libName.Copy(iEventInfo.iFileName);
+				
+				RLibrary lib;
+				TInt err = lib.LoadRomLibrary(libName, KNullDesC);
+				if (KErrNone == err)
+				{
+					iEventInfo.iCodeAddress = (TUint32)lib.EntryPoint();
+					lib.Close();
+				}
+			}
+		#endif
+
+			if (!created || !iEventInfo.iCodeAddress || !found)
+			{
+				iDispatch->iKernelDriver.ResumeThread(iEventInfo.iThreadId);
+			}
+			else
+			{
+				iDispatch->DoNotifyLibraryLoadedL(iEventInfo.iFileName, iEventInfo.iProcessId, iEventInfo.iThreadId, iEventInfo.iCodeAddress, iEventInfo.iDataAddress);
+			}
+			break;
+		}
+		case SEventInfo::ELibraryUnloaded:
+		{
+			TBool found = EFalse;
+			
+			for (TInt i=0; i<iDispatch->iDebugProcessList.Count(); i++)
+			{
+				if (iDispatch->iDebugProcessList[i]->ProcessId() == iEventInfo.iProcessId)
+				{
+					found = ETrue;
+					break;
+				}
+			}
+			
+			if (!found)
+			{
+				iDispatch->iKernelDriver.ResumeThread(iEventInfo.iThreadId);
+			}
+			else
+			{
+				iDispatch->DoNotifyLibraryUnloadedL(iEventInfo.iFileName, iEventInfo.iProcessId, iEventInfo.iThreadId);
+			}
+			
+			break;
+		}
+		case SEventInfo::EUserTrace:
+		{
+			iDispatch->DoNotifyUserTraceL(iEventInfo.iTraceData);
+			break;
+		}
+		case SEventInfo::EProcessAdded:
+		{
+			iDispatch->DoNotifyProcessAddedL(iEventInfo.iFileName, iEventInfo.iProcessId, 
+											 iEventInfo.iThreadId, iEventInfo.iUid, 
+											 iEventInfo.iCodeAddress, iEventInfo.iDataAddress);
+			break;
+		}
+		case SEventInfo::EUnknown:
+		default:
+			User::Panic(_L("Unknown event type"), __LINE__);
+			break;
+	}
+
+	// reset the values
+	iEventInfo.Reset();
+
+	// keep listening for more events
+	Watch();
+}
+
+//
+// CEventTrapper::DoCancel
+//
+// Stop listening for events
+//
+void CEventTrapper::DoCancel()
+{
+	iDispatch->iKernelDriver.CancelGetEvent();
+}
+
+
+//
+//
+// CDebugProcess implementation
+//
+//
+
+//
+// CDebugProcess::NewL
+//
+// Accepts CTrkDispatchLayer interface and the process ID and main
+// thread ID of a process being debugged
+//
+CDebugProcess* CDebugProcess::NewL(CTrkDispatchLayer *aDispatch, TUint32 aProcessId, TUint32 aMainThreadId)
+{
+	CDebugProcess* self = new(ELeave) CDebugProcess();
+	self->ConstructL(aDispatch, aProcessId, aMainThreadId);
+	return self;
+}
+
+//
+// CDebugProcess::ConstructL
+//
+// Accepts CTrkDispatchLayer interface and the process ID and main
+// thread ID of a process being debugged
+//
+void CDebugProcess::ConstructL(CTrkDispatchLayer *aDispatch, TUint32 aProcessId, TUint32 aMainThreadId)
+{
+	iProcessId = aProcessId;
+	iMainThreadId = aMainThreadId;
+	iReadyForLibraryLoadNotification = EFalse;
+	
+	// start waiting for this process to exit
+	iExitTrapper = new(ELeave) CExitTrapper(aDispatch, aProcessId);
+	iExitTrapper->Watch();
+}
+
+//
+// CDebugProcess destructor
+//
+CDebugProcess::~CDebugProcess()
+{
+	SafeDelete(iExitTrapper);
+}
+
+#ifndef __TEXT_SHELL__
+
+//
+// CPhoneInfo implementation
+//
+CPhoneInfo::CPhoneInfo():
+           CActive(EPriorityStandard),
+           iPhoneIdV1Pckg(iPhoneIdV1),
+           iDispatchLayer(NULL)
+{
+    CActiveScheduler::Add(this);
+}
+
+CPhoneInfo* CPhoneInfo::NewL()
+{
+    CPhoneInfo* self = new(ELeave) CPhoneInfo();
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop();
+    return self;
+}
+
+void CPhoneInfo::ConstructL()
+{
+    iTelephony = CTelephony::NewL();
+}
+
+CPhoneInfo::~CPhoneInfo() 
+{ 
+    Cancel();
+    Deque();
+    SafeDelete(iTelephony);
+}
+
+void CPhoneInfo::GetPhoneName(CTrkDispatchLayer* aDispatchLayer)
+{
+    iDispatchLayer = aDispatchLayer;
+    iTelephony->GetPhoneId(iStatus, iPhoneIdV1Pckg);
+    SetActive();
+}
+
+void CPhoneInfo::RunL()
+{   
+    if(iStatus == KErrNone)
+	{          
+        iDispatchLayer->UpdatePhoneNameInfo(iPhoneIdV1.iModel);              
+    }
+}
+
+void CPhoneInfo::DoCancel()
+{
+	iTelephony->CancelAsync(CTelephony::EGetPhoneIdCancel);
+}
+#endif
+
+//
+//
+// CTrkDispatchLayer implementation
+//
+//
+
+//
+// CTrkDispatchLayer constructor
+//
+CTrkDispatchLayer::CTrkDispatchLayer()
+	: iEngine(NULL),
+	  iFramingLayer(NULL),
+#ifndef __TEXT_SHELL__
+	  iPhoneInfo(NULL),
+#endif
+	  iFileState(EFileUnknown),
+	  iDebugProcessList(1),
+	  iProcessList(1),
+	  iThreadList(1),
+	  iSuspendedThreadList(1),
+	  iEventTrapper(NULL),
+	  iIsConnected(EFalse),
+	  iPhoneNameInfoAvailable(EFalse)
+	  
+#ifdef __OEM_TRK__	  
+	  ,iUseTcbServer(EFalse)
+#endif	  
+{
+}
+
+//
+// CTrkDispatchLayer::NewL
+//
+CTrkDispatchLayer* CTrkDispatchLayer::NewL(CTrkCommPort *aPort, CTrkEngine* aEngine)
+{
+	CTrkDispatchLayer* self = new(ELeave) CTrkDispatchLayer();
+	self->ConstructL(aPort, aEngine);
+	return self;
+}
+
+//
+// CTrkDispatchLayer destructor
+//
+CTrkDispatchLayer::~CTrkDispatchLayer()
+{
+	SafeDelete(iFramingLayer);
+
+	SafeDelete(iInputBuffer);
+	SafeDelete(iReplyBuffer);
+#ifndef __TEXT_SHELL__
+	SafeDelete(iPhoneInfo);
+#endif
+	// just in case a disconnect never happened
+	SafeDelete(iEventTrapper);
+	
+#ifndef __WINS__
+	iKernelDriver.Close();
+#endif
+
+    CloseTcbServer();
+	iProcessList.Close();
+	iThreadList.Close();
+	iSuspendedThreadList.Close();
+	
+	iDebugProcessList.ResetAndDestroy();	
+	iDebugProcessList.Close();
+	//Notify the server that Debugging is ended
+    if (iEngine)
+        iEngine->DebuggingEnded();  
+        
+}
+//
+// CTrkDispathcLayer::CloseTcbServer()
+//
+void CTrkDispatchLayer::CloseTcbServer()
+{
+#ifdef __OEM_TRK__  
+    //Shutdown the tcb server.
+    if (iUseTcbServer)
+    {
+        iTrkTcbSession.ShutDownServer();
+        iTrkTcbSession.Close();
+        iUseTcbServer = EFalse;
+    }
+#endif  
+
+}
+
+//
+// CTrkDispatchLayer::ConstructL
+//
+void CTrkDispatchLayer::ConstructL(CTrkCommPort *aPort, CTrkEngine* aEngine)
+{
+	iEngine = aEngine;
+	
+	// create the framing layer interface
+	iFramingLayer = new CTrkFramingLayer(aPort);
+
+	// At a minimum, we assume that the host debugger supports 3.3 version of the protocol
+	// From 3.0 to 3.3, TRK is backwards compatible. Starting with version 3.4, TRK sends 
+	// process created notifications as part of notify created event. Unless the host 
+	// debugger sets the supported protocol version to 3.4, we are not going to send this 
+	// new notification. Going forward, we should check for the protocol version before 
+	// we send new notifications. 
+	iHostVersion.iMajor = DS_PROTOCOL_MAJOR_VERSION_3;
+	iHostVersion.iMinor = DS_PROTOCOL_MINOR_VERSION_3;
+	
+	//To find the sw version runnning in the phone
+	FindPhoneSWVersion();
+		
+	// On techview, this functionality is not available for some reason.
+	// This needs to be investigated further, but this functionality is not critical for techview platform right now.
+#ifdef __S60__
+	// To find the name of the phone.
+	TRAPD(err1, FindPhoneNameL());
+	if (err1 != KErrNone)
+#endif	   
+	{
+	    iPhoneNameInfoAvailable = EFalse;
+	}
+}
+
+//
+// CTrkDispathLayer::FindPhoneSWVersion()
+//
+// Finds out the software version of the phone
+//
+void CTrkDispatchLayer::FindPhoneSWVersion()
+{
+#ifndef __TEXT_SHELL__
+    TBuf<KSysUtilVersionTextLength> version;
+    if (SysUtil::GetSWVersion( version ) == KErrNone ) 
+	{
+        iPhoneVersion.Copy(version);
+	}                
+#endif
+}
+
+//
+// CTrkDispathLayer::FindPhoneName()
+//
+// Finds the name of the phone 
+//
+void CTrkDispatchLayer::FindPhoneNameL()
+{
+#ifndef __TEXT_SHELL__
+    iPhoneInfo = CPhoneInfo::NewL();
+    iPhoneInfo->GetPhoneName(this);
+#endif             
+}
+
+//
+// CTrkDispatchLayer::Listen
+//
+// Start listening to the communications port for messages from the host debugger
+//
+void CTrkDispatchLayer::Listen()
+{
+	iFramingLayer->Listen(this);
+}
+
+//
+// CTrkDispatchLayer::StopListening
+//
+// Stop listening to the communications port for messages from the host debugger
+//
+void CTrkDispatchLayer::StopListening()
+{
+	// just in case the user quit MetroTrk while something was being debugged.
+	RProcess process;
+	for (TInt i=0; i<iDebugProcessList.Count(); i++)
+	{
+		if (KErrNone == process.Open(iDebugProcessList[i]->ProcessId()))
+		{
+		#ifdef EKA2
+			process.Kill(KErrNone);
+		#else	
+			process.Kill(KProcessKilled);
+		#endif
+			process.Close();
+		}
+	}
+
+	iFramingLayer->StopListening();
+}
+
+//
+// CTrkDispatchLayer::GetVersionInfo
+//
+// Get the current version of MetroTrk
+//
+void CTrkDispatchLayer::GetVersionInfo(TInt &aMajorVersion, TInt &aMinorVersion, TInt &aMajorAPIVersion, TInt &aMinorAPIVersion, TInt &aBuildNumber)
+{
+	aMajorVersion = MAJOR_VERSION_NUMBER;
+	aMinorVersion = MINOR_VERSION_NUMBER;
+	aMajorAPIVersion = DS_PROTOCOL_MAJOR_VERSION;
+	aMinorAPIVersion = DS_PROTOCOL_MINOR_VERSION;
+	aBuildNumber = BUILD_NUMBER;
+}
+
+//
+// CTrkDispatchLayer::HandleMsg
+//
+// Handle a command sent by the host debugger
+//
+void CTrkDispatchLayer::HandleMsg(const TDesC8& aMsg)
+{
+	TInt error = KErrNone;
+
+	// reset the input buffer and set it to the new unframed message
+	SafeDelete(iInputBuffer);
+	iInputBuffer = aMsg.Alloc();
+
+	if (!iInputBuffer)
+		User::Panic(_L("Failed to allocate input buffer"), __LINE__);
+	
+	TRAP(error, DispatchMsgL());
+
+	if (error < 0)
+	{
+		// its a symbian os error
+		error = kDSReplyOsError;
+	}
+	
+	// handle errors raised during command execution
+	switch(error)
+	{
+		// no error and ack was sent by handler
+ 		case kDSReplyNoError:
+ 			break;
+
+		// there was a problem with the packet received
+		case kDSReplyPacketSizeError:
+		case kDSReplyEscapeError:
+		case kDSReplyBadFCS:
+		case kDSReplyOverflow:
+		case kDSReplySequenceMissing:
+			iFramingLayer->RespondErr(kDSReplyNAK, error);
+			break;
+			
+		// command and format were OK, but failed for some other reason
+ 		default:
+			iFramingLayer->RespondErr(kDSReplyACK, error);
+	}
+}
+
+//
+// CTrkDispatchLayer::DispatchMsgL
+//
+// Handle the command sent by the host debugger
+//
+void CTrkDispatchLayer::DispatchMsgL()
+{
+	// make sure the input buffer is setup
+	User::LeaveIfNull(iInputBuffer);
+
+	// iInputBuffer holds the unframed message from the host
+	switch (iInputBuffer->Ptr()[0])
+	{
+		case kDSPing:
+		{
+			// nothing to do
+			iFramingLayer->RespondOkL(KNullDesC8);
+			break;
+		}
+		case kDSConnect:
+		{
+			DoConnectL();
+			break;
+		}
+		case kDSDisconnect:
+		{
+			DoDisconnectL();
+			break;
+		}
+		case kDSVersions:
+		{
+			DoVersionsL();
+			break;
+		}
+		case kDSVersions2:
+		{
+			DoVersions2L();
+			break;
+		}
+		case kDSVersions3:
+		{
+			DoVersions3L();
+			break;
+		}
+		case kDSHostVersions:
+		{
+			DoHostVersionsL();
+			break;
+		}
+		case kDSSupportMask:
+		{
+			DoSupportMaskL();
+			break;
+		}
+		case kDSCPUType:
+		{
+			DoCPUTypeL();
+			break;
+		}
+		case kDSReadMemory:
+		{
+			DoReadMemoryL();
+			break;
+		}
+		case kDSWriteMemory:
+		{
+			DoWriteMemoryL();
+			break;
+		}
+		case kDSReadRegisters:
+		{
+			DoReadRegistersL();
+			break;
+		}
+		case kDSWriteRegisters:
+		{
+			DoWriteRegistersL();
+			break;
+		}
+		case kDSContinue:
+		{
+			DoContinueL();
+			break;
+		}
+		case kDSStep:
+		{
+			DoStepL();
+			break;
+		}
+		case kDSStop:
+		{
+			DoStopL();
+			break;
+		}
+		case kDSSetBreak:
+		{
+			DoSetBreakL();
+			break;
+		}
+		case kDSClearBreak:
+		{
+			DoClearBreakL();
+			break;
+		}
+		case kDSModifyBreakThread:
+		{
+			DoModifyBreakThreadL();
+			break;
+		}
+		case kDSOSCreateItem:
+		{
+			DoCreateItemL();
+			break;
+		}
+		case kDSOSDeleteItem:
+		{
+			DoDeleteItemL();
+			break;
+		}
+		case kDSOSReadInfo:
+		{
+			DoReadInfoL();
+			break;
+		}
+		case kDSOSWriteInfo:
+		{
+			DoWriteInfoL();
+			break;
+		}
+		case kDSOSWriteFile:
+		{
+			DoWriteFileL();
+			break;
+		}
+		case kDSOSReadFile:
+		{
+			DoReadFileL();
+			break;
+		}
+		case kDSOSOpenFile:
+		{
+			DoOpenFileL();
+			break;
+		}	
+		case kDSOSCloseFile:
+		{
+			DoCloseFileL();
+			break;
+		}
+		case kDSOSPositionFile:
+		{
+			DoPositionFileL();
+			break;
+		}
+		case kDSOSInstallFile:
+		{
+			DoInstallFileL();
+			break;
+		}
+		case kDSOSInstallFile2:
+		{
+			DoInstallFile2L();
+			break;
+		}
+		case kDSOSPhoneSWVersion:
+	    {		    
+		    DoGetPhoneSWVersionL();
+			break;
+		}
+		case kDSOSPhoneName:		    
+		{
+		    DoGetPhoneNameL();
+		    break;
+		}
+		
+		case kDSReplyACK:
+		case kDSReplyNAK:
+			break;
+
+		case kDSReset:
+		case kDSFillMemory:
+		case kDSCopyMemory:
+		case kDSFlushCache:
+		case kDSDownload:
+		case kDSNotifyFileInput:			
+		default:
+		{
+			// unsupported command
+			iFramingLayer->RespondErr(kDSReplyACK, kDSReplyUnsupportedCommandError);
+			break;
+		}
+	}
+}
+
+//
+// CTrkDispatchLayer::DoConnectL
+//
+// The host debugger is starting a new debug session
+//
+void CTrkDispatchLayer::DoConnectL()
+{	
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSConnect != command)
+		User::Leave(kDSReplyError);
+
+	// if we're already connected for some reason, we need to cleanup so we're ready
+	// for a new debug session
+	if (iIsConnected)
+	{
+		// reset the sequence ids for the next debug session
+		iFramingLayer->ResetSequenceIDs();
+
+		//stop listening for events
+		SafeDelete(iEventTrapper);
+
+		// let the kernel side driver cleanup
+		iKernelDriver.Close();
+
+		iIsConnected = EFalse;
+	}
+
+	// reset the lists so that they are ready for use
+	iProcessList.Reset();
+	iThreadList.Reset();
+	iSuspendedThreadList.Reset();
+	iDebugProcessList.ResetAndDestroy();
+
+	TMetroTrkDriverInfo info;
+#ifndef EKA2
+	RLibrary euser;
+	User::LeaveIfError(euser.Load(EUSER_LIBPATH));
+	CleanupClosePushL(euser);
+	
+	info.iPanic1Address = (TUint32)euser.Lookup(812);			// RThread::Panic
+	info.iPanic2Address = (TUint32)euser.Lookup(813);			// RProcess::Panic
+	info.iException1Address = (TUint32)euser.Lookup(868);		// RThread::RaiseException
+	info.iException2Address = (TUint32)euser.Lookup(520);		// User::HandleException
+	info.iLibraryLoadedAddress = (TUint32)euser.Lookup(636);	// UserSvr::LibraryLoaded
+
+	// calculate the end address of the user library.  breakpoints and stepping will not
+	// be allowed from the start of ROM to the end of the user library since stopping a
+	// kernel thread could end up freezing the target
+	RFs fs;
+	User::LeaveIfError(fs.Connect());
+	CleanupClosePushL(fs);
+
+	RFile file;
+	User::LeaveIfError(file.Open(fs, EUSER_LIBPATH, EFileStream|EFileRead|EFileShareReadersOnly));
+	CleanupClosePushL(file);
+
+	TInt size;
+	User::LeaveIfError(file.Size(size));
+	
+	info.iUserLibraryEnd = (TUint32)euser.EntryPoint() + size;
+
+	CleanupStack::PopAndDestroy(); // file
+	CleanupStack::PopAndDestroy(); // fs
+	CleanupStack::PopAndDestroy(); // euser
+#endif	
+	
+	// start the kernel side driver
+	User::LeaveIfError(iKernelDriver.Open(info));
+	
+	// start listening for events
+	iEventTrapper = new(ELeave) CEventTrapper(this);
+	iEventTrapper->Watch();
+
+	iIsConnected = ETrue;	
+#ifdef __S60__	
+	// now close close crash logger
+	CloseCrashLogger();
+#endif	
+	
+	if (iEngine)
+		iEngine->DebuggingStarted();
+	
+	iFramingLayer->RespondOkL(KNullDesC8);
+}
+
+//
+// CTrkDispatchLayer::DoDisconnectL
+//
+// The host debugger is stopping the current debug session
+//
+void CTrkDispatchLayer::DoDisconnectL()
+{
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSDisconnect != command)
+		User::Leave(kDSReplyError);
+
+	// make sure we're connected
+	if (!iIsConnected)
+	{
+		User::Leave(KErrCouldNotDisconnect);
+	}
+
+	//stop listening for events
+	SafeDelete(iEventTrapper);
+
+	iIsConnected = EFalse;
+
+	iFramingLayer->RespondOkL(KNullDesC8);
+
+	// let the kernel side driver cleanup
+	iKernelDriver.Close();
+
+	//Shutdown the tcb server.
+	CloseTcbServer();
+	
+	// send the callback to the trk server
+	if (iEngine)
+		iEngine->DebuggingEnded();	
+        
+}
+
+//
+// CTrkDispatchLayer::DoVersionsL
+//
+// The host debugger is requesting MetroTrk version information
+//
+void CTrkDispatchLayer::DoVersionsL()
+{
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSVersions != command)
+		User::Leave(kDSReplyError);
+	
+	TUint8 kernelMajorVersion = MAJOR_VERSION_NUMBER;
+	TUint8 kernelMinorVersion = MINOR_VERSION_NUMBER;
+	TUint8 protocolMajorVersion = DS_PROTOCOL_MAJOR_VERSION;
+	TUint8 protocolMinorVersion = DS_PROTOCOL_MINOR_VERSION;
+
+	AddToReplyBufferL(kernelMajorVersion, true);
+	AddToReplyBufferL(kernelMinorVersion);
+	AddToReplyBufferL(protocolMajorVersion);
+	AddToReplyBufferL(protocolMinorVersion);
+
+	RespondOkL();
+}
+
+//
+// CTrkDispatchLayer::DoVersionsL
+//
+// The host debugger is requesting MetroTrk version information
+//
+void CTrkDispatchLayer::DoVersions2L()
+{
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSVersions2 != command)
+		User::Leave(kDSReplyError);
+	
+	TUint8 kernelMajorVersion = MAJOR_VERSION_NUMBER;
+	TUint8 kernelMinorVersion = MINOR_VERSION_NUMBER;
+	TUint8 protocolMajorVersion = DS_PROTOCOL_MAJOR_VERSION;
+	TUint8 protocolMinorVersion = DS_PROTOCOL_MINOR_VERSION;
+	TUint8 buildNumber = BUILD_NUMBER;
+
+	AddToReplyBufferL(kernelMajorVersion, true);
+	AddToReplyBufferL(kernelMinorVersion);
+	AddToReplyBufferL(protocolMajorVersion);
+	AddToReplyBufferL(protocolMinorVersion);
+	AddToReplyBufferL(buildNumber);
+
+	RespondOkL();
+}
+
+//
+// CTrkDispatchLayer::DoVersions3L
+//
+// The host debugger is requesting MetroTrk version information
+//
+void CTrkDispatchLayer::DoVersions3L()
+{
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSVersions3 != command)
+		User::Leave(kDSReplyError);
+	
+	TUint8 kernelMajorVersion = MAJOR_VERSION_NUMBER;
+	TUint8 kernelMinorVersion = MINOR_VERSION_NUMBER;
+	TUint8 protocolMajorVersion = DS_PROTOCOL_MAJOR_VERSION;
+	TUint8 protocolMinorVersion = DS_PROTOCOL_MINOR_VERSION;
+	TUint8 buildNumber = BUILD_NUMBER;
+
+	AddToReplyBufferL(kernelMajorVersion, true);
+	AddToReplyBufferL(kernelMinorVersion);
+	AddToReplyBufferL(protocolMajorVersion);
+	AddToReplyBufferL(protocolMinorVersion);
+	AddToReplyBufferL(buildNumber);
+	
+	TUint16 len = TRK_TYPE_DESCRIPTION.Length();
+	
+	AddToReplyBufferL(len);
+	AddToReplyBufferL(TRK_TYPE_DESCRIPTION);
+
+	RespondOkL();
+}
+
+//
+// CTrkDispatchLayer::DoHostVersionsL
+//
+// The host debugger is sending the supported protocol version
+//
+void CTrkDispatchLayer::DoHostVersionsL()
+{
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSHostVersions != command)
+		User::Leave(kDSReplyError);
+	
+	GetDataFromBufferL(&iHostVersion.iMajor, 1);
+	GetDataFromBufferL(&iHostVersion.iMinor, 1);
+	
+	iFramingLayer->RespondOkL(KNullDesC8);
+}
+
+//
+// CTrkDispatchLayer::DoSupportMaskL
+//
+// The host debugger is requesting MetroTrk capabilities
+//
+void CTrkDispatchLayer::DoSupportMaskL()
+{
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSSupportMask != command)
+		User::Leave(kDSReplyError);
+	
+	TBuf8<32> supportMask;
+	TUint8 level = DS_PROTOCOL_RTOS;
+	
+	supportMask.Zero();
+	supportMask.Append(DS_SUPPORT_MASK_00_07);
+	supportMask.Append(DS_SUPPORT_MASK_08_0F);
+	supportMask.Append(DS_SUPPORT_MASK_10_17);
+	supportMask.Append(DS_SUPPORT_MASK_18_1F);
+	supportMask.Append(DS_SUPPORT_MASK_20_27);
+	supportMask.Append(DS_SUPPORT_MASK_28_2F);
+	supportMask.Append(DS_SUPPORT_MASK_30_37);
+	supportMask.Append(DS_SUPPORT_MASK_38_3F);
+	supportMask.Append(DS_SUPPORT_MASK_40_47);
+	supportMask.Append(DS_SUPPORT_MASK_48_4F);
+	supportMask.Append(DS_SUPPORT_MASK_50_57);
+	supportMask.Append(DS_SUPPORT_MASK_58_5F);
+	supportMask.Append(DS_SUPPORT_MASK_60_67);
+	supportMask.Append(DS_SUPPORT_MASK_68_6F);
+	supportMask.Append(DS_SUPPORT_MASK_70_77);
+	supportMask.Append(DS_SUPPORT_MASK_78_7F);
+	supportMask.Append(DS_SUPPORT_MASK_80_87);
+	supportMask.Append(DS_SUPPORT_MASK_88_8F);
+	supportMask.Append(DS_SUPPORT_MASK_90_97);
+	supportMask.Append(DS_SUPPORT_MASK_98_9F);
+	supportMask.Append(DS_SUPPORT_MASK_A0_A7);
+	supportMask.Append(DS_SUPPORT_MASK_A8_AF);
+	supportMask.Append(DS_SUPPORT_MASK_B0_B7);
+	supportMask.Append(DS_SUPPORT_MASK_B8_BF);
+	supportMask.Append(DS_SUPPORT_MASK_C0_C7);
+	supportMask.Append(DS_SUPPORT_MASK_C8_CF);
+	supportMask.Append(DS_SUPPORT_MASK_D0_D7);
+	supportMask.Append(DS_SUPPORT_MASK_D8_DF);
+	supportMask.Append(DS_SUPPORT_MASK_E0_E7);
+	supportMask.Append(DS_SUPPORT_MASK_E8_EF);
+	supportMask.Append(DS_SUPPORT_MASK_F0_F7);
+	supportMask.Append(DS_SUPPORT_MASK_F8_FF);
+	
+	AddToReplyBufferL(supportMask, true);
+	AddToReplyBufferL(level);
+
+	RespondOkL();
+}
+
+//
+// CTrkDispatchLayer::DoCPUTypeL
+//
+// The host debugger is requesting cpu information
+//
+void CTrkDispatchLayer::DoCPUTypeL()
+{
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSCPUType != command)
+		User::Leave(kDSReplyError);
+
+	TUint8 cpuMajor = DS_CPU_MAJOR_ARM;
+	TUint8 cpuMinor = 0;
+	TUint8 bigEndian = iFramingLayer->IsBigEndian() ? 1 : 0;
+	TUint8 defaultTypeSize = 4;
+	TUint8 fpTypeSize = 0;
+	TUint8 extended1TypeSize = 0;
+	TUint8 extended2TypeSize = 0;
+
+	AddToReplyBufferL(cpuMajor, true);
+	AddToReplyBufferL(cpuMinor);
+	AddToReplyBufferL(bigEndian);
+	AddToReplyBufferL(defaultTypeSize);
+	AddToReplyBufferL(fpTypeSize);
+	AddToReplyBufferL(extended1TypeSize);
+	AddToReplyBufferL(extended2TypeSize);
+
+	RespondOkL();
+}
+
+//
+// CTrkDispatchLayer::DoReadMemoryL
+//
+// Read memory from the target device and return to the host
+//
+void CTrkDispatchLayer::DoReadMemoryL()
+{
+	// make sure we're connected
+	if (!iIsConnected)
+	{
+		User::Leave(KErrGeneral);
+	}
+
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSReadMemory != command)
+		User::Leave(kDSReplyError);
+
+ 	// get the options
+	TUint8 options = 0;
+	GetDataFromBufferL(&options, 1);
+
+	if ((options & DS_MSG_MEMORY_EXTENDED) != 0)
+		User::Leave(kDSReplyUnsupportedOptionError);
+
+	// get the length to read
+	TUint16 length = 0;
+	GetDataFromBufferL(&length, 2);
+
+	if (length > DS_MAXREADWRITELENGTH)
+		User::Leave(kDSReplyParameterError);
+	
+	// get the start address
+	TUint32 address = 0;
+	GetDataFromBufferL(&address, 4);
+
+	// get the process id
+	TUint32 processId = 0;
+	GetDataFromBufferL(&processId, 4);
+
+	// get the thread id
+	TUint32 threadId = 0;
+	GetDataFromBufferL(&threadId, 4);
+
+	// allocate enough room for the data
+	HBufC8 *data = HBufC8::NewLC(length);
+	TPtr8 ptr(data->Des());
+
+	TInt err = iKernelDriver.ReadMemory(threadId, address, length, ptr);
+	if (KErrNone != err)
+	{
+		CleanupStack::PopAndDestroy(data);
+		User::Leave(err);
+	}
+	
+	AddToReplyBufferL(length, true);
+	AddToReplyBufferL(ptr);
+
+	RespondOkL();
+
+	CleanupStack::PopAndDestroy(data);
+}
+
+//
+// CTrkDispatchLayer::DoWriteMemoryL
+//
+// Write memory from the host to the target device
+//
+void CTrkDispatchLayer::DoWriteMemoryL()
+{
+	// make sure we're connected
+	if (!iIsConnected)
+	{
+		User::Leave(KErrGeneral);
+	}
+
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSWriteMemory != command)
+		User::Leave(kDSReplyError);
+
+ 	// get the options
+	TUint8 options = 0;
+	GetDataFromBufferL(&options, 1);
+
+	if ((options & DS_MSG_MEMORY_EXTENDED) != 0)
+		User::Leave(kDSReplyUnsupportedOptionError);
+
+	// get the length to write
+	TUint16 length = 0;
+	GetDataFromBufferL(&length, 2);
+
+	if (length > DS_MAXREADWRITELENGTH)
+		User::Leave(kDSReplyParameterError);
+	
+	// get the start address
+	TUint32 address = 0;
+	GetDataFromBufferL(&address, 4);
+
+	// get the process id
+	TUint32 processId = 0;
+	GetDataFromBufferL(&processId, 4);
+
+	// get the thread id
+	TUint32 threadId = 0;
+	GetDataFromBufferL(&threadId, 4);
+
+	User::LeaveIfError(iKernelDriver.WriteMemory(threadId, address, length, *iInputBuffer));
+	
+	AddToReplyBufferL(length, true);
+
+	RespondOkL();
+}
+
+//
+// CTrkDispatchLayer::DoReadRegistersL
+//
+// Read registers from the target device and return to the host
+//
+void CTrkDispatchLayer::DoReadRegistersL()
+{
+	// make sure we're connected
+	if (!iIsConnected)
+	{
+		User::Leave(KErrGeneral);
+	}
+
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSReadRegisters != command)
+		User::Leave(kDSReplyError);
+
+	// get the options
+	TUint8 options = 0;
+	GetDataFromBufferL(&options, 1);
+
+	if (DS_MSG_REGISTERS_TYPE(options) != kDSRegistersDefault)
+		User::Leave(kDSReplyUnsupportedOptionError);
+		
+	// get the first register
+	TInt16 firstRegister = 0;
+	GetDataFromBufferL(&firstRegister, 2);
+
+	// get the last register
+	TInt16 lastRegister = 0;
+	GetDataFromBufferL(&lastRegister, 2);
+
+	if ((firstRegister < 0) || (lastRegister > 16))
+		User::Leave(kDSReplyInvalidRegisterRange);
+	
+	// get the process id
+	TUint32 processId = 0;
+	GetDataFromBufferL(&processId, 4);
+
+	// get the thread id
+	TUint32 threadId = 0;
+	GetDataFromBufferL(&threadId, 4);
+
+	// allocate enough space to hold the values
+	HBufC8 *values = HBufC8::NewLC((lastRegister - firstRegister + 1) * 4);
+	TPtr8 ptr(values->Des());
+	
+	TInt err = iKernelDriver.ReadRegisters(threadId, firstRegister, lastRegister, ptr);
+	if (KErrNone != err)
+	{
+		CleanupStack::PopAndDestroy(values);
+		User::Leave(err);
+	}
+	
+	for (int i=0; i<=lastRegister - firstRegister; i++)
+		AddToReplyBufferL(*(TUint32 *)&ptr.Ptr()[i*4], i==0 ? true : false);
+			
+	RespondOkL();
+
+	CleanupStack::PopAndDestroy(values);
+}
+
+//
+// CTrkDispatchLayer::DoWriteRegistersL
+//
+// Write registers from the host to the target device
+//
+void CTrkDispatchLayer::DoWriteRegistersL()
+{
+	// make sure we're connected
+	if (!iIsConnected)
+	{
+		User::Leave(KErrGeneral);
+	}
+
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSWriteRegisters != command)
+		User::Leave(kDSReplyError);
+
+	// get the options
+	TUint8 options = 0;
+	GetDataFromBufferL(&options, 1);
+
+	if (DS_MSG_REGISTERS_TYPE(options) != kDSRegistersDefault)
+		User::Leave(kDSReplyUnsupportedOptionError);
+
+	// get the first register
+	TInt16 firstRegister = 0;
+	GetDataFromBufferL(&firstRegister, 2);
+
+	// get the last register
+	TInt16 lastRegister = 0;
+	GetDataFromBufferL(&lastRegister, 2);
+
+	if ((firstRegister < 0) || (lastRegister > 16))
+		User::Leave(kDSReplyInvalidRegisterRange);
+
+	// get the process id
+	TUint32 processId = 0;
+	GetDataFromBufferL(&processId, 4);
+
+	// get the thread id
+	TUint32 threadId = 0;
+	GetDataFromBufferL(&threadId, 4);
+	
+	// MetroTrk register values come in as big endian so we may need to swap them
+	if (!iFramingLayer->IsBigEndian())
+	{
+		Swap4xN((TUint32 *)iInputBuffer->Ptr(), lastRegister-firstRegister + 1);
+	}
+	
+	User::LeaveIfError(iKernelDriver.WriteRegisters(threadId, firstRegister, lastRegister, *iInputBuffer));
+	
+	iFramingLayer->RespondOkL(KNullDesC8);
+}
+
+//
+// CTrkDispatchLayer::DoContinueL
+//
+// Resume thread execution
+//
+void CTrkDispatchLayer::DoContinueL()
+{
+	// make sure we're connected
+	if (!iIsConnected)
+	{
+		User::Leave(KErrGeneral);
+	}
+
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSContinue != command)
+		User::Leave(kDSReplyError);
+
+	// get the process id
+	TUint32 processId = 0;
+	GetDataFromBufferL(&processId, 4);
+
+	// get the thread id
+	TUint32 threadId = 0;
+	GetDataFromBufferL(&threadId, 4);
+	
+	// see if this thread is in the the suspended threads list
+	// if so, remove it and resume.  otherwise we need to handle
+	// the special case of the first time a thread is resumed
+	TInt index = iSuspendedThreadList.Find(threadId);
+	if (index >= 0)
+	{
+		iSuspendedThreadList.Remove(index);
+		User::LeaveIfError(iKernelDriver.ResumeThread(threadId));
+		iFramingLayer->RespondOkL(KNullDesC8);
+	}
+	else
+	{
+		// if it's not in the suspended list then this is the first time it has been
+		// resumed (the process has just been created).  see if there are statically
+		// linked libraries that we need to report to the host debugger.  if so, we
+		// don't really want to resume yet.  let the host debugger set any breakpoints
+		// in the libraries first.  it will call resume again once it's done.
+
+		// since we never mark it as suspended, we'll actually get here when the host
+		// debugger calls resume the second time.  we really don't want to mark it as
+		// suspended because then the host debugger will try to draw the thread window
+		TBool found = EFalse;
+		for (TInt i=0; i<iDebugProcessList.Count(); i++)
+		{
+			if (iDebugProcessList[i]->ProcessId() == processId)
+			{
+				found = ETrue;
+				// if we're already marked it as ready, just resume and return
+				if (iDebugProcessList[i]->iReadyForLibraryLoadNotification)
+				{
+					User::LeaveIfError(iKernelDriver.ResumeThread(threadId));
+					iFramingLayer->RespondOkL(KNullDesC8);		
+					return;
+				}
+
+				iDebugProcessList[i]->iReadyForLibraryLoadNotification = ETrue;
+				break;
+			}
+		}
+		// For RUN mode, we created the process but we didn't put it into the list
+		// therefore we do not want to notify the host debugger about static libraries
+		// so just resume and return  (see DoCreateExeL)
+		// The host debugger will soon disconnect in this mode
+		if (!found)
+		{
+			User::LeaveIfError(iKernelDriver.ResumeThread(threadId));
+			iFramingLayer->RespondOkL(KNullDesC8);		
+			return;
+		}
+
+		// the process has been created and the host debugger is listening for messages
+		// see if there are any statically linked libraries for this process.  if so, let
+		// the host debugger know about them now. note that the host debugger will send
+		// another resume command once it's handled the static libraries.  if there are
+		// not static libraries for this process, we really do need to resume the thread.
+		
+		TInt err = KErrNone;
+		TInt i = 0;
+		for (i=0; KErrNone==err; i++)
+		{
+			SEventInfo info;
+			info.iProcessId = processId;
+			info.iThreadId = threadId;
+			err = iKernelDriver.GetStaticLibraryInfo(i, info);
+			
+			if (KErrNone == err)
+			{
+				DoNotifyLibraryLoadedL(info.iFileName, info.iProcessId, 0xFFFFFFFF, info.iCodeAddress, info.iDataAddress);
+			}
+			//else if (0 == i)
+			//{
+				// there are no static libraries for this process
+				//User::LeaveIfError(iKernelDriver.ResumeThread(threadId));			
+			//}
+		}
+		//Always resume the thread instead of asking the host debugger to resume when sending the last static library notification.
+		User::LeaveIfError(iKernelDriver.ResumeThread(threadId));			
+		iFramingLayer->RespondOkL(KNullDesC8);		
+	}
+}
+
+//
+// CTrkDispatchLayer::DoStepL
+//
+// Execute one instruction in a thread
+//
+void CTrkDispatchLayer::DoStepL()
+{
+	// make sure we're connected
+	if (!iIsConnected)
+	{
+		User::Leave(KErrGeneral);
+	}
+
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSStep != command)
+		User::Leave(kDSReplyError);
+
+	// get the options
+	TUint8 options = 0;
+	GetDataFromBufferL(&options, 1);
+	
+	// we only support stepping out of a range of instructions
+	if ((kDSStepIntoRange != options) && (kDSStepOverRange != options))
+	{
+		User::Leave(kDSReplyUnsupportedOptionError);
+	}
+
+	// get the range start address
+	TUint32 startAddress = 0;
+	GetDataFromBufferL(&startAddress, 4);
+
+	// get the range stop address
+	TUint32 stopAddress = 0;
+	GetDataFromBufferL(&stopAddress, 4);
+		
+	// get the process id
+	TUint32 processId = 0;
+	GetDataFromBufferL(&processId, 4);
+
+	// get the thread id
+	TUint32 threadId = 0;
+	GetDataFromBufferL(&threadId, 4);
+
+	User::LeaveIfError(iKernelDriver.StepRange(threadId, startAddress, stopAddress, (kDSStepIntoRange == options)));
+
+	iFramingLayer->RespondOkL(KNullDesC8);
+}
+
+//
+// CTrkDispatchLayer::DoStopL
+//
+// Stop the execution of a thread
+//
+void CTrkDispatchLayer::DoStopL()
+{
+	// make sure we're connected
+	if (!iIsConnected)
+	{
+		User::Leave(KErrGeneral);
+	}
+
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSStop != command)
+		User::Leave(kDSReplyError);
+
+	// get the options
+	TUint8 options = 0;
+	GetDataFromBufferL(&options, 1);
+	
+	TUint32 processId = 0;
+	TUint32 threadId = 0;
+	
+	switch(options)
+	{
+		case kDSStopThread:
+		{
+			// get the process id
+			GetDataFromBufferL(&processId, 4);
+
+			// get the thread id
+			GetDataFromBufferL(&threadId, 4);
+			
+			User::LeaveIfError(iKernelDriver.SuspendThread(threadId));
+			
+			break;
+		}
+		case kDSStopSystem:
+		case kDSStopProcess:
+		default:
+		{
+			User::Leave(kDSReplyUnsupportedOptionError);
+			break;
+		}
+	}
+
+	iFramingLayer->RespondOkL(KNullDesC8);
+	
+	TBuf8<4> currentPC;
+	
+	User::LeaveIfError(iKernelDriver.ReadRegisters(threadId, 15, 15, currentPC));
+	
+	DoNotifyStoppedL(processId, threadId, *(TUint32 *)currentPC.Ptr(), KNullDesC8);
+}
+
+//
+// CTrkDispatchLayer::DoSetBreakL
+//
+// Set a breakpoint
+//
+void CTrkDispatchLayer::DoSetBreakL()
+{
+	// make sure we're connected
+	if (!iIsConnected)
+	{
+		User::Leave(KErrGeneral);
+	}
+
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSSetBreak != command)
+		User::Leave(kDSReplyError);
+
+	// get the options - unused
+	TUint8 options = 0;
+	GetDataFromBufferL(&options, 1);
+
+	// get the mode
+	TUint8 thumbMode = 0;
+	GetDataFromBufferL(&thumbMode, 1);
+
+	// get the address
+	TUint32 address = 0;
+	GetDataFromBufferL(&address, 4);
+
+	// get the length
+	TUint32 length = 0;
+	GetDataFromBufferL(&length, 4);
+
+	// get the count
+	TUint32 count = 0;
+	GetDataFromBufferL(&count, 4);
+
+	// get the process id
+	TUint32 processId = 0;
+	GetDataFromBufferL(&processId, 4);
+
+	// get the thread id
+	TUint32 threadId = 0;
+	GetDataFromBufferL(&threadId, 4);
+	
+	TInt32 breakId = 0;
+	User::LeaveIfError(iKernelDriver.SetBreak(processId, threadId, address, thumbMode, breakId));
+
+	// return the id of this breakpoint to the host debugger
+	AddToReplyBufferL((TUint32)breakId, true);
+	
+	RespondOkL();
+}
+
+//
+// CTrkDispatchLayer::DoClearBreakL
+//
+// Clear a breakpoint
+//
+void CTrkDispatchLayer::DoClearBreakL()
+{
+	// make sure we're connected
+	if (!iIsConnected)
+	{
+		User::Leave(KErrGeneral);
+	}
+
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+
+	if (kDSClearBreak != command)
+		User::Leave(kDSReplyError);
+
+	// get the breakpoint id
+	TUint32 breakId = 0;
+	GetDataFromBufferL(&breakId, 4);
+
+	User::LeaveIfError(iKernelDriver.ClearBreak(breakId));
+
+	iFramingLayer->RespondOkL(KNullDesC8);
+}
+
+//
+// CTrkDispatchLayer::DoModifyBreakThreadL
+//
+// Change the thread(s) that a breakpoint is associated with
+//
+void CTrkDispatchLayer::DoModifyBreakThreadL()
+{
+	// make sure we're connected
+	if (!iIsConnected)
+	{
+		User::Leave(KErrGeneral);
+	}
+
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+
+	if (kDSModifyBreakThread != command)
+		User::Leave(kDSReplyError);
+
+	// get the breakpoint id
+	TUint32 breakId = 0;
+	GetDataFromBufferL(&breakId, 4);
+
+	// get the thread id
+	TUint32 threadId = 0;
+	GetDataFromBufferL(&threadId, 4);
+
+	User::LeaveIfError(iKernelDriver.ChangeBreakThread(threadId, breakId));
+
+	iFramingLayer->RespondOkL(KNullDesC8);
+}
+
+//
+// CTrkDispatchLayer::DoCreateItemL
+//
+// Create a new OS item on the target device
+//
+void CTrkDispatchLayer::DoCreateItemL()
+{
+	// make sure we're connected
+	if (!iIsConnected)
+	{
+		User::Leave(KErrGeneral);
+	}
+
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSOSCreateItem != command)
+		User::Leave(kDSReplyError);
+
+	// get the item type
+	TUint16 type = 0;
+	GetDataFromBufferL(&type, 2);
+
+	switch(type)
+	{
+		case kDSOSProcessItem:
+		{
+			DoCreateProcessL();
+			break;
+		}
+		case kDSOSProcRunItem:
+		{
+			DoCreateProcessL(ETrue);
+			break;
+		}
+		case kDSOSProcAttachItem:
+		{
+			DoAttachProcessL(kDSOSProcAttachItem);
+			break;
+		}
+		case kDSOSProcAttach2Item:
+		{
+			DoAttachProcessL(kDSOSProcAttach2Item);
+			break;
+		}
+		case kDSOSProcAttach3Item:
+		{
+			DoAttachProcessL(kDSOSProcAttach3Item);
+			break;
+		}
+		case kDSOSThreadItem:
+		case kDSOSDLLItem:
+		case kDSOSAppItem:
+		case kDSOSMemBlockItem:
+		case kDSOSThreadAttachItem:
+		default:
+		{
+			User::Leave(kDSReplyUnsupportedOptionError);
+			break;
+		}
+	}
+}
+
+//
+// CTrkDispatchLayer::DoDeleteItemL
+//
+// Delete an OS item from the target device
+//
+void CTrkDispatchLayer::DoDeleteItemL()
+{
+	// make sure we're connected
+	if (!iIsConnected)
+	{
+		User::Leave(KErrGeneral);
+	}
+
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSOSDeleteItem != command)
+		User::Leave(kDSReplyError);
+
+	// get the item type
+	TUint16 type = 0;
+	GetDataFromBufferL(&type, 2);
+
+	switch(type)
+	{
+		case kDSOSProcessItem:
+		{
+			DoKillProcessL();
+			break;
+		}
+		case kDSOSProcAttachItem:
+		{
+		    DoDetachProcessL();
+			break;
+		}
+		case kDSOSThreadItem:
+		case kDSOSDLLItem:
+		case kDSOSAppItem:
+		case kDSOSMemBlockItem:
+		case kDSOSThreadAttachItem:
+		default:
+		{
+			User::Leave(kDSReplyUnsupportedOptionError);
+			break;
+		}
+	}
+}
+
+//
+// CTrkDispatchLayer::DoReadInfoL
+//
+// Read OS information from the target device
+//
+void CTrkDispatchLayer::DoReadInfoL()
+{	
+	// make sure we're connected
+	if (!iIsConnected)
+	{
+		User::Leave(KErrGeneral);
+	}
+
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+
+	if (kDSOSReadInfo != command)
+		User::Leave(kDSReplyError);
+
+	// get the type of info requested
+	TUint16 type = 0;
+	GetDataFromBufferL(&type, 2);
+
+	// get the start index
+	TUint32 index = 0;
+	GetDataFromBufferL(&index, 4);	
+	
+	switch(type)
+	{
+		case kDSOSProcessList:
+		{
+			DoReadProcessListL(index);
+			break;
+		}
+		case kDSOSThreadList:
+		{
+			DoReadThreadListL(index);
+			break;
+		}
+		case kDSOSDLLInfo:
+		{
+			TUint16 nameLength = 0;
+			GetDataFromBufferL(&nameLength, 2);
+			
+			// make sure the length of the message is correct
+			if (iInputBuffer->Length() != nameLength)
+				User::Leave(kDSReplyPacketSizeError);
+			
+			TBuf8<KMaxFileName> fileName;
+			fileName.Copy(*iInputBuffer);
+			fileName.ZeroTerminate();
+
+			DoReadLibraryInfoL(fileName);
+			break;
+		}
+		case kDSOSProcessInfo:
+		{
+			TUint32 uid3 = 0;
+			GetDataFromBufferL(&uid3, 4);
+			TUint16 nameLength = 0;
+			GetDataFromBufferL(&nameLength, 2);
+			
+			// make sure the length of the message is correct
+			if (iInputBuffer->Length() != nameLength)
+				User::Leave(kDSReplyPacketSizeError);
+			
+			TBuf8<KMaxFileName> fileName;
+			fileName.Copy(*iInputBuffer);
+			fileName.ZeroTerminate();
+			
+			DoReadProcessInfoL(uid3, fileName);
+			break;
+		}
+		case kDSOSProcessState:
+		case kDSOSThreadState:
+		case kDSOSDLLList:
+		case kDSOSDLLState:
+		default:
+		{
+			User::Leave(kDSReplyUnsupportedOptionError);
+			break;
+		}
+	}
+}
+
+//
+// CTrkDispatchLayer::DoWriteInfoL
+//
+// Set options for the Trk
+//
+void CTrkDispatchLayer::DoWriteInfoL()
+{
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+
+	if (kDSOSWriteInfo != command)
+		User::Leave(kDSReplyError);
+
+	// get the type of info requested
+	TUint16 type = 0;
+	GetDataFromBufferL(&type, 2);
+
+	// get the start index
+	TUint32 index = 0;
+	GetDataFromBufferL(&index, 4);
+
+	// no options supported yet.  might add something for auto-target libraries later
+	User::Leave(kDSReplyUnsupportedOptionError);
+}
+
+//
+// CTrkDispatchLayer::DoOpenFileL
+//
+// Open or create a file on the target
+//
+void CTrkDispatchLayer::DoOpenFileL()
+{
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSOSOpenFile != command)
+		User::Leave(kDSReplyError);
+
+	// get the file mode(s)
+	TUint8 modes = 0;
+	GetDataFromBufferL(&modes, 1);
+
+	if ((modes & kDSFileOpenAppend) || (modes & kDSFileOpenCreate))
+		modes |= kDSFileOpenWrite;
+
+	TUint16 nameLength = 0;
+	GetDataFromBufferL(&nameLength, 2);
+	
+	// make sure the length of the message is correct
+	if (iInputBuffer->Length() != nameLength)
+		User::Leave(kDSReplyPacketSizeError);
+	
+	TBuf<KMaxPath> fullpath;
+	fullpath.Copy(*iInputBuffer);
+	fullpath.ZeroTerminate();
+		
+	TUint mode = EFileShareExclusive;
+
+	// get the file mode(s)
+	if (modes & kDSFileOpenRead)
+		mode |= EFileRead;
+
+	if (modes & kDSFileOpenWrite)
+		mode |= EFileWrite;
+
+	if (modes & kDSFileOpenAppend)
+		mode |= EFileWrite;
+
+	if (modes & kDSFileOpenCreate)
+		mode |= EFileWrite;
+	
+
+	//for getting the modification date
+	TTime time;
+	
+	OpenFileL(fullpath, mode, time);
+	
+	TDateTime dateTime = time.DateTime();
+
+	TDateTimeConverter winTime(dateTime);
+	
+	TUint32 timestamp = winTime.GetWinTimeDate();
+
+	TUint32 handle = 1;
+	TUint8 err = 0;
+
+	AddToReplyBufferL(err, true);
+	AddToReplyBufferL(handle);
+	AddToReplyBufferL(timestamp);
+	
+	RespondOkL();
+}
+
+//
+// CTrkDispatchLayer::OpenFileL
+//
+// Open a file on the target, if plat security is enabled, uses TrkTcbServer to open the file.
+//
+void CTrkDispatchLayer::OpenFileL(const TDesC& aFullPath, TUint aMode, TTime& aTime)
+{
+
+#ifdef __OEM_TRK__	
+	//Check to see if TCB capability is enforced, if so, connect to the tcb server as well.
+	if (!iUseTcbServer && PlatSec::IsCapabilityEnforced(ECapabilityTCB))
+	{
+		if (!iTrkTcbSession.Connect())
+		{
+			iUseTcbServer = ETrue;
+		}	
+	}
+
+	if (iUseTcbServer)
+	{
+		User::LeaveIfError(iTrkTcbSession.OpenFile(aFullPath, aMode, aTime));
+	}
+	else
+#endif	
+	{
+	#ifndef __OEM_TRK__
+		if (IsRestrictedFolder(aFullPath))
+			User::Leave(KErrAccessDenied);
+	#endif
+		// connect to the file server
+		User::LeaveIfError(iFs.Connect());
+
+		TInt error = iFs.MkDirAll(aFullPath);
+
+		if ((KErrNone != error) && (KErrAlreadyExists != error))
+		{
+			iFs.Close();
+			User::Leave(error);
+		}
+		
+		error = iFile.Open(iFs, aFullPath, aMode);
+		
+		if (KErrNone != error)
+			User::LeaveIfError(iFile.Replace(iFs, aFullPath, aMode));
+		
+		User::LeaveIfError(iFile.Modified(aTime));
+		iFileState = EFileOpened;
+	}
+}
+
+//
+// CTrkDispatchLayer::DoReadFileL
+//
+// Read data from a file on the target
+//
+void CTrkDispatchLayer::DoReadFileL()
+{
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSOSReadFile != command)
+		User::Leave(kDSReplyError);
+
+	// make sure the length of the message is correct
+	if (iInputBuffer->Length() != 6)
+		User::Leave(kDSReplyPacketSizeError);
+	
+	// remove the handle
+	iInputBuffer->Des().Delete(0, 4);
+
+	// get the length
+	TUint8 err = 0;
+	TUint16 length = 0;
+	GetDataFromBufferL(&length, 2);
+	
+	// allocate a buffer large enough for the data
+	HBufC8 *buffer = HBufC8::NewLC(length);
+	TPtr8 ptr(buffer->Des());
+	
+	//	CleanupStack::PushL(buffer);
+	
+	TInt error = ReadFileL(length, ptr);	
+	if (KErrNone != error)
+	{
+		CleanupStack::PopAndDestroy(buffer);	
+		User::Leave(error);
+	}
+	
+	length = buffer->Length();
+	
+	AddToReplyBufferL(err, true);
+	AddToReplyBufferL(length);
+//	AddToReplyBufferL(buffer[0], length);
+	AddToReplyBufferL(ptr);
+	RespondOkL();
+	
+	CleanupStack::PopAndDestroy(buffer);
+}
+
+//
+// CTrkDispatchLayer::ReadFileL
+//
+// Reads data from a file on the target
+//
+TInt CTrkDispatchLayer::ReadFileL(TUint16 aLength, TPtr8& aData)
+{
+	TInt error = KErrNone;
+
+#ifdef __OEM_TRK__
+	if (iUseTcbServer)
+	{
+		User::LeaveIfError(iTrkTcbSession.ReadFile(aLength, aData));
+	}
+	else
+#endif	
+	{
+		iFileState = EFileReading;
+		error = iFile.Read(aData);
+	}
+	return error;
+}
+
+//
+// CTrkDispatchLayer::DoWriteFileL
+//
+// Write data to a file on the target
+//
+void CTrkDispatchLayer::DoWriteFileL()
+{
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSOSWriteFile != command)
+		User::Leave(kDSReplyError);
+	
+	// get the length
+	TUint32 handle = 0;
+	GetDataFromBufferL(&handle, 4);
+	
+	if (handle != 1)
+		User::Leave(kDSReplyParameterError);
+
+	// get the length
+	TUint8 err = 0;
+	TUint16 length = 0;
+	GetDataFromBufferL(&length, 2);
+
+	// make sure the length of the message is correct
+	if (iInputBuffer->Length() != length)
+		User::Leave(kDSReplyPacketSizeError);
+		
+	WriteFileL(*iInputBuffer);
+	
+	length = iInputBuffer->Length();
+	
+	AddToReplyBufferL(err, true);
+	AddToReplyBufferL(length);
+	RespondOkL();
+}
+
+//
+// CTrkDispatchLayer::WriteFileL
+//
+// Write data to a file on the target. If plat sec is enabled, uses Trk Tcb Server.
+//
+void CTrkDispatchLayer::WriteFileL(TDesC8& aData)
+{
+#ifdef __OEM_TRK__
+	if (iUseTcbServer)
+	{
+		User::LeaveIfError(iTrkTcbSession.WriteFile(aData));
+	}
+	else
+#endif	
+	{	
+		if (iFileState == EFileOpened)
+		{
+			iFile.SetSize(0);
+			iFileState = EFileWriting;
+		}
+		User::LeaveIfError(iFile.Write(aData));
+		User::LeaveIfError(iFile.Flush());
+	}
+}
+
+//
+// CTrkDispatchLayer::DoPositionFileL
+//
+// Change the current file position of a file on the target
+//
+void CTrkDispatchLayer::DoPositionFileL()
+{
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSOSPositionFile != command)
+		User::Leave(kDSReplyError);
+
+	// make sure the length of the message is correct
+	if (iInputBuffer->Length() != 9)
+		User::Leave(kDSReplyPacketSizeError);
+	
+	// get the positioning mode
+	TUint8 mode = 0;
+	GetDataFromBufferL(&mode, 1);
+
+	// remove the handle
+	iInputBuffer->Des().Delete(0, 4);
+
+	TUint8 err = 0;
+	TUint32 offset = 0;
+	GetDataFromBufferL(&offset, 4);
+
+	TSeek seek;
+	
+	// convert mode to native parameter and set the position accordingly
+	switch(mode)
+	{
+		default:
+		case kDSFileSeekSet:
+		{
+			seek = ESeekStart;
+			break;
+		}
+		case kDSFileSeekCur:
+		{
+			seek = ESeekCurrent;
+			break;
+		}
+		case kDSFileSeekEnd:
+		{
+			seek = ESeekEnd;
+			break;
+		}
+	}
+
+	PositionFileL(seek, (TInt &)offset);
+
+	AddToReplyBufferL(err, true);
+	
+	RespondOkL();
+}
+
+//
+// CTrkDispatchLayer::PositionFileL
+//
+// Change the current file position of a file on the target. If plat sec is enabled,
+// uses Trk Tcb Server.
+//
+void CTrkDispatchLayer::PositionFileL(TSeek aSeek, TInt& aOffset)
+{
+#ifdef __OEM_TRK__
+	if (iUseTcbServer)
+	{
+		User::LeaveIfError(iTrkTcbSession.PositionFile(aSeek, aOffset));
+	}
+	else
+#endif	
+	{
+		User::LeaveIfError(iFile.Seek(aSeek, aOffset));
+	}
+}
+
+
+//
+// CTrkDispatchLayer::DoCloseFileL
+//
+// Close a file on the target
+//
+void CTrkDispatchLayer::DoCloseFileL()
+{
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSOSCloseFile != command)
+		User::Leave(kDSReplyError);
+
+	// make sure the length of the message is correct
+	if (iInputBuffer->Length() != 8)
+		User::Leave(kDSReplyPacketSizeError);
+
+	// remove the handle
+	iInputBuffer->Des().Delete(0, 4);
+	
+	TUint8 err = 0;
+	TUint32 timestamp = 0;
+	GetDataFromBufferL(&timestamp, 4);
+	
+	TDateTimeConverter epocTime(timestamp);
+	
+	CloseFileL(epocTime.GetEpocTimeDate());
+
+	AddToReplyBufferL(err, true);
+
+	RespondOkL();
+}
+
+//
+// CTrkDispatchLayer::CloseFileL
+//
+// Close a file on the target. If plat sec is enabled, uses Trk Tcb Server.
+//
+void CTrkDispatchLayer::CloseFileL(const TTime& aModifiedTime)
+{
+#ifdef __OEM_TRK__
+	if (iUseTcbServer)
+	{
+		User::LeaveIfError(iTrkTcbSession.CloseFile(aModifiedTime));
+	}
+	else
+#endif	
+	{
+		User::LeaveIfError(iFile.SetModified(aModifiedTime));
+		User::LeaveIfError(iFile.Flush());
+		
+		iFile.Close();
+		iFs.Close();
+		iFileState = EFileClosed;
+	}
+}
+
+//
+// CTrkDispatchLayer::DoInstallFileL
+//
+// Install the application, supplied as a SIS file.
+//
+void CTrkDispatchLayer::DoInstallFileL()
+{
+	// make sure we're connected
+	if (!iIsConnected)
+	{
+		User::Leave(KErrGeneral);
+	}
+
+#ifndef __TEXT_SHELL__
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSOSInstallFile != command)
+		User::Leave(kDSReplyError);
+
+	// get the installation drive
+	TUint8 drive = 'C';
+	GetDataFromBufferL(&drive, 1);
+	
+	TChar installDrive(drive);
+
+	TUint16 nameLength = 0;
+	GetDataFromBufferL(&nameLength, 2);
+	
+	// make sure the length of the message is correct
+	if (iInputBuffer->Length() != nameLength)
+		User::Leave(kDSReplyPacketSizeError);
+	
+	TBuf<KMaxPath> fullpath;
+	fullpath.Copy(*iInputBuffer);
+	fullpath.ZeroTerminate();
+			
+	TUint8 err = 0;
+	// Temporarily disable the lib loaded event before launching the SW Installer.
+	// This is necessary when launching the SIS installer since  launching the 
+	// installer causes several libraries to be loaded. The driver suspends the 
+	// thread thats loaded the library. This suspension might potentially cause 
+	// a deadlock as the event handling active object will never get a chance to 
+	// run as the Install function below blocks until the installation is completed.
+	User::LeaveIfError(iKernelDriver.DisableLibLoadedEvent());
+	
+	// now launch the installer
+	User::LeaveIfError(CTrkSwInstall::SilentInstallL(fullpath, installDrive));
+
+	// now enable the lib loaded event
+	iKernelDriver.EnableLibLoadedEvent();
+	
+	AddToReplyBufferL(err, true);
+	RespondOkL();
+#else 
+	User::LeaveIfError(-1); 
+#endif
+}
+
+//
+// CTrkDispatchLayer::DoInstallFileL
+//
+// Install the application, supplied as a SIS file.
+//
+void CTrkDispatchLayer::DoInstallFile2L()
+{
+	// make sure we're connected
+	if (!iIsConnected)
+	{
+		User::Leave(KErrGeneral);
+	}
+
+#ifndef __TEXT_SHELL__
+	// make sure we got here from DispatchMsgL
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+	
+	if (kDSOSInstallFile2 != command)
+		User::Leave(kDSReplyError);
+
+	TUint16 nameLength = 0;
+	GetDataFromBufferL(&nameLength, 2);
+	
+	// make sure the length of the message is correct
+	if (iInputBuffer->Length() != nameLength)
+		User::Leave(kDSReplyPacketSizeError);
+	
+	TBuf<KMaxPath> fullpath;
+	fullpath.Copy(*iInputBuffer);
+	fullpath.ZeroTerminate();
+			
+	TUint8 err = 0;
+	// Temporarily disable the lib loaded event before launching the SW Installer.
+	// This is necessary when launching the SIS installer since  launching the 
+	// installer causes several libraries to be loaded. The driver suspends the 
+	// thread thats loaded the library. This suspension might potentially cause 
+	// a deadlock as the event handling active object will never get a chance to 
+	// run as the Install function below blocks until the installation is completed.
+	User::LeaveIfError(iKernelDriver.DisableLibLoadedEvent());
+
+	// now launch the installer
+	User::LeaveIfError(CTrkSwInstall::Install(fullpath));
+
+	// now enable the lib loaded event
+	iKernelDriver.EnableLibLoadedEvent();
+	
+	AddToReplyBufferL(err);
+	RespondOkL();
+#else
+	User::LeaveIfError(-1);
+#endif
+}
+
+
+//
+// CTrkDispathLayer::DoGetPhoneSWVesionL()
+//
+// sends  the software version of the phone to reply buffer
+//
+void CTrkDispatchLayer::DoGetPhoneSWVersionL()
+{
+    // make sure we got here from DispatchMsgL
+    
+	TUint8 command = 0;
+	GetDataFromBufferL(&command, 1);
+
+	if (kDSOSPhoneSWVersion != command)
+	{
+		User::Leave(kDSReplyError);
+	}
+#ifndef __TEXT_SHELL__
+	if (iPhoneVersion.Size()>0 )
+	{
+		TUint16 versionNameLength = iPhoneVersion.Length();
+		AddToReplyBufferL(versionNameLength, ETrue); 
+		AddToReplyBufferL(iPhoneVersion);       
+		RespondOkL();
+	}
+	else
+#endif	    
+	{
+		User::Leave(KErrGeneral);
+	}    
+                
+}
+
+
+//
+//CTrkDispathLayer::DoGetPhoneNameL()
+//
+//sends the phone model name to the reply buffer
+//
+void CTrkDispatchLayer::DoGetPhoneNameL()
+{    
+    TUint8 command = 0;
+    GetDataFromBufferL(&command, 1);
+    
+    if (kDSOSPhoneName != command)
+    {
+    	User::Leave(kDSReplyError);
+	}
+
+#ifndef __TEXT_SHELL__
+    if (iPhoneNameInfoAvailable)
+    {
+     	TUint16 phoneModelLen = iPhoneModel.Length();
+     	AddToReplyBufferL(phoneModelLen, true);
+     	AddToReplyBufferL(iPhoneModel);
+        RespondOkL();
+    }    
+    else
+#endif
+    {
+        User::Leave(KErrGeneral);
+    }
+}
+//
+//To Update the phone model name 
+//
+//callback function from the CPhoneInfo
+//
+void CTrkDispatchLayer::UpdatePhoneNameInfo(TDesC16& aPhoneModel)
+{
+#ifndef __TEXT_SHELL__
+    iPhoneModel.Copy(aPhoneModel);
+    iPhoneNameInfoAvailable = ETrue;    
+#endif
+}
+
+//
+// CTrkDispatchLayer::DoCreateProcessL
+//
+// Create a new process on the target device
+//
+void CTrkDispatchLayer::DoCreateProcessL(TBool aRun)
+{
+	// remove the options - currently unused
+	iInputBuffer->Des().Delete(0, 1);
+
+	// get the length of the data
+	TUint16 length = 0;
+	GetDataFromBufferL(&length, 2);
+
+	// make sure the length of the message is correct
+	if (iInputBuffer->Length() != length)
+		User::Leave(kDSReplyPacketSizeError);
+
+	// extract the filename and path, command line args, and working directory
+	TPtrC8 exec8(iInputBuffer->Ptr());
+	TPtrC8 args8(exec8.Ptr() + exec8.Length() + 1);
+		
+	// convert the filename and args to unicode descriptors
+	HBufC* exec = HBufC::NewLC(exec8.Length());
+	exec->Des().Copy(exec8);
+
+	HBufC* args = HBufC::NewLC(args8.Length());
+	args->Des().Copy(args8);
+
+	// open the file and get the type (app, exe, etc.)
+	RFs fs;
+	
+	// connect to the file server
+	User::LeaveIfError(fs.Connect());
+	
+	TEntry entry;
+		
+	User::LeaveIfError(fs.Entry(*exec, entry));
+	
+	fs.Close();
+
+	TCreateProcessData data;
+		
+	switch(entry[0].iUid)
+	{
+		case 0x1000007a:
+		{
+			// EXE
+			DoCreateExeL(*exec, *args, data, aRun);
+			break;
+		}
+		default:
+			User::Leave(KErrGeneral);
+	}
+
+	CleanupStack::PopAndDestroy(args);
+	CleanupStack::PopAndDestroy(exec);
+
+	AddToReplyBufferL(data.iProcessId, true);
+	AddToReplyBufferL(data.iMainThreadId);
+	if (!aRun)
+	{
+		AddToReplyBufferL(data.iCodeAddr);
+		AddToReplyBufferL(data.iDataAddr);
+	}
+		
+	RespondOkL();
+}
+
+//
+// CTrkDispatchLayer::DoCreateExeL
+//
+// Create a new executable on the target device
+//
+void CTrkDispatchLayer::DoCreateExeL(const TDesC& aPath, const TDesC& aArgs, TCreateProcessData& aData, TBool aRun)
+{
+	RProcess process;
+	User::LeaveIfError(process.Create(aPath, aArgs));
+	CleanupClosePushL(process);
+
+	aData.iProcessId = process.Id();
+	
+	HBufC* threadName = HBufC::NewLC(KMaxFullName);
+
+	*threadName = process.Name();
+	_LIT(KMainThreadSuffix, "::Main");
+	threadName->Des().Append(KMainThreadSuffix);
+
+	// this function should be (indirectly) called when the debuggee
+	// has been created but not yet resumed.  So it should have a main
+	// thread whose name ends with "::Main", and so the following call
+	// should not fail.
+	RThread thread;
+	User::LeaveIfError(thread.Open(*threadName));
+		
+	aData.iMainThreadId = thread.Id();
+	thread.Close();
+
+	if (!aRun)
+	{
+		CDebugProcess *proc = CDebugProcess::NewL(this, aData.iProcessId, aData.iMainThreadId);
+		iDebugProcessList.Append(proc);
+
+		User::LeaveIfError(iKernelDriver.GetProcessAddresses(aData.iMainThreadId, aData.iCodeAddr, aData.iDataAddr));
+	}
+		
+	CleanupStack::PopAndDestroy(threadName);
+	CleanupStack::PopAndDestroy(); // process
+}
+
+//
+// CTrkDispatchLayer::DoKillProcessL
+//
+// Kill an existing process
+//
+void CTrkDispatchLayer::DoKillProcessL()
+{
+	// get the process id
+	TUint32 processId = 0;
+	GetDataFromBufferL(&processId, 4);
+	
+	RProcess process;
+	User::LeaveIfError(process.Open(processId));
+#ifdef EKA2
+	process.Kill(KErrNone);
+#else	
+	process.Kill(KProcessKilled);
+#endif
+	process.Close();
+
+	iFramingLayer->RespondOkL(KNullDesC8);	
+}
+
+//
+// CTrkDispatchLayer::DoAttachProcessL
+//
+// Create a new process on the target device
+//
+void CTrkDispatchLayer::DoAttachProcessL(DSOSItemTypes aAttachType)
+{
+	// remove the options - currently unused
+	iInputBuffer->Des().Delete(0, 1);
+
+	// get the length of the data
+	TUint32 processId = 0;
+	GetDataFromBufferL(&processId, 4);
+
+	RProcess process;
+	User::LeaveIfError(process.Open(processId));
+	CleanupClosePushL(process);
+	
+	// do not allow attaching to a system, protected, or the MetroTrk process because
+	// if the user were to stop the wrong thread, the whole system could stop
+#ifdef EKA2
+	if ((TUint)processId == RProcess().Id())
+#else
+	if (process.System() || process.Protected() || ((TUint)processId == RProcess().Id()))
+#endif
+	{
+		User::Leave(kDSReplyUnsupportedOptionError);
+	}
+
+	TMetroTrkTaskInfo threadInfo(processId);
+	User::LeaveIfError(iKernelDriver.GetThreadInfo(0, threadInfo));
+
+	
+	TUint32 codeAddr;
+	TUint32 dataAddr;
+	User::LeaveIfError(iKernelDriver.GetProcessAddresses(threadInfo.iId, codeAddr, dataAddr));	
+	//this is necessary to get the process died notifications and also any other event for this process
+	CDebugProcess *proc = CDebugProcess::NewL(this, processId, threadInfo.iId);
+	// For processes that we are attaching, we need to set this flag to true.
+	// otherwise library load notifications for this process will be ignored
+	proc->iReadyForLibraryLoadNotification = ETrue;
+	iDebugProcessList.Append(proc);	
+			
+	AddToReplyBufferL(threadInfo.iId, true);
+	if (aAttachType == kDSOSProcAttach3Item)
+	{
+		// now get the UID3 for this process
+		// and add it to the reply
+		TMetroTrkProcUidInfo procUidInfo(processId);
+		User::LeaveIfError(iKernelDriver.GetProcUidInfo(procUidInfo));
+		AddToReplyBufferL(procUidInfo.iUid3);
+	}
+	if (aAttachType == kDSOSProcAttach3Item || aAttachType == kDSOSProcAttach2Item)
+	{				
+		AddToReplyBufferL(codeAddr);
+		AddToReplyBufferL(dataAddr);
+		
+		TBuf8<KMaxFullName> procName;
+		procName.Copy(process.Name());
+		TUint16 nameLength = procName.Length();
+
+		AddToReplyBufferL(nameLength);
+		AddToReplyBufferL(procName);		
+	}
+
+	CleanupStack::PopAndDestroy(); // process
+	RespondOkL();
+}
+
+//
+// CTrkDispatchLayer::DoDetachProcessL
+//
+// To detach the process from the list of processes
+//
+void CTrkDispatchLayer::DoDetachProcessL()
+{
+    TUint32 processId = 0;
+    GetDataFromBufferL(&processId, 4);
+    
+    RProcess process;
+    User::LeaveIfError(process.Open(processId));
+    
+	for (TInt i=0 ; i<iDebugProcessList.Count(); i++)
+	{
+		if(iDebugProcessList[i]->ProcessId()== processId) 
+		{
+			SafeDelete(iDebugProcessList[i]);
+			iDebugProcessList.Remove(i);
+		}
+	}
+    User::LeaveIfError(iKernelDriver.DetachProcess(processId));    
+
+    iFramingLayer->RespondOkL(KNullDesC8);
+}
+
+
+//
+// CTrkDispatchLayer::DoReadProcessListL
+//
+// Return a list of the current processes to the host debugger
+//
+void CTrkDispatchLayer::DoReadProcessListL(TInt32 aIndex)
+{
+	// remove the options - unused
+	iInputBuffer->Des().Delete(0, 1);
+
+	// remove the filter - unused
+	iInputBuffer->Des().Delete(0, 4);
+
+	// an index of zero means we start fresh.  and index other than zero means
+	// we were not able to return all of the processes in the last round due to
+	// message size limitations, so we need to pick up where we left off
+	if (aIndex == 0)
+	{
+		DoReBuildProcessList();
+	}
+	
+	TInt32 totalCount = iProcessList.Count();
+	TInt32 returnedCount = 0;
+	TInt32 bytesRemaining = MAXMESSAGESIZE_V2 - 30; // minus the framing bytes
+	TInt32 restOfMsgSize = sizeof(TUint32) // process id
+						 + sizeof(TUint32) // priority
+						 + sizeof(TUint8); // NULL character
+	
+	for (TInt32 i=aIndex; i<totalCount; i++)
+	{
+		// make sure there is enough room left in the message
+		if (bytesRemaining >= (iProcessList[i].iName.Length() + restOfMsgSize))
+		{
+			returnedCount++;
+			bytesRemaining -= (iProcessList[i].iName.Length() + restOfMsgSize);
+		}
+		else
+			break;
+	}
+
+	// add values for returnedCount and totalCount
+	AddToReplyBufferL((TUint32)returnedCount, true);
+	AddToReplyBufferL((TUint32)totalCount);
+
+	for (TInt32 i=aIndex; i<(aIndex + returnedCount); i++)
+	{
+		// add this process info to the buffer
+		AddToReplyBufferL(iProcessList[i].iId);
+		AddToReplyBufferL(iProcessList[i].iPriority);
+		AddToReplyBufferL(iProcessList[i].iName);
+		
+		// host expects the name to be a null terminated string
+		AddToReplyBufferL((TUint8)0);
+	}
+	
+	RespondOkL();
+}
+
+//
+// CTrkDispatchLayer::DoReadThreadListL
+//
+// Return a list of the current threads for a process to the host debugger
+//
+void CTrkDispatchLayer::DoReadThreadListL(TInt32 aIndex)
+{
+	// remove the options - unused
+	iInputBuffer->Des().Delete(0, 1);
+
+	// get the process id
+	TUint32 processId = 0;
+	GetDataFromBufferL(&processId, 4);
+
+	// an index of zero means we start fresh.  and index other than zero means
+	// we were not able to return all of the threads in the last round due to
+	// message size limitations, so we need to pick up where we left off
+	if (aIndex == 0)
+	{
+		DoReBuildThreadList(processId);
+	}
+	
+	TInt32 totalCount = iThreadList.Count();
+	TInt32 returnedCount = 0;
+	TInt32 bytesRemaining = MAXMESSAGESIZE_V2 - 30; // minus the framing bytes
+	TInt32 restOfMsgSize = sizeof(TUint32) // process id
+						 + sizeof(TUint32) // priority
+						 + sizeof(TUint8)  // state
+						 + sizeof(TUint8); // NULL character
+	
+	
+	for (TInt32 i=aIndex; i<totalCount; i++)
+	{
+		// make sure there is enough room left in the message
+		if (bytesRemaining >= (iThreadList[i].iName.Length() + restOfMsgSize))
+		{
+			returnedCount++;
+			bytesRemaining -= (iThreadList[i].iName.Length() + restOfMsgSize);
+		}
+		else
+			break;
+	}
+
+	// add values for returnedCount and totalCount
+	AddToReplyBufferL((TUint32)returnedCount, true);
+	AddToReplyBufferL((TUint32)totalCount);
+
+	for (TInt32 i=aIndex; i<(aIndex + returnedCount); i++)
+	{
+		// add this thread info to the buffer
+		AddToReplyBufferL(iThreadList[i].iId);
+		AddToReplyBufferL(iThreadList[i].iPriority);
+		AddToReplyBufferL(IsThreadSuspended(iThreadList[i].iId));		
+		AddToReplyBufferL(iThreadList[i].iName);
+
+		// host expects the name to be a null terminated string
+		AddToReplyBufferL((TUint8)0);
+	}
+
+	RespondOkL();
+}
+
+//
+// CTrkDispatchLayer::DoReBuildProcessList
+//
+// Build a list of the current processes
+//
+void CTrkDispatchLayer::DoReBuildProcessList()
+{
+	TInt err = KErrNone;
+
+	// reset the process list
+	iProcessList.Reset();
+	
+	// fill up the process list
+	for (TInt i=0; KErrNone==err; i++)
+	{
+		TMetroTrkTaskInfo processInfo(0);
+		err = iKernelDriver.GetProcessInfo(i, processInfo);
+		
+		//Get a Handle to the process
+		RProcess proc;
+		if(KErrNone == err && KErrNone == proc.Open(TProcessId(processInfo.iId)))
+		{			
+			//Only display currently running processes
+			if(EExitPending == proc.ExitType())
+			{
+				iProcessList.Append(processInfo);
+			}
+			proc.Close();
+		}
+	}
+}
+
+//
+// CTrkDispatchLayer::DoReBuildThreadList
+//
+// Build a list of the current threads for a process
+//
+void CTrkDispatchLayer::DoReBuildThreadList(TUint32 aProcessId)
+{
+	TInt err = KErrNone;
+
+	// reset the thread list
+	iThreadList.Reset();
+	
+	// fill up the thread list
+	for (TInt i=0; KErrNone==err; i++)
+	{
+		TMetroTrkTaskInfo threadInfo(aProcessId);
+		err = iKernelDriver.GetThreadInfo(i, threadInfo);
+		
+		//Get a Handle to the thread
+		RThread thread;
+		if(KErrNone == err && KErrNone == thread.Open(TThreadId(threadInfo.iId)))
+		{			
+			//Only display currently running processes
+			if(EExitPending == thread.ExitType())
+			{
+				iThreadList.Append(threadInfo);
+			}
+			thread.Close();
+		}
+	}
+}
+
+// CTrkDispatchLayer::DoNotifyStoppedL
+//
+// Notify the host debugger that a thread has stopped
+//
+// START_PANIC
+//void CTrkDispatchLayer::DoNotifyStoppedL(TUint32 aProcessId, TUint32 aThreadId, TUint32 aCurrentPC, const TDesC8 &aDescription)
+void CTrkDispatchLayer::DoNotifyStoppedL(TUint32 aProcessId, TUint32 aThreadId, TUint32 aCurrentPC, const TDesC8 &aDescription, TBool aAddException, const TUint16 aExceptionNumber)
+// END_PANIC
+{	
+	// add this thread to the suspended threads list
+	iSuspendedThreadList.Append(aThreadId);
+
+//	TUint8 event = (aAddException==true) ? kDSNotifyStopped2 : kDSNotifyStopped;
+	TUint8 event = kDSNotifyStopped;
+	TUint16 descLength = aDescription.Length();
+	
+	AddToReplyBufferL(event, true);
+	AddToReplyBufferL(aCurrentPC);
+	AddToReplyBufferL(aProcessId);
+	AddToReplyBufferL(aThreadId);
+	AddToReplyBufferL(descLength);
+
+	if (descLength)
+	{
+		AddToReplyBufferL(aDescription);
+
+		// host expects the string to be a null terminated string
+		AddToReplyBufferL((TUint8)0);
+	}
+	// START_PANIC
+	if (aAddException)
+		AddToReplyBufferL(aExceptionNumber);
+	// END_PANIC
+	
+	InformEventL();
+}
+
+//
+// CTrkDispatchLayer::DoNotifyProcessDiedL
+//
+// Notify the host debugger that a process has exited
+//
+void CTrkDispatchLayer::DoNotifyProcessDiedL(TUint32 aProcessId, TInt aExitCode)
+{
+	// remove this process from our list
+	for (TInt i=0; i<iDebugProcessList.Count(); i++)
+	{
+		if (iDebugProcessList[i]->ProcessId() == aProcessId)
+		{
+			SafeDelete(iDebugProcessList[i]);
+			iDebugProcessList.Remove(i);
+		}
+	}
+
+	TUint8 event = kDSOSNotifyDeleted;
+	TUint16 type = kDSOSProcessItem;
+
+	AddToReplyBufferL(event, true);
+	AddToReplyBufferL(type);
+	AddToReplyBufferL((TUint32)aExitCode);
+	AddToReplyBufferL(aProcessId);
+
+	InformEventL();
+}
+
+//
+// CTrkDispatchLayer::DoNotifyLibraryLoadedL
+//
+// Notify the host debugger that a library in now loaded
+//
+void CTrkDispatchLayer::DoNotifyLibraryLoadedL(TDesC8 &aName, TUint32 aProcessId, TUint32 aThreadId, TUint32 aCodeBaseAddress, TUint32 aDataBaseAddress)
+{
+	TUint8 event = kDSOSNotifyCreated;
+	TUint16 type = kDSOSDLLItem;
+
+	TUint16 nameLength = aName.Length();
+	
+	AddToReplyBufferL(event, true);
+	AddToReplyBufferL(type);
+	AddToReplyBufferL(aProcessId);
+	AddToReplyBufferL(aThreadId);
+	AddToReplyBufferL(aCodeBaseAddress);
+	AddToReplyBufferL(aDataBaseAddress);
+	AddToReplyBufferL(nameLength);
+	AddToReplyBufferL(aName);
+
+	InformEventL();
+}
+
+//
+// CTrkDispatchLayer::DoNotifyLibraryUnloadedL
+//
+// Notify the host debugger that a library has been unloaded
+//
+void CTrkDispatchLayer::DoNotifyLibraryUnloadedL(TDesC8 &aName, TUint32 aProcessId, TUint32 aThreadId)
+{
+	TUint8 event = kDSOSNotifyDeleted;
+	TUint16 type = kDSOSDLLItem;
+	
+	TUint16 nameLength = aName.Length();
+	
+	AddToReplyBufferL(event, true);
+	AddToReplyBufferL(type);
+	AddToReplyBufferL(aProcessId);
+	AddToReplyBufferL(aThreadId);
+	AddToReplyBufferL(nameLength);
+	AddToReplyBufferL(aName);
+
+	InformEventL();
+}
+
+//
+// CTrkDispatchLayer::GetDataFromBufferL
+//
+// Notify the host debugger that trace data has been recieved
+//
+void CTrkDispatchLayer::DoNotifyUserTraceL(TDesC8 &aTrace)
+{
+	if (iIsConnected)
+		iFramingLayer->SendRawMsgL(aTrace);
+}
+
+void CTrkDispatchLayer::DoNotifyProcessAddedL(TDesC8 &aName, TUint32 aProcessId, TUint32 aThreadId, TUint32 aUid, TUint32 aCodeBaseAddress, TUint32 aDataBaseAddress)
+{
+	// check to see if the host supported protocol handles this event, 
+	// otherwise just resume the thread. If not, this thread would get suspended indefinitely.
+	if (iHostVersion.iMajor < 3 || (iHostVersion.iMajor == 3  && iHostVersion.iMinor <= 3))
+	{
+		iKernelDriver.ResumeThread(aThreadId);				
+	}
+	else
+	{
+		TUint8 event = kDSOSNotifyCreated;
+		TUint16 type = kDSOSProcessItem;
+
+		TUint16 nameLength = aName.Length();
+		
+		AddToReplyBufferL(event, true);
+		AddToReplyBufferL(type);
+		AddToReplyBufferL(aProcessId);
+		AddToReplyBufferL(aThreadId);
+		AddToReplyBufferL(aUid);
+		AddToReplyBufferL(aCodeBaseAddress);
+		AddToReplyBufferL(aDataBaseAddress);
+		AddToReplyBufferL(nameLength);
+		AddToReplyBufferL(aName);
+
+		InformEventL();
+	}
+}
+
+//
+// CTrkDispatchLayer::DoReadLibraryInfoL()
+//
+void CTrkDispatchLayer::DoReadLibraryInfoL(TDesC8& aFileName)
+{
+	TMetroTrkLibInfo libInfo(aFileName.Length(), &aFileName);
+	
+	TInt err = iKernelDriver.GetLibraryInfo(libInfo);
+	
+	if (err == KErrNone)
+	{
+		AddToReplyBufferL(libInfo.iCodeAddress, true);
+		AddToReplyBufferL(libInfo.iDataAddress);
+		AddToReplyBufferL(libInfo.iAttachProcessId);
+		AddToReplyBufferL(libInfo.iAttachThreadId);
+		
+		RespondOkL();
+	}
+	else
+	{
+		User::Leave(err);
+	}			
+}
+
+//
+// CTrkDispatchLayer::DoReadProcessInfoL()
+//
+void CTrkDispatchLayer::DoReadProcessInfoL(TUint32 aUid, TDesC8& aFileName)
+{
+	TMetroTrkExeInfo exeInfo(aUid, aFileName.Length(), &aFileName);
+	
+	TInt err = iKernelDriver.GetExeInfo(exeInfo);
+	
+	if (err == KErrNone)
+	{
+		AddToReplyBufferL(exeInfo.iProcessID, true);
+		AddToReplyBufferL(exeInfo.iThreadID);
+		AddToReplyBufferL(exeInfo.iCodeAddress);
+		AddToReplyBufferL(exeInfo.iDataAddress);
+		
+		RespondOkL();
+	}
+	else
+	{
+		User::Leave(err);
+	}			
+}
+
+//
+// CTrkDispatchLayer::GetDataFromBufferL
+//
+// Get data from the input buffer
+//
+void CTrkDispatchLayer::GetDataFromBufferL(TAny* aData, TInt aLength)
+{
+	if (aLength > iInputBuffer->Length())
+		User::Leave(kDSReplyPacketSizeError);
+		
+	if (iFramingLayer->IsBigEndian())
+	{
+		Mem::Copy(aData, iInputBuffer->Ptr(), aLength);
+	}
+	else
+	{
+		TUint8 *p = (TUint8 *)aData;
+		for (int i=aLength-1, j=0; i>=0; i--, j++)
+			p[j] = iInputBuffer->Ptr()[i];
+	}
+	
+	// now remove it from the buffer
+	iInputBuffer->Des().Delete(0, aLength);
+}
+
+//
+// CTrkDispatchLayer::AddToReplyBufferL
+//
+// Add data to the buffer which will be sent back to the host as a reply
+//
+void CTrkDispatchLayer::AddToReplyBufferL(TUint8 aData, TBool aReset)
+{
+	if (aReset)
+	{
+		// free the memory associated with the old reply buffer and allocate a new one
+		SafeDelete(iReplyBuffer);
+		iReplyBuffer = HBufC8::New(sizeof(TUint8));
+	}
+	else
+	{
+		// reallocate to make enough room for the new data
+		iReplyBuffer = iReplyBuffer->ReAlloc(iReplyBuffer->Length() + sizeof(TUint8));
+	}
+	
+	// make sure the above worked
+	if (!iReplyBuffer)
+		User::Leave(KErrNoMemory);
+	
+	iReplyBuffer->Des().Append(aData);
+}
+
+//
+// CTrkDispatchLayer::AddToReplyBufferL
+//
+// Add data to the buffer which will be sent back to the host as a reply
+//
+void CTrkDispatchLayer::AddToReplyBufferL(TUint16 aData, TBool aReset)
+{
+	TUint16 temp = aData;
+	
+	if (aReset)
+	{
+		// free the memory associated with the old reply buffer and allocate a new one
+		SafeDelete(iReplyBuffer);
+		iReplyBuffer = HBufC8::New(sizeof(TUint16));
+	}
+	else
+	{
+		// reallocate to make enough room for the new data
+		iReplyBuffer = iReplyBuffer->ReAlloc(iReplyBuffer->Length() + sizeof(TUint16));
+	}
+	
+	// make sure the above worked
+	if (!iReplyBuffer)
+		User::Leave(KErrNoMemory);
+	
+	// the host expects all values except for raw data to be returned in big endian format
+	if (!iFramingLayer->IsBigEndian())
+	{
+		temp = Swap2(aData);
+	}
+
+	iReplyBuffer->Des().Append((TUint8 *)&temp, sizeof(TUint16));
+}
+
+//
+// CTrkDispatchLayer::AddToReplyBufferL
+//
+// Add data to the buffer which will be sent back to the host as a reply
+//
+void CTrkDispatchLayer::AddToReplyBufferL(TUint32 aData, TBool aReset)
+{
+	TUint32 temp = aData;
+	
+	if (aReset)
+	{
+		// free the memory associated with the old reply buffer and allocate a new one
+		SafeDelete(iReplyBuffer);
+		iReplyBuffer = HBufC8::New(sizeof(TUint32));
+	}
+	else
+	{
+		// reallocate to make enough room for the new data
+		iReplyBuffer = iReplyBuffer->ReAlloc(iReplyBuffer->Length() + sizeof(TUint32));
+	}
+	
+	// make sure the above worked
+	if (!iReplyBuffer)
+		User::Leave(KErrNoMemory);
+	
+	// the host expects all values except for raw data to be returned in big endian format
+	if (!iFramingLayer->IsBigEndian())
+	{
+		temp = Swap4(aData);
+	}
+
+	iReplyBuffer->Des().Append((TUint8 *)&temp, sizeof(TUint32));
+}
+
+//
+// CTrkDispatchLayer::AddToReplyBufferL
+//
+// Add data to the buffer which will be sent back to the host as a reply
+//
+void CTrkDispatchLayer::AddToReplyBufferL(const TDesC8 &aData, TBool aReset)
+{
+	if (aReset)
+	{
+		// free the memory associated with the old reply buffer and allocate a new one
+		SafeDelete(iReplyBuffer);
+		iReplyBuffer = HBufC8::New(aData.Length());
+	}
+	else
+	{
+		// reallocate to make enough room for the new data
+		iReplyBuffer = iReplyBuffer->ReAlloc(iReplyBuffer->Length() + aData.Length());
+	}
+	
+	// make sure the above worked
+	if (!iReplyBuffer)
+		User::Leave(KErrNoMemory);
+	
+	iReplyBuffer->Des().Append(aData);
+}
+
+//
+// CTrkDispatchLayer::IsThreadSuspended
+//
+// Determines whether or not a thread is suspended
+//
+TUint8 CTrkDispatchLayer::IsThreadSuspended(TUint32 aThreadId)
+{
+	if (iSuspendedThreadList.Find(aThreadId) >= 0)
+		return 1;
+	
+	return 0;
+}
+
+//
+// CTrkDispatchLayer::IsRestrictedFolder
+//
+// Check to see if the path is any of the data caged paths like \sys\ or \private\ or \resource\
+//
+TBool CTrkDispatchLayer::IsRestrictedFolder(const TDesC& aPath)
+{
+	_LIT(KSYS, "\\sys\\");
+	_LIT(KRESOURCE, "\\resource\\");
+	_LIT(KPRIVATE, "\\private\\");
+	
+	if ( (aPath.FindC(KSYS)>=0) || (aPath.FindC(KRESOURCE)>=0) || (aPath.FindC(KPRIVATE)>=0) )
+		return ETrue;
+	
+	return EFalse;
+}
+
+
+TInt CTrkDispatchLayer::CloseCrashLogger()
+{
+    TInt err = KErrNone;
+    
+    //The old mobile crash file name is "d_exc_mc.exe" and the new one is "mc_useragent.exe"    
+    //This is the string that needs to be passed to the RProcess::Open call to get a handle.
+    //The complete process name actually includes the UID info as well.
+    //Instead of hard coding the process name, its better to just 
+    //search for the process and find it that way.      
+    //_LIT16(KCrashLoggerName, "mc_useragent.exe[1020e519]0001");
+    _LIT16(KOldCrashLoggerName, "d_exc_mc*");
+    _LIT16(KCrashLoggerName, "mc_useragent*");
+    
+    err = TerminateProcess(KOldCrashLoggerName);
+    err = TerminateProcess(KCrashLoggerName);
+
+    return err;
+}
+
+TInt CTrkDispatchLayer::TerminateProcess(const TDesC& aProcessName)
+{
+    TFindProcess find(aProcessName);
+    TFullName name; 
+        
+    TInt err = find.Next(name);
+    if (KErrNone == err)
+    {   
+        RProcess process;
+        err = process.Open(find);
+    
+        if (KErrNone == err)
+        {
+            process.Kill(KErrNone);
+        }
+    }
+    return err;
+}