sl@0: // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of the License "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: // Provides the debug agent server implementation.
sl@0: // 
sl@0: //
sl@0: 
sl@0: #include <e32base.h>
sl@0: #include <e32base_private.h>
sl@0: #include <e32cons.h>
sl@0: #include <trkkerneldriver.h>
sl@0: #include "d_rmdebugserver.h"
sl@0: #include "d_rmdebugclient.h"
sl@0: #include "t_rmdebug.h"
sl@0: 
sl@0: 
sl@0: CDebugServServer::CDebugServServer(CActive::TPriority aActiveObjectPriority)
sl@0:    : CServer2(aActiveObjectPriority)
sl@0: //
sl@0: // Server constructor
sl@0: //
sl@0: 	{
sl@0: 	}
sl@0: 
sl@0: CSession2* CDebugServServer::NewSessionL(const TVersion& /*aVersion*/, const RMessage2& /*aMessage*/) const
sl@0: //
sl@0: // Session constructor
sl@0: //
sl@0: 	{
sl@0: 	// make sure the kernel side device driver is not already loaded
sl@0:    TInt err;
sl@0: 	err = User::LoadLogicalDevice(KDebugDriverFileName);
sl@0: 	if ((KErrNone == err) || (KErrAlreadyExists == err))
sl@0:        {
sl@0:        return new(ELeave) CDebugServSession();
sl@0:        }
sl@0:    else
sl@0:        {
sl@0:        return (NULL);
sl@0:        }
sl@0: 	}   
sl@0: 
sl@0: CDebugServSession::CDebugServSession()
sl@0: // Session implementation
sl@0: 	{
sl@0:    TInt err;
sl@0: 	TMetroTrkDriverInfo info;
sl@0:    info.iUserLibraryEnd = 0;
sl@0:    err = iKernelDriver.Open(info);
sl@0:    if (KErrNone != err)
sl@0: 		{
sl@0:  		User::Leave(err);
sl@0: 		}          
sl@0: 	}
sl@0: 
sl@0: CDebugServSession::~CDebugServSession()
sl@0: //
sl@0: // Session destructor
sl@0: //
sl@0: 	{
sl@0: 	// stop the kernel side driver
sl@0: 	iKernelDriver.Close();
sl@0: 
sl@0: 	User::FreeLogicalDevice(KDebugDriverName);
sl@0: 	}
sl@0: 
sl@0: 
sl@0: void CDebugServSession::ServiceL(const RMessage2& aMessage)
sl@0: //
sl@0: // Session service handler
sl@0: //
sl@0: 	{
sl@0: 	TInt res = KErrNone;
sl@0: 
sl@0: 	switch(aMessage.Function())
sl@0: 		{
sl@0: 		case EDebugServResumeThread:
sl@0: 			res = ResumeThread(aMessage);
sl@0: 			break;
sl@0: 
sl@0: 		case EDebugServSuspendThread:
sl@0: 			res = SuspendThread(aMessage);
sl@0: 			break;          
sl@0: 
sl@0: //		case EDebugServReadProcessInfo:
sl@0: //			res = ReadProcessInfo(aMessage);
sl@0: //			break;        
sl@0: //
sl@0: //		case EDebugServReadThreadInfo:
sl@0: //			res = ReadThreadInfo(aMessage);
sl@0: //			break;
sl@0: 
sl@0: 		case EDebugServReadMemory:
sl@0: 			res = ReadMemory(aMessage);
sl@0: 			break;        
sl@0: 
sl@0: 		case EDebugServWriteMemory:
sl@0: 			res = WriteMemory(aMessage);
sl@0: 			break;        
sl@0: 
sl@0: 		default:
sl@0: 			User::Leave(KErrNotSupported);
sl@0: 			break;
sl@0: 		}
sl@0: 
sl@0: 	aMessage.Complete(res);
sl@0: 	}
sl@0: 
sl@0: 
sl@0: 
sl@0: TInt CDebugServSession::SuspendThread(const RMessage2& aMessage)
sl@0: //
sl@0: // Session suspend thread
sl@0: //
sl@0: 	{
sl@0: 	TInt err;
sl@0: 
sl@0: 	err = iKernelDriver.SuspendThread(aMessage.Int0());
sl@0: 
sl@0: 	return err;
sl@0: 	}
sl@0: 
sl@0: TInt CDebugServSession::ResumeThread(const RMessage2& aMessage)
sl@0: //
sl@0: // Server resume thread
sl@0: //
sl@0: 	{
sl@0: 	TInt err;
sl@0: 
sl@0: 	err = iKernelDriver.ResumeThread(aMessage.Int0());
sl@0: 
sl@0: 	return err;
sl@0: 	}
sl@0: 
sl@0: //TInt CDebugServSession::ReadProcessInfo(const RMessage2& aMessage)
sl@0: ////
sl@0: //// Server read process information
sl@0: ////
sl@0: //	{
sl@0: //	TInt err;
sl@0: //	TProcessInfo procinfo;
sl@0: //	TMetroTrkTaskInfo processInfo(0);
sl@0: //
sl@0: //	err = iKernelDriver.GetProcessInfo(aMessage.Int0(), processInfo);
sl@0: //
sl@0: //	if (KErrNone == err)
sl@0: //		{
sl@0: //		procinfo.iProcessID = processInfo.iId;
sl@0: //		procinfo.iPriority = processInfo.iPriority;
sl@0: //		procinfo.iName.Copy(processInfo.iName);
sl@0: //
sl@0: //		TPckgBuf<TProcessInfo> p(procinfo);
sl@0: //		aMessage.WriteL(1,p);        
sl@0: //		}
sl@0: //
sl@0: //	return err;
sl@0: //	}
sl@0: //
sl@0: //TInt CDebugServSession::ReadThreadInfo(const RMessage2& aMessage)
sl@0: ////
sl@0: //// Server read thread information
sl@0: ////
sl@0: //	{
sl@0: //	TInt err;
sl@0: //	TThreadInfo thrdinfo;
sl@0: //	TMetroTrkTaskInfo threadInfo(aMessage.Int1()); // Sets OtherID to the second input parameter in aMessage
sl@0: //
sl@0: //	// aMessage.Int0 is the index into the thread list for the process
sl@0: //	err = iKernelDriver.GetThreadInfo(aMessage.Int0(), threadInfo);	   
sl@0: //
sl@0: //	if (KErrNone == err)
sl@0: //		{
sl@0: //		thrdinfo.iThreadID = threadInfo.iId;
sl@0: //		thrdinfo.iPriority = threadInfo.iPriority;
sl@0: //		thrdinfo.iName.Copy(threadInfo.iName);
sl@0: //		thrdinfo.iOwningProcessID = threadInfo.iOtherId;
sl@0: //
sl@0: //		TPckgBuf<TThreadInfo> p(thrdinfo);
sl@0: //
sl@0: //		// Write out the results to the third argument passed in (pointer to the threadinfo structure)
sl@0: //		aMessage.WriteL(2,p);           
sl@0: //		}
sl@0: //
sl@0: //	return err;
sl@0: //	}
sl@0: 
sl@0: TInt CDebugServSession::ReadMemory(const RMessage2& aMessage)
sl@0: //
sl@0: // Server read process memory
sl@0: //
sl@0: 	{   
sl@0: 	TInt err;
sl@0: 	TUint32 threadId = aMessage.Int0();
sl@0: 	TPckgBuf<TMemoryInfo> pckg = *(TPckgBuf<TMemoryInfo> *)(aMessage.Ptr1());
sl@0: 	TMemoryInfo* InputMemoryInfo = &pckg();
sl@0: 
sl@0: 	TPtr8 *ptrtst = InputMemoryInfo->iDataPtr;
sl@0: 
sl@0: 	err = iKernelDriver.ReadMemory(threadId, InputMemoryInfo->iAddress, InputMemoryInfo->iSize, *ptrtst);
sl@0: 
sl@0: 	return err;
sl@0: 	}
sl@0: 
sl@0: TInt CDebugServSession::WriteMemory(const RMessage2& aMessage)
sl@0: //
sl@0: // Server write process memory
sl@0: //
sl@0: 	{
sl@0: 	TInt err;
sl@0: 	TUint32 threadId = aMessage.Int0();
sl@0: 	TPckgBuf<TMemoryInfo> pckg = *(TPckgBuf<TMemoryInfo> *)(aMessage.Ptr1());
sl@0: 	TMemoryInfo* InputMemoryInfo = &pckg();
sl@0: 
sl@0: 	TPtr8 *ptrtst = InputMemoryInfo->iDataPtr;
sl@0: 
sl@0: 	err = iKernelDriver.WriteMemory(threadId, InputMemoryInfo->iAddress, InputMemoryInfo->iSize, *ptrtst);
sl@0: 
sl@0: 	return err;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: GLDEF_C TInt CDebugServServer::ThreadFunction(TAny*)
sl@0: //
sl@0: // Server thread function, continues until active scheduler stops
sl@0: //
sl@0: 	{
sl@0: 	CTrapCleanup* cleanup=CTrapCleanup::New();
sl@0: 	if (cleanup == NULL)
sl@0: 		{
sl@0: 		User::Leave(KErrNoMemory);
sl@0: 		}
sl@0: 
sl@0: 	CActiveScheduler *pA=new CActiveScheduler;
sl@0: 	CDebugServServer *pS=new CDebugServServer(EPriorityStandard);
sl@0: 
sl@0: 	CActiveScheduler::Install(pA);
sl@0: 
sl@0: 	TInt err = pS->Start(KDebugServerName);
sl@0: 	if (err != KErrNone)
sl@0: 		{
sl@0: 		User::Leave(KErrNone);
sl@0: 		}
sl@0: 
sl@0: 	RThread::Rendezvous(KErrNone);
sl@0: 
sl@0: 	CActiveScheduler::Start();
sl@0: 
sl@0: 	delete pS;
sl@0: 	delete pA;
sl@0: 	delete cleanup;
sl@0: 
sl@0: 	return (KErrNone);
sl@0: 	}
sl@0: 
sl@0: 
sl@0: 
sl@0: EXPORT_C TInt StartThread(RThread& aServerThread)
sl@0: //
sl@0: // Start the server thread
sl@0: //
sl@0: 	{
sl@0: 	TInt res=KErrNone;
sl@0: 
sl@0: 	TFindServer finddebugserver(KDebugServerName);
sl@0: 	TFullName name;
sl@0: 
sl@0: 	if (finddebugserver.Next(name) != KErrNone)
sl@0: 		{
sl@0: 		res = aServerThread.Create( KDebugServerName,
sl@0: 									CDebugServServer::ThreadFunction,
sl@0: 									KDefaultStackSize,
sl@0: 									KDefaultHeapSize,
sl@0: 									KDefaultHeapSize,
sl@0: 									NULL
sl@0: 									);
sl@0: 
sl@0: 		if (res == KErrNone)
sl@0: 			{
sl@0: 			TRequestStatus rendezvousStatus;
sl@0: 
sl@0: 			aServerThread.SetPriority(EPriorityNormal);
sl@0: 			aServerThread.Rendezvous(rendezvousStatus);
sl@0: 			aServerThread.Resume();
sl@0: 			User::WaitForRequest(rendezvousStatus);
sl@0: 			}                                 
sl@0: 		else
sl@0: 			{
sl@0: 			aServerThread.Close();
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	return res;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: 
sl@0: RDebugServSession::RDebugServSession()
sl@0: //
sl@0: // Server session constructor
sl@0: //
sl@0: 	{
sl@0: 	}
sl@0: 
sl@0: TInt RDebugServSession::Open()
sl@0: //
sl@0: // Session open
sl@0: //
sl@0: 	{
sl@0: 	TInt r = StartThread(iServerThread);
sl@0: 	if (r == KErrNone)
sl@0: 		{
sl@0: 		r=CreateSession(KDebugServerName, Version(), KDefaultMessageSlots);
sl@0: 		}
sl@0: 
sl@0: 	return r;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: TVersion RDebugServSession::Version(void) const
sl@0: //
sl@0: // Session version
sl@0: //
sl@0: 	{
sl@0: 	return (TVersion(KDebugServMajorVersionNumber, KDebugServMinorVersionNumber, KDebugServBuildVersionNumber));
sl@0: 	}
sl@0: 
sl@0: TInt RDebugServSession::SuspendThread(const TInt aThreadID)
sl@0: //
sl@0: // Session suspend thread request
sl@0: //
sl@0: 	{
sl@0: 	TIpcArgs args(aThreadID);
sl@0: 	TInt res;
sl@0: 	res = SendReceive(EDebugServSuspendThread, args);
sl@0: 
sl@0: 	return res;
sl@0: 	}
sl@0: 
sl@0: TInt RDebugServSession::ResumeThread(const TInt aThreadID)
sl@0: //
sl@0: // Session resume thread request
sl@0: //
sl@0: 	{
sl@0: 	TIpcArgs args(aThreadID);
sl@0: 	TInt res;
sl@0: 	res = SendReceive(EDebugServResumeThread, args);
sl@0: 
sl@0: 	return res;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: //TInt RDebugServSession::ReadProcessInfo(const TInt aIndex, TProcessInfo* aInfo)
sl@0: ////
sl@0: //// Session read process information request
sl@0: ////
sl@0: //	{
sl@0: //	TPckgBuf<TProcessInfo> pckg;
sl@0: //	pckg = *aInfo;
sl@0: //
sl@0: //	TIpcArgs args(aIndex, &pckg);
sl@0: //
sl@0: //	TInt res;
sl@0: //
sl@0: //	res = SendReceive(EDebugServReadProcessInfo, args);
sl@0: //
sl@0: //	*aInfo = pckg();
sl@0: //
sl@0: //	return res;
sl@0: //
sl@0: //	}
sl@0: //
sl@0: //TInt RDebugServSession::ReadThreadInfo(const TInt aIndex, const TInt aProc, TThreadInfo* aInfo)
sl@0: ////
sl@0: //// Session read thread information request
sl@0: ////
sl@0: //	{
sl@0: //	TPckgBuf<TThreadInfo> pckg;
sl@0: //	pckg = *aInfo;
sl@0: //
sl@0: //	TIpcArgs args(aIndex, aProc, &pckg);
sl@0: //
sl@0: //	TInt res;
sl@0: //
sl@0: //	res = SendReceive(EDebugServReadThreadInfo, args);
sl@0: //
sl@0: //	*aInfo = pckg();
sl@0: //
sl@0: //	return res;
sl@0: //
sl@0: //	}
sl@0: 
sl@0: 
sl@0: TInt RDebugServSession::ReadMemory(const TUint32 aThreadID, TMemoryInfo* aInfo)
sl@0: //
sl@0: // Session read thread memory request
sl@0: //
sl@0: 	{
sl@0: 	TPckgBuf<TMemoryInfo> pckg;
sl@0: 	pckg = *aInfo;
sl@0: 
sl@0: 	TIpcArgs args(aThreadID, &pckg);
sl@0: 
sl@0: 	TInt res;
sl@0: 
sl@0: 	res = SendReceive(EDebugServReadMemory, args);
sl@0: 
sl@0: 	*aInfo = pckg();
sl@0: 
sl@0: 	return res;
sl@0: 
sl@0: 	}
sl@0: 
sl@0: 
sl@0: TInt RDebugServSession::WriteMemory(const TUint32 aThreadID, TMemoryInfo* aInfo)
sl@0: //
sl@0: // Session write thread memory request
sl@0: //
sl@0: 	{
sl@0: 	TPckgBuf<TMemoryInfo> pckg;
sl@0: 	pckg = *aInfo;
sl@0: 
sl@0: 	TIpcArgs args(aThreadID, &pckg);
sl@0: 
sl@0: 	TInt res;
sl@0: 
sl@0: 	res = SendReceive(EDebugServWriteMemory, args);
sl@0: 
sl@0: 	return res;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: 
sl@0: TInt RDebugServSession::Close()
sl@0: //
sl@0: // Session close the session and thread
sl@0: //
sl@0: 	{
sl@0: 	RSessionBase::Close();
sl@0: 	iServerThread.Close();
sl@0: 
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: