kernel/eka/drivers/resmanus/d_resmanus.cpp
changeset 0 a41df078684a
child 109 b3a1d9898418
child 256 c1f20ce4abcf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/resmanus/d_resmanus.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,2485 @@
+// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\drivers\resmanus\d_resmanus.cpp
+// 
+//
+
+// LDD for Resource Manager user side API
+#include "resmanus.h"
+#include <kernel/kern_priv.h>
+#include <kernel/kernel.h>
+#include <e32hal.h>
+#include <e32uid.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <e32def_private.h>
+#include <drivers/resource_extend.h>
+
+#ifdef RESOURCE_MANAGER_SIMULATED_PSL
+#include "rescontrol_psl.h"
+#endif
+
+#ifdef PRM_US_INSTRUMENTATION_MACRO
+#include <drivers/resmanus_trace.h>
+#endif
+
+#ifdef PRM_ENABLE_EXTENDED_VERSION2
+_LIT(KResManUsThreadName,"ResManUsExtendedCoreLddThread");
+#elif defined (PRM_ENABLE_EXTENDED_VERSION)
+_LIT(KResManUsThreadName,"ResManUsExtendedLddThread");
+#else
+_LIT(KResManUsThreadName,"ResManUsLddThread");
+#endif
+
+#define RESMANUS_FAULT()	Kern::Fault("RESMANUS",__LINE__)
+
+const TInt KResManUsThreadPriority = 24;
+const TInt KResManUsRegistrationPriority = 5; // Arbitrary! Can be 0-7, 7 is highest
+const TInt KResManCallBackPriority = 5; // Arbitrary! Can be 0-7, 7 is highest
+
+//Macro to return appropriate request type.
+#define GET_USER_REQUEST(request, buffer, type)						\
+	{																\
+	if(type == EGetState)											\
+		request = ((TTrackGetStateBuf*)buffer)->iRequest;			\
+	else if(type == ESetState)										\
+		request = ((TTrackSetStateBuf*)buffer)->iRequest;			\
+	else															\
+		request = ((TTrackNotifyBuf*)buffer)->iRequest;				\
+	}
+
+/***************************************************************************************
+	class TTrackGetStateBuf
+ ***************************************************************************************/
+TTrackGetStateBuf::TTrackGetStateBuf(TPowerResourceCbFn aFn, TAny* aPtr,
+						       TDfcQue* aQue, TInt aPriority)
+							   :	iCtrlBlock(aFn, aPtr, aQue, aPriority)
+	{
+	iRequest = NULL;
+	}
+
+/***************************************************************************************
+	class TTrackSetStateBuf
+ ***************************************************************************************/
+TTrackSetStateBuf::TTrackSetStateBuf(TPowerResourceCbFn aFn, TAny* aPtr,
+						       TDfcQue* aQue, TInt aPriority)
+							   :	iCtrlBlock(aFn, aPtr, aQue, aPriority)
+	{
+	iRequest = NULL;
+	}
+
+/***************************************************************************************
+	class TTrackNotifyBuf
+ ***************************************************************************************/
+TTrackNotifyBuf::TTrackNotifyBuf(TPowerResourceCbFn aFn, TAny* aPtr,
+								 TDfcQue* aQue, TInt aPriority)
+							   :	iNotifyBlock(aFn, aPtr, aQue, aPriority)
+	{
+	iRequest = NULL;
+	}
+
+TTrackNotifyBuf::~TTrackNotifyBuf()
+	{
+	if(iRequest)
+		Kern::DestroyClientRequest(iRequest);
+	}
+
+TTrackSetStateBuf::~TTrackSetStateBuf()
+	{
+	if(iRequest)
+		Kern::DestroyClientRequest(iRequest);
+	}
+
+TTrackGetStateBuf::~TTrackGetStateBuf()
+	{
+	if(iRequest)
+		Kern::DestroyClientRequest(iRequest);
+	}
+	
+/***************************************************************************************
+	class DDeviceResManUs
+ ***************************************************************************************/
+DDeviceResManUs::DDeviceResManUs()
+// Constructor
+    {
+    __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceResManUs::DDeviceResManUs()"));
+    iParseMask=KDeviceAllowAll&~KDeviceAllowUnit; // Allow info and pdd, but not units
+    iUnitsMask=0;
+    iVersion=TVersion(KResManUsMajorVersionNumber,
+		      KResManUsMinorVersionNumber,
+		      KResManUsBuildVersionNumber);
+    }
+
+DDeviceResManUs::~DDeviceResManUs()
+// Destructor
+    {
+    __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceResManUs::~DDeviceResManUs()"));
+#ifdef RESOURCE_MANAGER_SIMULATED_PSL
+	iSharedDfcQue->Destroy();
+#else
+	delete iSharedDfcQue;
+#endif
+	}
+
+TInt DDeviceResManUs::Install()
+// Install the device driver.
+    {
+    __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceResManUs::Install()"));
+	// Create the message queue and initialise the DFC queue pointer
+#ifndef RESOURCE_MANAGER_SIMULATED_PSL
+	TInt r=Kern::DfcQInit(iSharedDfcQue,KResManUsThreadPriority,&KResManUsThreadName);
+#else
+	TInt r = Kern::DynamicDfcQCreate(iSharedDfcQue,KResManUsThreadPriority,KResManUsThreadName);
+#endif
+    __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DfcQCreate r  = %d", r));
+	if(r!=KErrNone)
+		return r;
+
+#ifdef CPU_AFFINITY_ANY
+        NKern::ThreadSetCpuAffinity((NThread*)(iSharedDfcQue->iThread), KCpuAffinityAny);
+#endif
+	r = SetName(&KLddRootName);
+    __KTRACE_OPT(KRESMANAGER, Kern::Printf("> SetName, r  = %d", r));
+	return r;
+    }
+
+
+void DDeviceResManUs::GetCaps(TDes8& aDes) const
+// Return the ResManUs capabilities.
+    {
+    __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceResManUs::GetCaps(TDes8& aDes) const"));
+    TPckgBuf<TCapsDevResManUs> b;
+    b().version=TVersion(KResManUsMajorVersionNumber,
+			 KResManUsMinorVersionNumber,
+			 KResManUsBuildVersionNumber);
+    Kern::InfoCopy(aDes,b);
+    }
+
+
+TInt DDeviceResManUs::Create(DLogicalChannelBase*& aChannel)
+// Create a channel on the device.
+    {
+    __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceResManUs::Create(DLogicalChannelBase*& aChannel)"));
+	if(iOpenChannels>=KMaxNumChannels)
+		return KErrOverflow;
+    aChannel=new DChannelResManUs;
+    return aChannel?KErrNone:KErrNoMemory;
+    }
+
+
+/***************************************************************************************
+	class DChannelResManUs
+ ***************************************************************************************/
+DChannelResManUs::DChannelResManUs() 
+// Constructor
+    {
+    __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::DChannelResManUs()"));
+    iClient=&Kern::CurrentThread();
+	// Increase the DThread's ref count so that it does not close without us
+	iClient->Open();
+    }
+
+
+DChannelResManUs::~DChannelResManUs()
+// Destructor
+    {
+    __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::~DChannelResManUs()"));
+
+	// Cancel any outstanding requests
+	//
+	// For each tracker (Get, Set and notify)
+	// 
+	if(iGetStateTracker != NULL)
+		{
+		CancelTrackerRequests(iGetStateTracker,EFalse,0,NULL); // EFalse,0, to ignore resource IDs
+		RemoveTrackingControl(iGetStateTracker);
+		}
+	if(iSetStateTracker != NULL)
+		{
+		CancelTrackerRequests(iSetStateTracker,EFalse,0,NULL); // EFalse,0, to ignore resource IDs
+		RemoveTrackingControl(iSetStateTracker);
+		}
+	if(iListenableTracker != NULL)
+		{
+		CancelTrackerRequests(iListenableTracker,EFalse,0,NULL); // EFalse,0, to ignore resource IDs
+		RemoveTrackingControl(iListenableTracker);
+		}
+
+	delete iUserNameUsed;
+	delete iResourceDependencyIds;
+	delete iClientNamesResCtrl;
+	delete iResourceInfoResCtrl;
+
+	// decrement the DThread's reference count
+	Kern::SafeClose((DObject*&)iClient, NULL);
+    }
+
+
+static void AsyncCallBackFn(TUint aClient, TUint aResourceId, TInt aLevel, TInt aLevelOwnerId, TInt aResult, TAny* aTrackingBuffer)
+	{
+// Callback function for asynchronous requests
+    __KTRACE_OPT(KRESMANAGER, Kern::Printf("> AsyncCallBackFn aClient=0x%x aResourceId=0x%x, aLevel=0x%x, aResult=0x%x, aTrackingBuffer=0x%x\n",aClient, aResourceId, aLevel, aResult, aTrackingBuffer));
+	TTrackingBuffer* buffer = ((TTrackingBuffer*)aTrackingBuffer);
+	TTrackingControl* tracker = buffer->GetTrackingControl();
+	__ASSERT_ALWAYS((tracker!=NULL),RESMANUS_FAULT());
+	DChannelResManUs* channel = tracker->iOwningChannel;
+
+#ifdef PRM_US_INSTRUMENTATION_MACRO
+	if(tracker->iType==EGetState)
+		{
+		PRM_US_GET_RESOURCE_STATE_END_TRACE;
+		}
+	else if(tracker->iType==ESetState)
+		{
+		PRM_US_SET_RESOURCE_STATE_END_TRACE;
+		}
+#endif
+	if(tracker->iType == EGetState)
+		{
+		TTrackGetStateBuf* stateBuf = (TTrackGetStateBuf*)aTrackingBuffer;
+		if(aResult==KErrNone)
+			{
+			// Write the state value to the user-supplied variable
+			stateBuf->iRequest->Data1() = aLevel;
+			stateBuf->iRequest->Data2() = aLevelOwnerId;
+			}
+		Kern::QueueRequestComplete(channel->iClient, ((TTrackGetStateBuf*)buffer)->iRequest, aResult);
+		}
+	else if(tracker->iType == ESetState)
+		{
+		Kern::QueueRequestComplete(channel->iClient, ((TTrackSetStateBuf*)buffer)->iRequest, aResult);
+		}
+	// Once notified of a change in a resource state, must cancel the notification
+	// request in the Resource Controller to give the client the appearance of a 
+	// 'one'shot' type of operation.
+	else if(tracker->iType==ENotify)
+		{
+#ifdef PRM_ENABLE_EXTENDED_VERSION
+		if(((TInt)aClient==KDynamicResourceDeRegistering)&&(aResourceId&KIdMaskDynamic))  
+			{
+			// Resource has de-registered from Resource Controller, so can't expect any more notifications
+			// of this type. Cancellation of notifications (i.e. invoke Resource Controller) and transfer of
+			// buffers to free queue (for both conditional and unconditional notifications) is already done.
+			// To distinguish removal of a dynamic resource, hijack aResult (the value used when completing
+			// the user-side TRequestStatus object) and set it to KErrDisconnected.
+			aResult = KErrDisconnected;
+			}
+
+#endif
+		TInt r = (channel->iPddPtr)->CancelNotification(channel->ClientHandle(),aResourceId,
+										((TTrackNotifyBuf*)buffer)->iNotifyBlock);
+		__ASSERT_ALWAYS((r == KErrCancel),RESMANUS_FAULT());
+		Kern::QueueRequestComplete(channel->iClient, ((TTrackNotifyBuf*)buffer)->iRequest, aResult);
+		}
+
+	// Return the tracking buffer to the free queue
+	channel->FreeTrackingBuffer(buffer);
+	}
+
+TInt DChannelResManUs::GetValidName(const TDesC8* aInfo)
+	{
+// Extract a usable name from that supplied by the client
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DChannelResManUs::GetValidName"));
+	TInt err=KErrNone;
+	if(aInfo)
+		{
+		DThread* thread = &Kern::CurrentThread();
+		TInt nameLen = Kern::ThreadGetDesLength(thread, aInfo);
+		if(nameLen<0)
+			return nameLen; // return error code
+		iNameProvidedLength = nameLen;
+		if(nameLen > MAX_CLIENT_NAME_LENGTH)
+			err=KErrBadName;
+		else
+			{
+			nameLen = (nameLen<=MAX_NAME_LENGTH_IN_RESMAN) ? nameLen : MAX_NAME_LENGTH_IN_RESMAN;
+			if((iUserNameUsed = HBuf8::New(nameLen))==NULL)
+				return KErrNoMemory;
+			err = Kern::ThreadDesRead(thread,aInfo,*iUserNameUsed,0);
+			if(err!=KErrNone)
+				return err;
+			}
+		}
+	else
+		err=KErrBadName;
+	return err;
+	}
+
+TInt DChannelResManUs::RequestUserHandle(DThread* aThread, TOwnerType aType)
+// Called when a user thread requests a handle to this channel
+    {
+    // Make sure that only our client can get a handle
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DChannelResManUs::RequestUserHandle"));
+    if (aType!=EOwnerThread || aThread!=iClient)
+        return KErrAccessDenied;
+    return KErrNone;
+    }
+
+void DChannelResManUs::RegistrationDfcFunc(TAny* aChannel)
+	{
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DChannelResManUs::RegistrationDfcFunc"));
+	// DFC function invoked for registration with Resource Controller
+	DChannelResManUs* channel = (DChannelResManUs*)aChannel;
+	// RegisterProxyClient(TUint& aProxyId, const TDesC& aName);
+	TUint uintVal=0;
+	TInt r = KErrNone;
+	__ASSERT_ALWAYS((r==KErrNone),RESMANUS_FAULT());
+
+	r=(channel->iPddPtr)->RegisterProxyClient(uintVal,*((TDesC8*)(channel->iUserNameUsed)));
+	if(r!=KErrNone)
+		{
+		// Registration failed
+		// Ensure that the client-side flag is cleared in uintVal
+		// so the failure can be detected in DoCreate
+		uintVal &= ~USER_SIDE_CLIENT_BIT_MASK; // Copied from rescontrol_export
+		}
+	channel->SetClientHandle((TInt)uintVal);
+	NKern::FSSignal(channel->iFastSem);
+	}
+
+
+TInt DChannelResManUs::RegisterWithResCtrlr()
+	{
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DChannelResManUs::RegisterWithResCtrlr"));
+	TInt r = KErrNone;
+	// Initialise the channel's fast semaphore
+	iFastSem = new NFastSemaphore();
+	if(iFastSem == NULL)
+		r = KErrNoMemory;
+	else
+		{
+		iFastSem->iOwningThread = (NThreadBase*)NKern::CurrentThread();
+
+		// Attempt to perform registration with the Resource Controller on behalf of the client.
+		SetDfcQ(((DDeviceResManUs*)(iDevice))->iSharedDfcQue);
+		TDfc tempDfc(RegistrationDfcFunc, this, iDfcQ, KResManUsRegistrationPriority);
+
+		// Block this thread until the DFC has executed
+		tempDfc.Enque();
+		NKern::FSWait(iFastSem);
+		// Have finished with iFastSem
+		delete iFastSem;
+
+		// Registration complete - check success
+		if(!(USER_SIDE_CLIENT_BIT_MASK & ClientHandle()))
+			{
+			// Registration failed
+			r = KErrCouldNotConnect;	
+			}
+		// Start receiving messages ...
+		iMsgQ.Receive();
+		}
+	return r;
+	}
+
+TInt DChannelResManUs::DoCreate(TInt /*aUnit*/,
+                                const TDesC8* aInfo, 
+                                const TVersion &aVer)
+// Create the channel from the passed info.
+    {
+    __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer)"));
+
+	TInt r = KErrNone;
+	iPddPtr = ((DUserSideProxyInterface*)iPdd)->iController;
+	// Check client has appropriate capabilities
+	if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by DDevicePowerRsrc::Create")))
+		return KErrPermissionDenied;
+
+	// Check software version
+	if (!Kern::QueryVersionSupported(TVersion(KResManUsMajorVersionNumber,
+			 KResManUsMinorVersionNumber,
+			 KResManUsBuildVersionNumber),
+				     aVer))
+		return KErrNotSupported;
+
+	// Implementation note: if this method fails, the destructor will be invoked
+	// as part of which all successfully-allocated memory will be freed. Therefore,
+	// no memory will be explicitly freed in the event of failure in the code which follows.
+	
+	// Allocate the arrays used for acquiring client, resource and dependency information
+	if((iClientNamesResCtrl = HBuf8::New(KNumClientNamesResCtrl * sizeof(TPowerClientInfoV01)))==NULL)
+		return KErrNoMemory;
+	if((iResourceInfoResCtrl = HBuf8::New(KNumResourceInfoResCtrl * sizeof(TPowerResourceInfoV01)))==NULL)
+		return KErrNoMemory;
+	if((iResourceDependencyIds = HBuf8::New(KNumResourceDependencies * sizeof(SResourceDependencyInfo)))==NULL)
+		return KErrNoMemory;
+	// Obtain the channel name to use
+	if((r=GetValidName(aInfo))!=KErrNone)
+		return r;
+#ifdef PRM_ENABLE_EXTENDED_VERSION
+	iResDepsValid = 0;
+#endif
+
+#ifdef PRM_US_INSTRUMENTATION_MACRO
+	PRM_US_OPEN_CHANNEL_START_TRACE;	 
+#endif
+
+	// Set up the request tracking support
+	iGetStateTracker = new TTrackingControl();
+	iSetStateTracker = new TTrackingControl();;
+	iListenableTracker = new TTrackingControl();
+	if((iGetStateTracker==NULL) || (iSetStateTracker==NULL) || (iListenableTracker==NULL))
+		return KErrNoMemory;
+
+	// Register with the Resource Controller
+	r = RegisterWithResCtrlr();
+
+#ifdef PRM_US_INSTRUMENTATION_MACRO
+	PRM_US_OPEN_CHANNEL_END_TRACE;
+#endif
+
+    return r;
+    }
+
+//Override sendMsg to allow data copy in the context of client thread for WDP.
+TInt DChannelResManUs::SendMsg(TMessageBase* aMsg)
+	{
+	TThreadMessage& m = *(TThreadMessage*)aMsg;
+	TInt id = m.iValue;
+	TInt r = KErrNone;
+	if (id != (TInt)ECloseMsg && id != KMaxTInt)
+		{
+		if (id<0)
+			{
+			TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
+			r = SendRequest(aMsg);
+			if (r != KErrNone)
+				Kern::RequestComplete(pS,r);
+			}
+		else
+			r = SendControl(aMsg);
+		}
+	else
+		r = DLogicalChannel::SendMsg(aMsg);
+	return r;
+	}
+
+TInt DChannelResManUs::SendRequest(TMessageBase* aMsg)
+	{
+	TThreadMessage& m = *(TThreadMessage*)aMsg;
+	TInt id = ~m.iValue;
+	TRequestStatus* pS = (TRequestStatus*)m.Ptr0();
+	TInt r = KErrNone;
+	TTrackingBuffer *trackBuf = NULL;
+	TUint parms[4];
+	TPowerResourceCb *callBack;
+	DPowerResourceNotification *prn;
+
+	switch(id)
+		{
+		case RBusDevResManUs::EChangeResourceState:
+			{
+			__ASSERT_ALWAYS(m.Ptr2() != NULL, RESMANUS_FAULT());
+#ifdef _DUMP_TRACKERS
+			if((r=DumpTracker(iSetStateTracker))!=KErrNone)
+				break;
+#endif
+			r = GetAndInitTrackingBuffer(iSetStateTracker, trackBuf, (TUint)m.Ptr1(), pS);
+			if( r != KErrNone)
+				return r;
+			callBack = &(((TTrackSetStateBuf*)trackBuf)->iCtrlBlock);
+			new (callBack) TPowerResourceCb(&AsyncCallBackFn, (TAny*)trackBuf, iDfcQ, KResManCallBackPriority);
+			parms[0] = (TUint)m.Ptr2();
+			parms[1] = (TUint)callBack;
+			m.iArg[2] = &(parms[0]);
+			break;
+			}
+		case RBusDevResManUs::EGetResourceState:
+			{
+			__ASSERT_ALWAYS(m.Ptr2() != NULL, RESMANUS_FAULT());
+			umemget32(&(parms[0]), m.Ptr2(), 3*sizeof(TInt));
+#ifdef _DUMP_TRACKERS
+			if((r=DumpTracker(iGetStateTracker))!=KErrNone)
+				break;
+#endif
+			r = GetStateBuffer(iGetStateTracker, trackBuf, (TUint)m.Ptr1(), (TInt*)parms[1], (TInt*)parms[2], callBack, pS);
+			if(r != KErrNone)
+				return r;
+			parms[3] = (TUint)callBack;
+			m.iArg[2] = &(parms[0]);
+			break;
+			}
+		case RBusDevResManUs::ERequestChangeNotification:
+			{
+			__ASSERT_ALWAYS(m.Ptr1() != NULL, RESMANUS_FAULT());
+			r = GetAndInitTrackingBuffer(iListenableTracker, trackBuf, (TUint)m.Ptr1(), pS);
+			if(r != KErrNone)
+				return r;
+			prn = &(((TTrackNotifyBuf*)trackBuf)->iNotifyBlock);
+			new (prn) DPowerResourceNotification(&AsyncCallBackFn, (TAny*)trackBuf, iDfcQ, KResManCallBackPriority);
+			m.iArg[2] = (TAny*)prn;
+			break;
+			}
+		case RBusDevResManUs::ERequestQualifiedChangeNotification:
+			{
+			__ASSERT_ALWAYS(m.Ptr1() != NULL, RESMANUS_FAULT());
+			__ASSERT_ALWAYS(m.Ptr2() != NULL, RESMANUS_FAULT());
+			umemget32(&(parms[0]), m.Ptr2(), 2*sizeof(TUint));
+			m.iArg[2] = &parms[0];
+			r = GetAndInitTrackingBuffer(iListenableTracker, trackBuf, (TUint)parms[0], pS);
+			if(r != KErrNone)
+				return r;
+			prn = &(((TTrackNotifyBuf*)trackBuf)->iNotifyBlock);
+			new (prn) DPowerResourceNotification(&AsyncCallBackFn, (TAny*)trackBuf, iDfcQ, KResManCallBackPriority);
+			parms[2] = (TUint)prn;
+			break;
+			}
+		default:
+			{
+			return KErrNotSupported;
+			}
+		}
+
+	if(r == KErrNone)
+		r = DLogicalChannel::SendMsg(aMsg);
+	if(r != KErrNone)
+		FreeTrackingBuffer(trackBuf);
+	return r;
+	}
+
+
+TInt DChannelResManUs::SendControl(TMessageBase* aMsg)
+	{
+	TThreadMessage& m = *(TThreadMessage*)aMsg;
+	TInt id = m.iValue;
+	TInt param1 = 0;
+	TUint parms[4];
+	TAny* a1 = m.Ptr0();
+	TAny* a2 = m.Ptr1();
+	TAny* ptr1 = NULL;
+	switch(id)
+		{
+		case RBusDevResManUs::EInitialise:
+			{
+			__ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT());
+			TUint8 stateRes[3];
+			umemget(&(stateRes[0]), a1, 3*sizeof(TUint8));
+			m.iArg[0] = &(stateRes[0]);
+			break;
+			}
+		case RBusDevResManUs::EGetNoOfResources:
+		case RBusDevResManUs::EGetResourceControllerVersion:
+			{
+			__ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT());
+			m.iArg[0] = &param1;
+			break;
+			}
+		case RBusDevResManUs::EGetNoOfClients:
+		case RBusDevResManUs::EGetNumClientsUsingResource:
+			{
+			__ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT());
+			__ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT());
+			umemget32(&(parms[0]), a2, 3*sizeof(TUint));
+			m.iArg[1]  = &(parms[0]);
+			m.iArg[0] = &param1;
+			break;
+			}
+		case RBusDevResManUs::EGetNumResourcesInUseByClient:
+			{
+			__ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT());
+			__ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT());
+			TBuf8 <MAX_NAME_LENGTH_IN_RESMAN> clientName;
+			Kern::KUDesGet(clientName, *(TDesC8*)m.Ptr0());
+			m.iArg[0] = (TAny*)&clientName;
+			umemget32(&(parms[0]), m.Ptr1(), 2*sizeof(TUint));
+			param1 = parms[1];
+			m.iArg[1] = &param1;
+			break;
+			}
+		case RBusDevResManUs::EGetResourceIdByName:
+			{
+			__ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT());
+			__ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT());
+			TBuf8 <MAX_NAME_LENGTH_IN_RESMAN> resourceName;
+			Kern::KUDesGet(resourceName, *(TDesC8*)m.Ptr0());
+			m.iArg[0] = (TAny*)&resourceName;
+			m.iArg[1] = &param1;
+			break;
+			}
+#ifdef RESOURCE_MANAGER_SIMULATED_PSL
+		case RBusDevResManUs::EGetNumCandidateAsyncResources:
+		case RBusDevResManUs::EGetNumCandidateSharedResources:
+			{
+			__ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT());
+			m.iArg[0] = &param1;
+			break;
+			}
+		case RBusDevResManUs::EGetCandidateAsyncResourceId:
+		case RBusDevResManUs::EGetCandidateSharedResourceId:
+			{
+			__ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT());
+			m.iArg[1] = &param1;
+			break;
+			}
+#endif
+		case RBusDevResManUs::EGetNumDependentsForResource:
+			{
+			__ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT());
+			__ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT());
+			umemget32(&(parms[0]), m.Ptr1(), 2*sizeof(TUint));
+			m.iArg[1] = &(parms[0]);
+			m.iArg[0] = &param1;
+			break;
+			}
+		case RBusDevResManUs::EGetDependentsIdForResource:
+			{
+			__ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT());
+			__ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT());
+			umemget32(&(parms[0]), m.Ptr1(), 3*sizeof(TUint));
+			TInt len, maxLen;
+			ptr1 = (TAny*)parms[1];
+			Kern::KUDesInfo(*(const TDesC8*)parms[1], len, maxLen);
+			umemget32(&param1, m.Ptr0(), sizeof(TUint));
+			if((maxLen - len) < (TInt)(param1 * sizeof(SResourceDependencyInfo)))
+				{
+				return KErrArgument;
+				}
+			m.iArg[0] = &param1;
+			m.iArg[1] = &(parms[0]);
+			break;
+			}
+		case RBusDevResManUs::EGetResourceInfo:
+			{
+			__ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT());
+			__ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT());
+			TResourceInfoBuf buf;
+			m.iArg[1] = &buf;
+			break;
+			}
+		case RBusDevResManUs::EGetAllResourcesInfo:
+			{
+			__ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT());
+			__ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT());
+			umemget32(&(parms[0]), m.Ptr1(), 2*sizeof(TUint));
+			ptr1 = (TAny*)parms[0];
+			umemget32(&param1, (TAny*)parms[0], sizeof(TUint));
+			parms[0]  =(TUint)&param1;
+			RSimplePointerArray<TResourceInfoBuf> infoPtrs;
+			umemget(&infoPtrs, m.Ptr0(), sizeof(RSimplePointerArray<TResourceInfoBuf>));
+			if((infoPtrs.Count() < 0) || (infoPtrs.Count() < param1))
+				return KErrArgument;
+			m.iArg[1] = &(parms[0]);
+			break;
+			}
+		case RBusDevResManUs::EGetInfoOnClientsUsingResource:
+			{
+			__ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT());
+			__ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT());
+			umemget32(&parms[0], m.Ptr1(), 4*sizeof(TUint));
+			ptr1 = (TAny*)parms[0];
+			umemget32(&param1, (TAny*)parms[0], sizeof(TUint));
+			parms[0] = (TUint)&param1;
+			RSimplePointerArray<TClientInfoBuf>infoPtrs;
+			umemget(&infoPtrs, m.Ptr0(), sizeof(RSimplePointerArray<TClientInfoBuf>));
+			if((infoPtrs.Count() < 0) || (infoPtrs.Count() < param1))
+				return KErrArgument;
+			m.iArg[1] = &(parms[0]);
+			break;
+			}
+		case RBusDevResManUs::EGetNamesAllClients:
+			{
+			__ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT());
+			__ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT());
+			umemget32(&parms[0], m.Ptr1(), 4*sizeof(TUint));
+			ptr1 = (TAny*)parms[0];
+			umemget32(&param1, (TAny*)parms[0], sizeof(TUint));
+			parms[0] = (TUint)&param1;
+			RSimplePointerArray<TClientName> infoPtrs;
+			umemget(&infoPtrs, m.Ptr0(), sizeof(RSimplePointerArray<TClientName>));
+			if((infoPtrs.Count() < 0) || (infoPtrs.Count() < param1))
+				return KErrArgument;
+			m.iArg[1] = &(parms[0]);
+			break;
+			}
+		case RBusDevResManUs::EGetInfoOnResourcesInUseByClient:
+			{
+			__ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT());
+			__ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT());
+			TBuf8 <MAX_NAME_LENGTH_IN_RESMAN> clientName;
+			Kern::KUDesGet(clientName, *(TDesC8*)m.Ptr0());
+			m.iArg[0] = (TAny*)&clientName;
+			umemget32(&parms[0], m.Ptr1(), 3*sizeof(TUint));
+			ptr1 = (TAny*)parms[0];
+			umemget32(&param1, (TAny*)parms[0], sizeof(TUint));
+			parms[0] = (TUint)&param1;
+			RSimplePointerArray<TResourceInfoBuf> infoPtrs;
+			umemget(&infoPtrs, (TAny*)parms[1], sizeof(RSimplePointerArray<TResourceInfoBuf>));
+			if((infoPtrs.Count() < 0) || (infoPtrs.Count() < param1))
+				return KErrArgument;
+			m.iArg[1] = &(parms[0]);
+			break;
+			}
+		}
+
+	TInt r = DLogicalChannel::SendMsg(aMsg);
+	if(r != KErrNone)
+		return r;
+
+	switch(id)
+		{
+		case RBusDevResManUs::EGetNoOfResources:
+		case RBusDevResManUs::EGetNoOfClients:
+		case RBusDevResManUs::EGetNumClientsUsingResource:
+		case RBusDevResManUs::EGetResourceControllerVersion:
+		case RBusDevResManUs::EGetNumDependentsForResource:
+			{
+			umemput32(a1, (TAny*)&param1, sizeof(TUint));
+			break;
+			}
+		case RBusDevResManUs::EGetNumResourcesInUseByClient:
+			{
+			umemput32((TAny*)parms[0], (TAny*)&param1, sizeof(TUint));
+			break;
+			}
+		case RBusDevResManUs::EGetResourceIdByName:
+			{
+			umemput32(a2, (TAny*)&param1, sizeof(TUint));
+			break;
+			}
+#ifdef RESOURCE_MANAGER_SIMULATED_PSL
+		case RBusDevResManUs::EGetNumCandidateAsyncResources:
+		case RBusDevResManUs::EGetNumCandidateSharedResources:
+			{
+			umemput32(a1, (TAny*)&param1, sizeof(TUint));
+			break;
+			}
+		case RBusDevResManUs::EGetCandidateAsyncResourceId:
+		case RBusDevResManUs::EGetCandidateSharedResourceId:
+			{
+			umemput32(a2, (TAny*)&param1, sizeof(TUint));
+			break;
+			}
+#endif
+		case RBusDevResManUs::EGetDependentsIdForResource:
+			{
+			r = Kern::ThreadDesWrite(iClient,(TAny*)ptr1, (const TDesC8&)*(SResourceDependencyInfo*)parms[1], 0);
+			if(r == KErrOverflow) //This is done to retain the error as per API spec
+				r = KErrArgument;
+			break;
+			}
+		case RBusDevResManUs::EGetResourceInfo:
+			{
+			Kern::KUDesPut(*(TDes8*)a2, (const TDesC8&)*(TResourceInfoBuf*)m.Ptr1());
+			break;
+			}
+		case RBusDevResManUs::EGetAllResourcesInfo:
+			{
+			TUint numToCopy;
+			RSimplePointerArray<TResourceInfoBuf> infoPtrs;
+			umemget(&infoPtrs, a1, sizeof(RSimplePointerArray<TResourceInfoBuf>));
+			numToCopy = (infoPtrs.Count() < param1) ? infoPtrs.Count() : param1;
+			umemput32(ptr1, (TAny*)&param1, sizeof(TUint));
+			TResourceInfoBuf** entriesAddr = infoPtrs.Entries();
+			TInt* entryPtr = (TInt*)entriesAddr;
+			TPowerResourceInfoV01 *currRes = (TPowerResourceInfoV01*)iResourceInfoResCtrl->Ptr();
+			TResourceInfoBuf* clientAddr;
+			TResourceInfoBuf tempInfo;
+			for(TUint index = 0; index < numToCopy; index++)
+				{
+				umemget32(&clientAddr, entryPtr, sizeof(TResourceInfoBuf*));
+				entryPtr++;
+				r = ExtractResourceInfo(currRes, tempInfo);
+				if(r != KErrNone)
+					return r;
+				umemput((TAny*)clientAddr, (TAny*)&(tempInfo), tempInfo.Length());
+				currRes++;
+				}
+			break;
+			}
+		case RBusDevResManUs::EGetInfoOnClientsUsingResource:
+			{
+			TUint numToCopy;
+			RSimplePointerArray<TClientInfoBuf> infoPtrs;
+			umemget(&infoPtrs, a1, sizeof(RSimplePointerArray<TClientName>));
+			numToCopy = infoPtrs.Count();
+			TClientInfoBuf** entriesAddr = infoPtrs.Entries();
+			TInt* entryPtr = (TInt*)entriesAddr;
+			TPowerClientInfoV01* rcDataPtr = (TPowerClientInfoV01*)iClientNamesResCtrl->Ptr();
+			TClientInfoBuf* clientAddr;
+			TUint userSideClients = 0;
+			TClientInfoBuf tempInfo;
+			for(TInt index = 0; index < param1; index++)
+				{
+				if((!parms[1]) && !(rcDataPtr->iClientId & USER_SIDE_CLIENT_BIT_MASK))
+					{
+					rcDataPtr++;
+					continue;
+					}
+				if(numToCopy == 0)
+					{
+					userSideClients++;
+					continue;
+					}
+				umemget32(&clientAddr, entryPtr, sizeof(TClientName*));
+				entryPtr++;
+				tempInfo().iId = rcDataPtr->iClientId;
+				tempInfo().iName = *rcDataPtr->iClientName;
+				Kern::InfoCopy(*clientAddr, tempInfo);
+				rcDataPtr++;
+				numToCopy--;
+				userSideClients++;
+				}
+			if(parms[1])
+				umemput32(ptr1, (TAny*)&param1, sizeof(TUint));
+			else
+				umemput32(ptr1, (TAny*)&userSideClients, sizeof(TUint));
+			break;
+			}
+		case RBusDevResManUs::EGetNamesAllClients:
+			{
+			TUint numToCopy;
+			RSimplePointerArray<TClientName> infoPtrs;
+			umemget(&infoPtrs, a1, sizeof(RSimplePointerArray<TClientName>));
+			numToCopy = infoPtrs.Count();
+			TClientName** entriesAddr = infoPtrs.Entries();
+			TInt* entryPtr = (TInt*)entriesAddr;
+			TPowerClientInfoV01* rcDataPtr = (TPowerClientInfoV01*)iClientNamesResCtrl->Ptr();
+			TClientName* clientAddr;
+			TUint userSideClients = 0;
+			for(TInt index = 0; index < param1; index++)
+				{
+				if((!parms[1]) && !(rcDataPtr->iClientId & USER_SIDE_CLIENT_BIT_MASK))
+					{
+					rcDataPtr++;
+					continue;
+					}
+				if(numToCopy == 0)
+					{
+					userSideClients++;
+					continue;
+					}
+				umemget32(&clientAddr, entryPtr, sizeof(TClientName*));
+				entryPtr++;
+				Kern::KUDesPut(*((TDes8*)clientAddr), *(const TDesC8*)rcDataPtr->iClientName);
+				rcDataPtr++;
+				numToCopy--;
+				userSideClients++;
+				}
+			if(parms[1])
+				umemput32(ptr1, (TAny*)&param1, sizeof(TUint));
+			else
+				umemput32(ptr1, (TAny*)&userSideClients, sizeof(TUint));
+			break;
+			}
+		case RBusDevResManUs::EGetInfoOnResourcesInUseByClient:
+			{
+			TUint numToCopy;
+			RSimplePointerArray<TResourceInfoBuf> infoPtrs;
+			umemget(&infoPtrs, (TAny*)parms[1], sizeof(RSimplePointerArray<TResourceInfoBuf>));
+			numToCopy = (infoPtrs.Count() < param1) ? infoPtrs.Count() : param1;
+			umemput32(ptr1, (TAny*)&param1, sizeof(TUint));
+			TResourceInfoBuf** entriesAddr = infoPtrs.Entries();
+			TInt* entryPtr = (TInt*)entriesAddr;
+			TPowerResourceInfoV01* currRes = (TPowerResourceInfoV01*)iResourceInfoResCtrl->Ptr();
+			TResourceInfoBuf* clientAddr;
+			TResourceInfoBuf tempInfo;
+			for(TUint index = 0; index < numToCopy; index++)
+				{
+				umemget32(&clientAddr, entryPtr, sizeof(TResourceInfoBuf*));
+				entryPtr++;
+				r = ExtractResourceInfo(currRes, tempInfo);
+				if(r != KErrNone)
+					return r;
+				umemput((TAny*)clientAddr, (TAny*)&(tempInfo), tempInfo.Length());
+				currRes++;
+				}
+			break;
+			}
+		}
+	return r;
+	}
+
+void DChannelResManUs::HandleMsg(TMessageBase* aMsg)
+    {
+    TThreadMessage& m=*(TThreadMessage*)aMsg;
+    TInt id=m.iValue;
+    
+    __KTRACE_OPT(KRESMANAGER, Kern::Printf(" >ldd: DChannelResManUs::HandleMsg(TMessageBase* aMsg) id=%d\n", id));
+	
+	if (id==(TInt)ECloseMsg)
+		{
+		// Deregister here to ensure the correct thread ID is read
+		if(ClientHandle() != 0)
+			{
+			// Must de-register from Resource Controller before closing down
+			// Not checking return value - still need to delete allocated buffers
+#ifdef PRM_US_INSTRUMENTATION_MACRO
+	PRM_US_DEREGISTER_CLIENT_START_TRACE;
+#endif
+			((DPowerResourceController*)iPddPtr)->DeregisterProxyClient(ClientHandle());
+
+#ifdef PRM_US_INSTRUMENTATION_MACRO
+	PRM_US_DEREGISTER_CLIENT_END_TRACE;
+#endif
+			SetClientHandle(0);
+			}
+	    iMsgQ.iMessage->Complete(KErrNone,EFalse);
+		return;
+		}
+    else if (id==KMaxTInt)
+		{
+		// DoCancel
+		DoCancel(m.Int0());
+		m.Complete(KErrNone,ETrue);
+		return;
+		}
+
+    if (id<0)
+		{
+		// DoRequest
+		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
+		TInt r=DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
+		m.Complete(r,ETrue);
+		}
+    else
+		{
+		// DoControl
+		__KTRACE_OPT(KRESMANAGER, Kern::Printf(" >ldd: do control id=%d...\n", id));
+		TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
+		m.Complete(r,ETrue);
+		}
+	}
+
+TInt DChannelResManUs::CancelTrackerRequests(TTrackingControl* aTracker, TBool aSingleRsrc, TUint aResourceId, TRequestStatus* aStatus)
+	{
+	// Cancel all outstanding requests from this client for a specified operation on 
+	// a specified resource
+
+	// Loop all entries in the iBusyQue of requests to locate a match for the 
+	// operation type and resource ID
+	//
+	// For each match, remove the buffer from the busy queue and return to the free queue
+	// If the request is already being processed, and so the callback function will be called
+	// later, then the callback will exit gracefully.
+	//
+    __KTRACE_OPT(KRESMANAGER, Kern::Printf(" > DChannelResManUs::CancelTrackerRequests"));
+	TInt returnVal = KErrNone;
+	TBool statusMatched=EFalse;
+	TTrackingBuffer* firstLink = NULL;
+	TTrackingBuffer* lastLink = NULL;
+	TInt type = aTracker->iType;
+
+#ifdef PRM_US_INSTRUMENTATION_MACRO
+	if(type==EGetState)
+		{
+		PRM_US_CANCEL_GET_RESOURCE_STATE_START_TRACE;
+		}
+	else if(type==ESetState)
+		{
+		PRM_US_CANCEL_SET_RESOURCE_STATE_START_TRACE;
+		}
+#endif
+
+	if(aTracker->iBusyQue != NULL)
+		{
+		firstLink = (TTrackingBuffer*)(aTracker->iBusyQue->iA.iNext);
+		lastLink = (TTrackingBuffer*)(&(aTracker->iBusyQue->iA));
+		}
+	while(( firstLink!=lastLink )&&(!statusMatched))
+		{
+		TTrackingBuffer* buffer = firstLink;
+		TUint resourceId = buffer->GetResourceId();
+		if(aSingleRsrc)
+			if(resourceId != aResourceId)	// Required resource?
+				{
+				firstLink=(TTrackingBuffer*)(firstLink->iNext);
+				continue;
+				}
+		if(aStatus!=NULL)
+			{
+			TClientRequest *request;
+			GET_USER_REQUEST(request, buffer, type)
+			if(request->StatusPtr() == aStatus)
+				{
+				statusMatched = ETrue;
+				}
+			else
+				{
+				firstLink=(TTrackingBuffer*)(firstLink->iNext);
+				continue;
+				}
+			}
+		TInt r = KErrNone;
+		if(type==EGetState)
+			{
+			TTrackGetStateBuf* stateBuf = (TTrackGetStateBuf*)firstLink;
+			r=((DPowerResourceController*)iPddPtr)->CancelAsyncRequestCallBack(ClientHandle(),
+															resourceId, (stateBuf->iCtrlBlock));
+			}
+		else if(type==ESetState)
+			{
+			TTrackSetStateBuf* stateBuf = (TTrackSetStateBuf*)firstLink;
+			r = ((DPowerResourceController*)iPddPtr)->CancelAsyncRequestCallBack(ClientHandle(), 
+															resourceId, (stateBuf->iCtrlBlock));
+			}
+		else if(type==ENotify)
+			{
+			TTrackNotifyBuf* notifyBuf = (TTrackNotifyBuf*)firstLink;
+			r=((DPowerResourceController*)iPddPtr)->CancelNotification(ClientHandle(), resourceId,
+															notifyBuf->iNotifyBlock);
+			}
+
+		// Process the accumulated return value
+		if((r==KErrCompletion)&&((returnVal==KErrNone)||(returnVal==KErrCancel)))
+			{
+			returnVal=KErrCompletion;	
+			}
+		else if((r==KErrInUse)&&
+			((returnVal==KErrNone)||(returnVal==KErrCompletion)||(returnVal==KErrCancel)))
+			{
+			returnVal=KErrInUse;
+			}
+		else if(r!=KErrCancel)
+			{
+			returnVal=r;
+			}
+
+		// Return the tracking buffer to the free queue
+		TTrackingBuffer* tempLink = (TTrackingBuffer*)(firstLink->iNext);
+		FreeTrackingBuffer(firstLink);
+		firstLink = tempLink;
+
+#ifdef PRM_US_INSTRUMENTATION_MACRO
+	if(type==EGetState)
+		{
+		PRM_US_CANCEL_GET_RESOURCE_STATE_END_TRACE;
+		}
+	else if(type==ESetState)
+		{
+		PRM_US_CANCEL_SET_RESOURCE_STATE_END_TRACE;
+		}
+#endif
+		// Complete the TRequestStatus object
+		if((r!=KErrCompletion)&&(r!=KErrInUse))
+			{
+			TClientRequest* request;
+			GET_USER_REQUEST(request, buffer, type)
+			Kern::QueueRequestComplete(iClient, request, r);
+			}
+
+		} //  while
+	return returnVal;
+	}
+
+
+TTrackingControl* DChannelResManUs::MapRequestToTracker(TInt aRequestType)
+// Utility function to map identifiers for cancel commands to request types.
+	{
+	TTrackingControl *tracker=NULL;
+	switch(aRequestType)
+		{
+		case RBusDevResManUs::ECancelChangeResourceStateRequests:
+		case RBusDevResManUs::ECancelChangeResourceState:
+			{
+			tracker=iSetStateTracker;
+			break;
+			}
+		case RBusDevResManUs::ECancelGetResourceStateRequests:
+		case RBusDevResManUs::ECancelGetResourceState:
+			{
+			tracker=iGetStateTracker;
+			break;
+			}
+		case RBusDevResManUs::ECancelChangeNotificationRequests:
+		case RBusDevResManUs::ECancelRequestChangeNotification:
+			{
+			tracker=iListenableTracker;
+			break;
+			}
+		default:
+			{
+			__ASSERT_ALWAYS(0,RESMANUS_FAULT());
+			}
+		}
+	return tracker;
+	}
+
+
+TInt DChannelResManUs::CancelRequestsOfType(TInt aRequestType, TRequestStatus* aStatus)
+// Cancel a particular request. This may be qualified by the type of operation
+    {
+	__ASSERT_ALWAYS(((aRequestType==RBusDevResManUs::ECancelChangeResourceState)||
+					(aRequestType==RBusDevResManUs::ECancelGetResourceState)||
+					(aRequestType==RBusDevResManUs::ECancelRequestChangeNotification)||
+					(KMaxTInt)),
+					RESMANUS_FAULT());
+	// For the KMaxTInt case, the type of the request is not known and so all trackers
+	// must be considered before the request is found.
+	// For all other cases, only the relevant tracker is searched.
+	TInt r=KErrNone;
+	if(aRequestType!=KMaxTInt)
+		{
+		TTrackingControl*tracker=MapRequestToTracker(aRequestType);
+		r=CancelTrackerRequests(tracker, EFalse, 0, aStatus);
+		}
+	else
+		{
+		TTrackingControl* tracker[3] = {iGetStateTracker, iSetStateTracker, iListenableTracker};
+		TUint8 index=0;
+		while((index<3) && (r==KErrNone))
+			{
+			r=CancelTrackerRequests(tracker[index], EFalse, 0, aStatus);
+			++index;
+			}
+		}
+	if(r==KErrCancel) 
+		r=KErrNone;	// All cancellations were successful
+
+	return r;
+	}
+
+
+void DChannelResManUs::DoCancel(TInt aMask)
+// Cancel an outstanding request.
+    {
+	TRequestStatus* status = (TRequestStatus*)aMask;
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoCancel, TRequestStatus addr = 0x%x",(TInt)status));
+
+	CancelRequestsOfType(KMaxTInt, status); // Ignore return value
+	return;
+	}
+
+TInt DChannelResManUs::DoRequest(TInt aReqNo, TRequestStatus* /*aStatus*/, TAny* a1, TAny* a2)
+// Asynchronous requests.
+    {
+    __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)"));
+
+    TInt r=KErrNone;
+    switch (aReqNo)
+		{
+		case RBusDevResManUs::EChangeResourceState:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoRequest case EChangeResourceState"));
+			// a1 specifies the identifier of the required resource
+			// a2 specifies the required state for the resource
+			//
+			TUint *param = (TUint*)a2;
+			TUint resourceId = (TUint)a1;
+			TInt newState = (TInt)param[0];
+
+#ifdef PRM_US_INSTRUMENTATION_MACRO
+	PRM_US_SET_RESOURCE_STATE_START_TRACE;
+#endif
+				// Invoke the API
+				r=((DPowerResourceController*)iPddPtr)->ChangeResourceState(ClientHandle(),
+														resourceId, newState, (TPowerResourceCb*)param[1]);
+			break;
+			}
+
+		case RBusDevResManUs::EGetResourceState:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoRequest case EGetResourceState"));
+			// a1 specifies the resource ID
+			// a2 specifies the container stating if a cached value is required, the address of the variable
+			// to be update with the state value and the address of the level owner ID
+			//
+			TUint resourceId = (TUint)a1;
+			TUint *parms = (TUint*)a2;
+			TBool cached = (TBool)(parms[0]);
+
+#ifdef PRM_US_INSTRUMENTATION_MACRO
+	PRM_US_GET_RESOURCE_STATE_START_TRACE;
+#endif
+				// Always invoke the asynchronous version of the API
+				r=((DPowerResourceController*)iPddPtr)->GetResourceState(ClientHandle(),
+																		resourceId, cached, *((TPowerResourceCb*)parms[3]));
+			break;
+			}
+
+
+		case RBusDevResManUs::ERequestChangeNotification:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoRequest case ERequestChangeNotification"));
+			// a1 specifies the resource ID
+			r=((DPowerResourceController*)iPddPtr)->RequestNotification(ClientHandle(),
+														(TUint)a1, *((DPowerResourceNotification*)a2));
+			break;
+			}
+
+		case RBusDevResManUs::ERequestQualifiedChangeNotification:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoRequest case ERequestQualifiedChangeNotification"));
+			// a1 specifies the threshold value that the state is to change by
+			// a2 specifies the address of the container holding the resourceID and the required direction
+			TInt threshold = (TInt)a1;
+			TUint *parms = (TUint*)a2;
+			TUint resourceId = parms[0];
+			TBool direction = (TBool)(parms[1]);			
+			r=((DPowerResourceController*)iPddPtr)->RequestNotification(ClientHandle(),
+														resourceId, *((DPowerResourceNotification*)parms[2]), threshold, direction);
+			break;
+			}
+
+		default:
+	    	return KErrNotSupported;
+		}
+	    return r;
+    }
+
+TInt DChannelResManUs::DoControl(TInt aFunction, TAny* a1, TAny* a2)
+// Synchronous requests.
+    {
+    __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::DoControl(TInt aFunction, TAny* a1, TAny* a2)") );
+
+    TInt r=KErrNone;
+    switch (aFunction)
+		{
+		case RBusDevResManUs::EInitialise:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EInitialise"));
+			// a1 specifies the array describing the number of 'gettable' and 'settable' state resources
+			// and the number of 'listenable' resources
+			//
+			TUint8 *stateRes = (TUint8*)a1;
+#ifdef PRM_US_INSTRUMENTATION_MACRO
+	PRM_US_REGISTER_CLIENT_START_TRACE;
+#endif
+			// The call to the Resource Controller's AllocReserve method requires two parameters:
+			// the number of client level objects and the number of request message objects
+			// Each 'settable' state resource requires a client level object and a request message object
+			// Each 'gettable' state resource requires a request message object, only.
+			// Call Resource Control to make allocations
+			r=((DPowerResourceController*)iPddPtr)->AllocReserve(ClientHandle(),
+															stateRes[1],							// Number of settable
+															(TUint8)(stateRes[1] + stateRes[0]));	// Number of (settable + gettable)
+#ifdef PRM_US_INSTRUMENTATION_MACRO
+	PRM_US_REGISTER_CLIENT_END_TRACE;
+#endif
+			if(r==KErrNone)
+				{
+				// Require 1 TPowerResourceCb object per gettable resource state
+				// Require 1 TPowerResourceCb object per settable resource state
+				// Require 1 DPowerResourceNotification object per listenable resource
+				//
+				if(stateRes[0]>0)
+					r=InitTrackingControl(iGetStateTracker,EGetState,stateRes[0]);
+				if((r==KErrNone) && (stateRes[1]>0))
+					r=InitTrackingControl(iSetStateTracker,ESetState,stateRes[1]);
+				if((r==KErrNone) && (stateRes[2]>0))
+					r=InitTrackingControl(iListenableTracker,ENotify,stateRes[2]);
+#ifdef _DUMP_TRACKERS
+			if((r=DumpTracker(iGetStateTracker))!=KErrNone)
+				break;
+			if((r=DumpTracker(iSetStateTracker))!=KErrNone)
+				break;
+#endif
+				}
+			break;
+			}
+
+		case RBusDevResManUs::EGetNoOfResources:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetNoOfResources"));
+			TUint numResources;
+			r=((DPowerResourceController*)iPddPtr)->GetNumResourcesInUseByClient(ClientHandle(),0,numResources);
+			iResInfoValid = 0;			// New numResources invalidates the iResInfoXXXX information
+			iResInfoStoredClientId = 0;
+			iResInfoStoredNum = 0;
+			if(r!=KErrNone)
+				return r;
+			// a2 specifies whether the resource information should be loaded
+			if((r==KErrNone)&&(a2!=NULL))
+				{
+				TUint prevNumRes = 0;
+				while((numResources != prevNumRes)&&(r==KErrNone))
+					{
+					// if the number of resources is greater than can be accommodated by the array,
+					// re-size it
+					if((r=EnsureSizeIsSufficient(iResourceInfoResCtrl, (TInt)(numResources*sizeof(TPowerResourceInfoV01))))!=KErrNone)
+						break;
+					prevNumRes = numResources;
+					// Get the resource info from the Resource Controller
+					// Specify 'aTargetClientId' as zero to access all resources
+					iResourceInfoResCtrl->SetLength(0);
+					r=((DPowerResourceController*)iPddPtr)->GetInfoOnResourcesInUseByClient(
+															ClientHandle(),0,numResources,iResourceInfoResCtrl);
+					}
+				if(r==KErrNone)
+					{
+					iResInfoValid = 1;
+					iResInfoStoredClientId = KAllResInfoStored;
+					iResInfoStoredNum = numResources;
+					}
+				}
+			if(r==KErrNone)
+				*(TUint*)a1 = numResources;
+			break;
+			}
+
+		case RBusDevResManUs::EGetAllResourcesInfo:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetAllResourcesInfo"));
+			// Parameters are passed in TUint* parms[2]
+			// The address of the number of resources is at element 0
+			// The flag to indicate if the resource info stored is to be refreshed is at element 1
+			TUint* parms = (TUint*)a2;
+			TUint numResources = *(TUint*)parms[0];
+			TBool refresh=(TBool)(parms[1]);
+			
+			// The results are to be written to an RSimplePointerArray, the address is in a1
+			// Check that the array has enough elements
+			if(refresh)
+				{
+				// For the refresh option, invoke Resource Controller API once, only (do not recurse)
+				// If the number of requested resources is greater than can be accommodated by the array,
+				// re-size it
+				if((r=EnsureSizeIsSufficient(iResourceInfoResCtrl, (TInt)(numResources*sizeof(TPowerResourceInfoV01))))!=KErrNone)
+					break;
+				// Get the resource info from the Resource Controller
+				// Specify 'aTargetClientId' as zero to access all resources
+				iResourceInfoResCtrl->SetLength(0);
+				r=((DPowerResourceController*)iPddPtr)->GetInfoOnResourcesInUseByClient(
+														ClientHandle(),0,numResources,iResourceInfoResCtrl);
+				if(numResources != iResInfoStoredNum)
+					{
+					iResInfoValid = 0;		// Assume cohesion is now lost 
+					iResInfoStoredClientId = 0;
+					iResInfoStoredNum = 0;
+					}
+				}
+			else
+				{
+				// If the information stored is not valid or is not for all resources return KErrNotReady 
+				if((iResInfoValid != 1)||(iResInfoStoredClientId != KAllResInfoStored))
+					{
+					r=KErrNotReady;
+					break;
+					}
+				// The number of resources for which information is available in this case is iResInfoStoredNum
+				numResources = iResInfoStoredNum;
+				}
+#ifdef RESOURCE_MANAGER_SIMULATED_PSL
+			TPowerResourceInfoV01* currRes = (TPowerResourceInfoV01*)iResourceInfoResCtrl->Ptr();
+			for(TUint index = 0; index < numResources; index++)
+				{
+				CheckForCandidateAsyncResource(currRes);
+				CheckForCandidateSharedResource(currRes);
+				currRes++;
+				}
+#endif
+			*(TUint*)(parms[0]) = numResources;
+
+			break;
+			}
+
+		case RBusDevResManUs::EGetNoOfClients:
+		case RBusDevResManUs::EGetNumClientsUsingResource:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetNoOfClients"));
+			// Parameters are passed in TUint parms[3]
+			// The flag to indicate if kernel-side clients are to be included is at element 0
+			// The ID of the resource of interest (0 is expected for EGetNoOfClients)
+			// The flag to indicate if the client info is to be read now is at element 1
+			TUint *parms = (TUint*)a2;
+			TUint includeKern = parms[0];
+			TUint resourceId = parms[1];
+			TUint infoRead = parms[2];
+			TUint requiredId = resourceId;
+			if(aFunction == RBusDevResManUs::EGetNoOfClients)
+				{
+				__ASSERT_ALWAYS(resourceId==0,RESMANUS_FAULT());
+				requiredId = KAllClientInfoStored;
+				}
+			TUint numClients = 0;
+			if(includeKern==1)
+				{
+				// Client must exhibit PlatSec capability ReadDeviceData
+				if(!iClient->HasCapability(ECapabilityReadDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Resource Manager user-side API function EGetNoOfClients")))
+					{
+					r =  KErrPermissionDenied;
+					break;
+					}
+				if(r==KErrNone)
+					r=((DPowerResourceController*)iPddPtr)->GetNumClientsUsingResource(ClientHandle(),resourceId,numClients);
+				}
+			else
+				numClients = (TUint)(iDevice->iOpenChannels);
+
+			// New numClients invalidates the iClientInfoXXXX information
+			iClientInfoValid = 0;
+			iClientInfoStoredResId = 0;
+			iClientInfoStoredNum= 0;
+
+			if((r==KErrNone)&&(infoRead==1))
+				{
+				// Capability check already performed, so no need to repeat ...
+				TUint prevNumClients = 0;
+				while((numClients != prevNumClients)&&(r == KErrNone))
+					{
+					// Ensure buffer is large enough to store the information
+					if((r=EnsureSizeIsSufficient(iClientNamesResCtrl, (TInt)(numClients*sizeof(TPowerClientInfoV01))))!=KErrNone)
+						break;
+					prevNumClients = numClients;
+					// Invoke the API
+					r=((DPowerResourceController*)iPddPtr)->GetInfoOnClientsUsingResource(ClientHandle(),
+																					resourceId,numClients,iClientNamesResCtrl);
+					};
+
+				if(r==KErrNone)
+					{
+					iClientInfoValid = 1;
+					iClientInfoStoredResId = requiredId;
+					iClientInfoStoredNum = numClients;
+					if(includeKern!=1)
+						{
+						TUint numAllClients = numClients;
+						numClients = 0;
+						TPowerClientInfoV01* rcDataPtr = (TPowerClientInfoV01*)(iClientNamesResCtrl->Ptr());
+						for(TUint i=0; i<numAllClients; i++)
+							{
+							if( rcDataPtr->iClientId & USER_SIDE_CLIENT_BIT_MASK)
+								++numClients;
+							++rcDataPtr;
+							}
+						}
+					}
+				}
+			if(r==KErrNone)
+				*(TUint*)a1 = numClients;
+			break;
+			}
+
+		case RBusDevResManUs::EGetNamesAllClients:
+		case RBusDevResManUs::EGetInfoOnClientsUsingResource:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetNamesAllClients-EGetInfoOnClientsUsingResource"));
+			// Parameters are passed in TUint* parms[4]
+			// The address of the number of clients is at element 0
+			// The flag to indicate if kernel-side info is requested is at element 1
+			// The resource ID is at element 2
+			// The flag to indicate if the client information stored is to be refreshed is at element 3
+			TUint* parms = (TUint*)a2;
+			TUint numClients = *(TUint*)parms[0];
+			TBool includeKern=(TBool)(parms[1]);
+			TUint resourceId=(TUint)(parms[2]);
+			TBool refresh=(TBool)(parms[3]);
+		
+			TUint numClientsAvailable = 0; 
+			iClientNamesResCtrl->SetLength(0);
+			
+			if(includeKern)
+				{
+				// Client must exhibit PlatSec capability ReadDeviceData
+				if(!iClient->HasCapability(ECapabilityReadDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Resource Manager user-side API function EGetNamesAllClients-EGetInfoOnClientsUsingResource")))
+					{
+					r = KErrPermissionDenied;
+					break;  // Early exit in event of error
+					}
+				TUint requiredId = (resourceId==0)?(TUint)KAllClientInfoStored:resourceId;
+				if(refresh)
+					{
+					// For the refresh option, invoke Resource Controller API once, only (do not recurse)
+					// If the number of clients is greater than can be accommodated by the array,
+					// re-size it
+					if((r=EnsureSizeIsSufficient(iClientNamesResCtrl, (TInt)(numClients*sizeof(TPowerClientInfoV01))))!=KErrNone)
+						break;
+					// Invoke the API
+					numClientsAvailable = numClients; // Arbitrary initialisation (to silence compiler warning)
+					r=((DPowerResourceController*)iPddPtr)->GetInfoOnClientsUsingResource(ClientHandle(),
+																					resourceId,numClientsAvailable,iClientNamesResCtrl);
+					if((r!=KErrNone)||(numClientsAvailable != iClientInfoStoredNum)||(iClientInfoStoredResId != requiredId))
+						{
+						iClientInfoValid = 0;	// Assume cohesion is now lost	
+						iClientInfoStoredResId = 0;
+						iClientInfoStoredNum = 0;
+						}
+					}
+				else
+					{
+					// If the information stored is not valid, is not for the required resources return KErrNotReady 
+					if((iClientInfoValid != 1)||(iClientInfoStoredResId != requiredId))
+						r=KErrNotReady;
+					// The number of clients for which information is available in this case is iClientInfoStoredNum
+					numClientsAvailable = iClientInfoStoredNum;
+					}
+				}
+			else
+				{
+				// Resource Controller will return information for the number of clients requested,
+				// taken in order from its internal storage - but this will be regardless of whether
+				// they are kernel-side or user-side; the USER_SIDE_CLIENT_BIT_MASK bit must be 
+				// interrogated to determine this.
+				//
+				// Therefore, need to read all the clients - but to do this, must find out how many 
+				// clients there are first.
+				TUint numAllClients;
+				r=((DPowerResourceController*)iPddPtr)->GetNumClientsUsingResource(ClientHandle(),resourceId,numAllClients);
+				if(r!=KErrNone)
+					break;  // Early exit in event of error
+				if(numAllClients > 0)
+					{
+					if(refresh)
+						{
+						// For the refresh option, invoke Resource Controller API once, only (do not recurse)
+						// If the number of clients is greater than can be accommodated by the array,
+						// re-size it
+						if((r=EnsureSizeIsSufficient(iClientNamesResCtrl, (TInt)(numAllClients*sizeof(TPowerClientInfoV01))))!=KErrNone)
+							break;
+						// Invoke the API
+						r=((DPowerResourceController*)iPddPtr)->GetInfoOnClientsUsingResource(ClientHandle(),
+																						resourceId,numAllClients,iClientNamesResCtrl);
+						TUint requiredId = (resourceId==0)?(TUint)KAllClientInfoStored:resourceId;
+						if((r!=KErrNone)||(numClientsAvailable != iClientInfoStoredNum)||(iClientInfoStoredResId != requiredId))
+							{
+							iClientInfoValid = 0;	// Assume cohesion is now lost	
+							iClientInfoStoredResId = 0;
+							iClientInfoStoredNum = 0;
+							break;
+							}
+						else
+							{
+							iClientInfoValid = 1;
+							iClientInfoStoredResId = requiredId;
+							iClientInfoStoredNum = numAllClients;
+							}
+						}
+					else
+						{
+						// If the information stored is not valid, is not for the required resources return KErrNotReady 
+						TUint requiredId = (resourceId==0)?(TUint)KAllClientInfoStored:resourceId;
+						if((iClientInfoValid != 1)||(iClientInfoStoredResId != requiredId))
+							{
+							r=KErrNotReady;
+							break;
+							}
+						// The number of clients for which information is available in this case is iClientInfoStoredNum
+						numAllClients = iClientInfoStoredNum;
+						}
+					numClientsAvailable = numAllClients;
+					} // if(numAllClients > 0)
+				}
+			// Write the total number of user side cients available
+			*(TUint*)parms[0] = numClientsAvailable;
+			break;
+			}
+		case RBusDevResManUs::EGetNumResourcesInUseByClient:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetNumResourcesInUseByClient"));
+			// a1 specifies the container holding the client name
+			//
+			
+			// If client doesn't exist, return KErrNotFound
+			// If client has appropriate capabilities, or if the client for which the information is sought
+			// is user-side, invoke the Resource Controller API directly
+			// Otherwise, return KErrPermissionDenied
+			TUint clientId=0;
+			r=((DPowerResourceController*)iPddPtr)->GetClientId(ClientHandle(),
+															*(TDesC8*)a1,clientId);
+			if(r!=KErrNone)
+				return KErrNotFound;
+			// Perform capability check
+			if(!iClient->HasCapability(ECapabilityReadDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Resource Manager user-side API function EGetNoOfClients")))
+				{
+				if(!(clientId & USER_SIDE_CLIENT_BIT_MASK))
+					return KErrPermissionDenied;
+				}
+			TUint numResources=0;
+			if(r==KErrNone)
+				r=((DPowerResourceController*)iPddPtr)->GetNumResourcesInUseByClient(ClientHandle(),
+																			clientId,numResources);
+			// New numResources invalidates the iResXXXX information
+			iResInfoValid = 0;
+			iResInfoStoredClientId = 0;
+			iResInfoStoredNum= 0;
+
+			// parms[1] specifies whether the resource information should be loaded
+			if((r==KErrNone)&&(*(TUint*)a2 != NULL))
+				{
+				TUint prevNumRes = 0;
+				while((numResources != prevNumRes)&&(r==KErrNone))
+					{
+					// if the number of resources is greater than can be accommodated by the array,
+					// re-size it
+					if((r=EnsureSizeIsSufficient(iResourceInfoResCtrl, (TInt)(numResources*sizeof(TPowerResourceInfoV01))))!=KErrNone)
+						break;
+					prevNumRes = numResources;
+					// Get the resource info from the Resource Controller
+					// Specify 'aTargetClientId' as zero to access all resources
+					iResourceInfoResCtrl->SetLength(0);
+					r=((DPowerResourceController*)iPddPtr)->GetInfoOnResourcesInUseByClient(
+															ClientHandle(),clientId,numResources,iResourceInfoResCtrl);
+					}
+				if(r==KErrNone)
+					{
+					iResInfoValid = 1;
+					iResInfoStoredClientId = clientId;
+					iResInfoStoredNum = numResources;
+					}
+				}
+			if(r==KErrNone)
+				*(TUint*)a2 = numResources;
+			break;
+			}
+
+		case RBusDevResManUs::EGetInfoOnResourcesInUseByClient:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetInfoOnResourcesInUseByClient"));
+			// a1 specifies the container holding the client name
+			// a2 specifies an array TUint* parms[3] which contains:
+			//   - the address of the variable to write the number of reasources to
+			//   - a pointer to the container to hold the resources' information
+			//   - the flag to indicate whether the resource info should be (re-)read here
+
+			TUint clientId=0;
+			TUint *parms = (TUint*)a2;
+			TUint numResources = *(TUint*)parms[0];
+			// The results are to be written to an RSimplePointerArray, the address is in parms[1]
+			// Check that the array has enough elements
+			// If client doesn't exist, return KErrNotFound
+			// If client has appropriate capabilities, or if the client for which the information is sought
+			// is user-side, invoke the Resource Controller API directly
+			// Otherwise, return KErrPermissionDenied
+			r=((DPowerResourceController*)iPddPtr)->GetClientId(ClientHandle(),
+															*(TDesC8*)a1,clientId);
+			if(r!=KErrNone)
+				return KErrNotFound;
+			// Perform capability check
+			if(!iClient->HasCapability(ECapabilityReadDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Resource Manager user-side API function EGetNoOfClients")))
+				{
+				if(!(clientId & USER_SIDE_CLIENT_BIT_MASK))
+					return KErrPermissionDenied;
+				}
+
+			TUint updatedNumResources = numResources;
+			r=((DPowerResourceController*)iPddPtr)->GetNumResourcesInUseByClient(ClientHandle(),clientId,updatedNumResources);
+			if(r!=KErrNone)
+				break;
+
+			if(updatedNumResources>0)
+				{
+				if((TUint)(parms[2] != 0))
+					{
+					// For the refresh option, invoke Resource Controller API once, only (do not recurse)
+					// If the number of requested resources is greater than can be accommodated by the array,
+					// re-size it
+					if((r=EnsureSizeIsSufficient(iResourceInfoResCtrl, (TInt)(numResources*sizeof(TPowerResourceInfoV01))))!=KErrNone)
+						break;
+					// Get the resource info from the Resource Controller
+					// Specify 'aTargetClientId' as zero to access all resources
+					iResourceInfoResCtrl->SetLength(0);
+					r=((DPowerResourceController*)iPddPtr)->GetInfoOnResourcesInUseByClient(
+															ClientHandle(),clientId,numResources,iResourceInfoResCtrl);
+					if((numResources != iResInfoStoredNum)||(iResInfoStoredClientId != clientId))
+						{
+						iResInfoValid = 0;		// Assume cohesion is now lost 
+						iResInfoStoredClientId = 0;
+						iResInfoStoredNum = 0;
+						}
+					}
+				else
+					{
+					// If the information stored is not valid or is not for the required clientId return KErrNotReady 
+					if((iResInfoValid != 1)||(iResInfoStoredClientId != clientId))
+						r=KErrNotReady;
+					// The number of resources for which information is available in this case is iResInfoStoredNum
+					numResources = iResInfoStoredNum;
+					}
+				}
+			if(r==KErrNone)
+				*(TUint*)parms[0] = updatedNumResources;
+
+			break;
+			}
+
+		case RBusDevResManUs::EGetResourceIdByName:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetResourceIdByName"));
+			// a1 specifies the container holding the resource name
+			// a2 specifies the variable to be update with the ID
+			TUint resourceId;
+			r=((DPowerResourceController*)iPddPtr)->GetResourceId(ClientHandle(), *(TDesC8*)a1, resourceId);
+			if(r==KErrNone)
+				*(TUint *)a2 = resourceId;
+			break;
+			}
+
+		case RBusDevResManUs::EGetResourceInfo:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetResourceInfo"));
+			// a1 specifies the container holding the resource ID
+			// a2 specifies the address of the container to be written to
+
+			TUint resourceId= (TUint)a1;
+			TPowerResourceInfoBuf01 resCtrlInfo;
+			resCtrlInfo.SetLength(0);
+			TResourceInfoBuf tempInfo;
+			r=((DPowerResourceController*)iPddPtr)->GetResourceInfo(ClientHandle(),resourceId,&resCtrlInfo);
+			if(r==KErrNone)
+				{
+				// Copy the client buffer to tempInfo so that its size can be determined
+				// by ExtractResourceInfo
+				r=ExtractResourceInfo(&(resCtrlInfo()), tempInfo);
+				}			
+			if(r==KErrNone)
+				{
+				// Write the resources' info to the client thread
+				*(TResourceInfoBuf*)a2 = tempInfo;
+				}
+			break;
+			}
+
+
+		case RBusDevResManUs::ECancelChangeResourceStateRequests:
+		case RBusDevResManUs::ECancelGetResourceStateRequests:
+		case RBusDevResManUs::ECancelChangeNotificationRequests:
+			{
+			TUint resourceId = (TUint)a1;
+			TTrackingControl*tracker=MapRequestToTracker(aFunction);
+			r=CancelTrackerRequests(tracker, ETrue, resourceId, NULL);
+			if(r==KErrCancel)
+				r=KErrNone;	// All cancellations were successful
+			break;
+			}
+
+		case RBusDevResManUs::ECancelChangeResourceState:
+		case RBusDevResManUs::ECancelGetResourceState:
+		case RBusDevResManUs::ECancelRequestChangeNotification:
+			{
+			TRequestStatus* status = (TRequestStatus*)a1;
+			r=CancelRequestsOfType(aFunction, status);
+			break;
+			}
+
+
+#ifdef RESOURCE_MANAGER_SIMULATED_PSL
+		case RBusDevResManUs::EGetNumCandidateAsyncResources:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetNumCandidateAsyncResources"));
+			TUint numResources;
+			GetNumCandidateAsyncResources(numResources);
+			// Write the result to the client thread
+			*(TUint*)a1 = numResources;
+			break;
+			}
+		case RBusDevResManUs::EGetCandidateAsyncResourceId:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetCandidateAsyncResourceId"));
+			// Get the index to use
+			TUint index = (TUint)a1;
+			TUint resourceId = 0;
+			r=GetCandidateAsyncResourceId(index, resourceId);
+			if(r==KErrNone)				// Write the result to the client thread
+				*(TUint*)a2 = resourceId;
+			break;
+			}
+
+		case RBusDevResManUs::EGetNumCandidateSharedResources:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetNumCandidateSharedResources"));
+			TUint numResources;
+			GetNumCandidateSharedResources(numResources);
+			// Write the result to the client thread
+			*(TUint*)a1 = numResources;
+			break;
+			}
+		case RBusDevResManUs::EGetCandidateSharedResourceId:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetCandidateSharedResourceId"));
+			// Get the index to use
+			TUint index = (TUint)a1;
+			TUint resourceId = 0;
+			r=GetCandidateSharedResourceId(index, resourceId);
+			if(r==KErrNone)				// Write the result to the client thread
+				*(TUint*)a2 = resourceId;
+			break;
+			}
+#endif
+
+		case RBusDevResManUs::EGetResourceControllerVersion:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetResourceControllerVersion"));
+			// a1 specifies the address of the TVersion variable to be written to
+			// a2 is not used
+			TUint version;
+			if((r=((DPowerResourceController*)iPddPtr)->GetInterface(ClientHandle(), 
+																	KResManControlIoGetVersion, 
+																	(TAny*)&version,
+																	NULL, 
+																	NULL))!=KErrNone)
+				return r;
+			// Write the required information
+			*(TUint*)a1 = version;
+			break;
+			}
+		
+		case RBusDevResManUs::EGetNumDependentsForResource:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetNumDependentsForResource"));
+			// a1 specifies a pointer to the variable to be written to
+			// a2 specifies an array TUint parms[2] which contains:
+			//   - the resource ID
+			//   - flag to indicate if dependency information is to be loaded as part of this call
+			TUint *parms = (TUint*)a2;
+			TUint numDependents = 0;
+			r=((DPowerResourceController*)iPddPtr)->GetInterface(ClientHandle(), 
+																	KResManControlIoGetNumDependents,
+																	(TAny*)(parms[0]),	// Resource ID
+																	&numDependents,
+																	NULL);
+			iResDepsValid=EFalse; // The number of dependents may differ from the dependency information stored
+			if(r!=KErrNone)
+				return r;
+
+			// Load the dependency information, if required.
+			if(parms[1])
+				{
+				// The dependency information may be updated subsequent to the request for the number of dependents. In order
+				// to provide a coherent number and array of dependents, the requests for dependency information will be
+				// re-issued if the (new) number of dependents differs from that previously read.
+				TUint prevNumDeps = 0;
+				TUint newNumDeps = numDependents;
+				while((newNumDeps != prevNumDeps)&&(r == KErrNone))
+					{
+					if((r=EnsureSizeIsSufficient(iResourceDependencyIds, (TInt)(newNumDeps*sizeof(SResourceDependencyInfo))))!=KErrNone)
+						return r;
+					prevNumDeps = newNumDeps;
+					if((r=((DPowerResourceController*)iPddPtr)->GetInterface(ClientHandle(), 
+																			KResManControlIoGetDependentsId,
+																			(TAny*)(parms[0]),	// Resource ID
+																			(TAny*)(iResourceDependencyIds),
+																			(TAny*)&newNumDeps))!=KErrNone)
+						return r;
+					};
+				// Dependency information now in synch with number reported
+				numDependents = newNumDeps;
+				iNumResDepsStored = newNumDeps;
+				iResDepsValid = ETrue;
+				}
+			// Write the number of dependents to the client thread
+			*(TUint*)a1 = numDependents;
+			break;
+			}
+
+
+		case RBusDevResManUs::EGetDependentsIdForResource:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetDependentsIdForResource"));
+			// a1 specifies a pointer to the variable to hold the number of dependencies
+			// a2 specifies an array TUint parms[4] which contains:
+			//   - the resource ID
+			//   - the address of the array to write the required IDs to
+			//   - flag to indicate if dependency information is to be (re-)loaded as part of this call
+			TUint *parms = (TUint*)a2;
+			TUint numDependents = 0;
+
+			// (Re-)Load the dependency information, if required.
+			if(parms[2])
+				{
+				if((r=((DPowerResourceController*)iPddPtr)->GetInterface(ClientHandle(), 
+															KResManControlIoGetNumDependents, 
+															(TAny*)(parms[0]), 
+															(TAny*)&numDependents, 
+															NULL))!=KErrNone)
+					return r;
+
+				iResDepsValid=EFalse; // The number of dependents may differ from the dependency information stored
+				// In order to provide a coherent number and array of dependents, the requests for dependency information
+				// will be re-issued if the (new) number of dependents differs from that previously read.
+				TUint prevNumDeps = 0;
+				TUint newNumDeps = numDependents;
+				while(newNumDeps != prevNumDeps)
+					{
+					if((r=EnsureSizeIsSufficient(iResourceDependencyIds, (TInt)(newNumDeps*sizeof(SResourceDependencyInfo))))!=KErrNone)
+						return r;
+					prevNumDeps = newNumDeps;
+					if((r=((DPowerResourceController*)iPddPtr)->GetInterface(ClientHandle(), 
+																			KResManControlIoGetDependentsId,
+																			(TAny*)(parms[0]),	// Resource ID
+																			(TAny*)(iResourceDependencyIds),
+																			(TAny*)&newNumDeps))!=KErrNone)
+						return r;
+					};
+
+				// Dependency information now in synch with number reported
+				numDependents = newNumDeps;
+				iNumResDepsStored = newNumDeps;
+				iResDepsValid = ETrue;
+				}
+
+			// If iResDepsValid equals zero, the results are invalid - so return KErrNotReady.
+			if(iResDepsValid==0)
+				return KErrNotReady;
+
+			// Write the number of dependencies available to the client
+			*(TUint*)a1 = iNumResDepsStored;
+			// Write the dependencies to the client array if it is of sufficient size
+			// Copy the required dependency information to the user-supplied container.
+			parms[1] = (TUint)iResourceDependencyIds;
+			break;
+			}
+		
+		default:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl default 0x%x", aFunction));
+			r=KErrNotSupported;
+			}
+		}
+	    return(r);
+    }
+
+
+TInt DChannelResManUs::EnsureSizeIsSufficient(HBuf*& aBuffer, TInt aMinSize)
+	{
+// Utility function to ensure a buffer is of at least the minimum required size
+// If the buffer is to small, an attempt is made to increase its size.
+// If the re-sizing fails, KErrNoMemory is returned; otherwise KErrNone.
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::EnsureSizeIsSufficient"));
+
+	if(aBuffer->MaxLength() < aMinSize)
+		{
+		aBuffer = aBuffer->ReAlloc(aMinSize);
+		if(aBuffer->MaxLength() < aMinSize)
+			return KErrNoMemory; // ReAlloc failed - aBuffer is unchanged
+		}
+	aBuffer->SetLength(0);
+	return KErrNone;
+	}
+
+void DChannelResManUs::FreeTrackingBuffer(TTrackingBuffer*& aBuffer)
+	{
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DChannelResManUs::FreeTrackingBuffer"));
+	// Function invoked for to free tracking buffers from the busy to free queue of a tracking control
+	__ASSERT_ALWAYS((aBuffer!=NULL),RESMANUS_FAULT());
+	NKern::FMWait(&iBufferFastMutex);
+	TTrackingControl* tracker = aBuffer->GetTrackingControl();
+	SDblQue* bufQue = aBuffer->GetQue();
+
+	__ASSERT_ALWAYS(((tracker!=NULL)&&(bufQue!=NULL)),RESMANUS_FAULT());
+
+	// Check that the buffer is still in the busy queue of the tracker - exit if not
+	if(bufQue == tracker->iBusyQue)
+		{
+		aBuffer->Deque();
+		tracker->iFreeQue->Add(aBuffer);
+		aBuffer->SetQue(tracker->iFreeQue);
+		}
+	NKern::FMSignal(&iBufferFastMutex);	
+	}
+
+
+TInt DChannelResManUs::GetAndInitTrackingBuffer(TTrackingControl*& aTracker, TTrackingBuffer*& aBuffer, TUint aResourceId, TRequestStatus* aStatus)
+	{
+// Utility function - perform the necessary processing to get a buffer to support
+// asynchronous requests to change the state of a resource
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::GetAndInitTrackingBuffer"));
+	TInt r=KErrNone;
+	NKern::FMWait(&iBufferFastMutex);
+	if(aTracker->iFreeQue->IsEmpty())
+		r = KErrUnderflow;
+	else
+		{
+		// Need intermediate cast from SDblQueLink* to TAny* before TTrackingBuffer*
+		TAny* ptr = (TAny*)(aTracker->iFreeQue->GetFirst());
+		aBuffer = (TTrackingBuffer*)ptr;
+		aTracker->iBusyQue->Add((SDblQueLink*)ptr);
+		aBuffer->SetQue(aTracker->iBusyQue);
+		aBuffer->SetResourceId(aResourceId);
+		TClientRequest* request;
+		TTrackingControl* tracker = aBuffer->GetTrackingControl();
+		GET_USER_REQUEST(request, aBuffer, tracker->iType);
+		request->Reset();
+		request->SetStatus(aStatus);
+		}
+	NKern::FMSignal(&iBufferFastMutex);	
+	return r;
+	}
+
+TInt DChannelResManUs::GetStateBuffer(TTrackingControl*& aTracker, TTrackingBuffer*& aBuffer, TUint aResourceId, TInt* aState, TInt* aLevelOwnerPtr, TPowerResourceCb*& aCb, TRequestStatus* aStatus)
+	{
+// Utility function - perform the necessary processing to get a buffer and control block
+// to support asynchronous requests to change the state of a resource
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::GetStateBuffer"));
+
+	TInt r=GetAndInitTrackingBuffer(aTracker, aBuffer, aResourceId, aStatus);
+	if(r==KErrNone)
+		{
+		TTrackGetStateBuf* stateBuf = (TTrackGetStateBuf*)aBuffer;
+		stateBuf->iRequest->SetDestPtr1(aState);
+		stateBuf->iRequest->SetDestPtr2(aLevelOwnerPtr);
+		// Use placement new to update the content of the TPowerResourceCb
+		aCb = &(stateBuf->iCtrlBlock);
+		new (aCb) TPowerResourceCb(&AsyncCallBackFn,(TAny*)aBuffer,iDfcQ,KResManCallBackPriority);
+		}
+	return r;
+	}
+
+
+#ifdef _DUMP_TRACKERS
+TInt DChannelResManUs::DumpTracker(TTrackingControl* aTracker)
+	{
+	Kern::Printf("\nDChannelResManUs::DumpTracker");
+	Kern::Printf("Tracker at 0x%x\n",aTracker);
+	if(NULL==aTracker)
+		return KErrGeneral;
+	Kern::Printf("iType=%d",aTracker->iType);
+	switch(aTracker->iType)
+		{
+		case 0:
+			Kern::Printf("= GetState tracker\n");
+		break;
+		case 1:
+			Kern::Printf("= SetState tracker\n");
+		break;
+		case 2:
+			Kern::Printf("= Notify tracker\n");
+		break;
+		}
+	Kern::Printf("iOwningChannel at 0x%x\n",aTracker->iOwningChannel);
+	Kern::Printf("iFreeQue at 0x%x\n",aTracker->iFreeQue);
+	SDblQueLink* buf;
+	if(aTracker->iFreeQue!=NULL)
+		{
+		buf=aTracker->iFreeQue->First();
+		while(buf!=aTracker->iFreeQue->Last())
+			{
+			Kern::Printf("iFreeQue buffer at 0x%x\n",buf);
+			TAny* intermediatePtr = (TAny*)buf;
+			if((aTracker->iType == EGetState)||(aTracker->iType == ESetState))
+				{
+				TTrackStateBuf* tempBuf =(TTrackStateBuf*)intermediatePtr;
+				Kern::Printf("buffer control block at 0x%x\n",tempBuf->iCtrlBlock);
+				}
+			buf= buf->iNext;
+			};
+		}
+	Kern::Printf("iBusyQue at 0x%x\n",aTracker->iBusyQue);
+	if(aTracker->iBusyQue!=NULL)
+		{
+		buf=aTracker->iBusyQue->First();
+		while(buf!=aTracker->iBusyQue->Last())
+			{
+			Kern::Printf("iBusyQue buffer at 0x%x\n",buf);
+			TAny* intermediatePtr = (TAny*)buf;
+			if((aTracker->iType == EGetState)||(aTracker->iType == ESetState))
+				{
+				TTrackStateBuf* tempBuf =(TTrackStateBuf*)intermediatePtr;
+				Kern::Printf("buffer control block at 0x%x\n",tempBuf->iCtrlBlock);
+				}
+			buf= buf->iNext;
+			};
+		}
+
+	return KErrNone;
+	}
+#endif
+
+TInt DChannelResManUs::InitTrackingControl(TTrackingControl*& aTracker, TUint8 aType, TUint8 aNumBuffers)
+	{
+// Set the tracker type, create the tracking queues and required tracking buffers.
+// Assign all the tracking buffers to the free queue.
+//
+    __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::InitTrackingControl()"));
+
+	TInt r = KErrNone;
+	aTracker->iType = (TAsyncOpType)aType;
+	aTracker->iOwningChannel = this;
+	aTracker->iFreeQue = new SDblQue();
+	__ASSERT_DEBUG(aTracker->iFreeQue != NULL, RESMANUS_FAULT());
+	if(aTracker->iFreeQue == NULL)
+		r = KErrNoMemory;
+	if(r==KErrNone)
+		{
+		aTracker->iBusyQue = new SDblQue();
+		__ASSERT_DEBUG(aTracker->iBusyQue != NULL, RESMANUS_FAULT());
+		if(aTracker->iBusyQue == NULL)
+			{
+			delete aTracker->iFreeQue;
+			r = KErrNoMemory;
+			}
+		}
+	if(r==KErrNone)
+		{
+		for(TUint8 i=0; (i<aNumBuffers) && (r==KErrNone) ;i++)
+			{
+			TAny* buf = NULL;
+			TAny* ptr=NULL; // To be assigned to non-NULL value later
+			switch(aTracker->iType)
+				{
+				case EGetState:
+					{
+					buf = (TAny*)(new TTrackGetStateBuf(&AsyncCallBackFn,ptr,iDfcQ,KResManCallBackPriority));
+					r = Kern::CreateClientDataRequest2(((TTrackGetStateBuf*)buf)->iRequest);
+					break;
+					}
+				case ESetState:
+					{
+					buf = (TAny*)(new TTrackSetStateBuf(&AsyncCallBackFn, ptr, iDfcQ, KResManCallBackPriority));
+					r = Kern::CreateClientRequest(((TTrackSetStateBuf*)buf)->iRequest);
+					break;
+					}
+				case ENotify:
+					{
+					buf = (TAny*)(new TTrackNotifyBuf(&AsyncCallBackFn,ptr,iDfcQ,KResManCallBackPriority));
+					r = Kern::CreateClientRequest(((TTrackNotifyBuf*)buf)->iRequest);
+					break;
+					}
+				default:
+					__ASSERT_ALWAYS(0,RESMANUS_FAULT());
+				}
+			__ASSERT_DEBUG(buf!=NULL, RESMANUS_FAULT());
+			if((buf == NULL) || (r == KErrNoMemory))
+				{
+				r = KErrNoMemory;
+				break;
+				}
+			else
+				{
+				((TTrackingBuffer*)buf)->SetTrackingControl(aTracker);
+				(aTracker->iFreeQue)->Add((SDblQueLink*)buf);
+				((TTrackingBuffer*)buf)->SetQue(aTracker->iFreeQue);
+				}
+			}
+		// If buffer allocation failed, need to remove all previously-allocated buffers and the queues
+		if(r!=KErrNone)
+			{
+			SDblQueLink* ptr = (aTracker->iFreeQue)->First();
+			do
+				{
+				SDblQueLink* next = NULL;
+				if(ptr !=NULL)
+					next = ptr->iNext;
+				delete ptr;
+				ptr = next;
+				} while ((ptr!=NULL)&&(ptr!=(aTracker->iFreeQue)->Last()));
+			delete aTracker->iFreeQue;
+			delete aTracker->iBusyQue;
+			}
+		}
+	return r;
+	}
+
+
+void DChannelResManUs::RemoveTrackingControl(TTrackingControl*& aTracker)
+    {
+    __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::RemoveTrackingControl()"));
+
+	// Free the resource-tracking links and their respective queues
+	TAny* buf;
+	if(aTracker->iFreeQue!=NULL)
+		{
+		while(!aTracker->iFreeQue->IsEmpty())
+			{
+			buf = (TAny*)(aTracker->iFreeQue->GetFirst()); // Dequeues the element
+			delete buf;
+			}
+		delete aTracker->iFreeQue;
+		}
+
+	if(aTracker->iBusyQue!=NULL)
+		{
+		while(!aTracker->iBusyQue->IsEmpty())
+			{
+			buf = (TAny*)(aTracker->iBusyQue->GetFirst()); // Dequeues the element
+			delete buf;
+			}
+		delete aTracker->iBusyQue;
+		}
+	delete aTracker;
+    }
+
+
+#ifdef RESOURCE_MANAGER_SIMULATED_PSL
+void DChannelResManUs::CheckForCandidateAsyncResource(TPowerResourceInfoV01* aResource)
+	{
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::CheckForCandidateAsyncResource"));
+	// Proceed only if we already have less that the maximum number of candidate resources
+	if(iNoCandidateAsyncRes >= MAX_NUM_CANDIDATE_RESOURCES)
+		return;
+	// For the purposes of asynchronous testing, we need a long latency resource
+	if(((TInt)(aResource->iLatencyGet)==(TInt)(EResLongLatency)) && 
+		((TInt)(aResource->iLatencySet)==(TInt)(EResLongLatency)))
+		{
+		// An additional requirement is that the level of the resource can be 
+		// updated a sufficient amount of times to support the required testing.
+		if(((aResource->iMaxLevel - aResource->iMinLevel) > LEVEL_GAP_REQUIRED_FOR_ASYNC_TESTING) &&
+			((TInt)(aResource->iSense) == (TInt)(EResPositive)) )
+			{
+			TInt r=((DPowerResourceController*)iPddPtr)->GetResourceId(ClientHandle(), *(aResource->iResourceName), iCandidateAsyncResIds[iNoCandidateAsyncRes]);
+			if(r!=KErrNone)
+				{
+				__KTRACE_OPT(KRESMANAGER, Kern::Printf("Failed to identify long latency resource\n"));
+				}
+			else
+				{
+				__KTRACE_OPT(KRESMANAGER, Kern::Printf("Potential async resource ID = %d\n",iCandidateAsyncResIds[iNoCandidateAsyncRes]));
+				iHaveLongLatencyResource = ETrue;
+				++iNoCandidateAsyncRes;
+				}
+			}
+		}
+	}
+
+
+void DChannelResManUs::GetNumCandidateAsyncResources(TUint& aNumResources)
+	{
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::GetNumCandidateAsyncResources"));
+
+	aNumResources = iNoCandidateAsyncRes;
+	}
+
+TInt DChannelResManUs::GetCandidateAsyncResourceId(TUint aIndex, TUint& aResourceId)
+	{
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::GetCandidateAsyncResourceId"));
+	TInt r = KErrNone;
+	if(aIndex>=iNoCandidateAsyncRes)
+		r = KErrNotFound;
+	else
+		aResourceId = iCandidateAsyncResIds[aIndex];
+	return r;
+	}
+
+void DChannelResManUs::CheckForCandidateSharedResource(TPowerResourceInfoV01* aResource)
+	{
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::CheckForCandidateSharedResource"));
+
+	// Proceed only if we already have less that the maximum number of candidate resources
+	if(iNoCandidateSharedRes >= MAX_NUM_CANDIDATE_RESOURCES)
+		return;
+
+	// For the purposes of testing shared usgae of resources, we need a shareable resource
+	if((TInt)(aResource->iUsage)==(TInt)(EResShared))
+		{
+		// An additional requirement is that the level of the resource can be 
+		// updated a sufficient amount of times to support the required testing.
+		if(((aResource->iMaxLevel - aResource->iMinLevel) > LEVEL_GAP_REQUIRED_FOR_SHARED_TESTING) &&
+			((TInt)(aResource->iSense) == (TInt)(EResPositive)) )
+			{
+			TInt r=((DPowerResourceController*)iPddPtr)->GetResourceId(ClientHandle(), *(aResource->iResourceName), iCandidateSharedResIds[iNoCandidateSharedRes]);
+			if(r!=KErrNone)
+				{
+				__KTRACE_OPT(KRESMANAGER, Kern::Printf("Failed to identify shared resource\n"));
+				}
+			else
+				{
+				__KTRACE_OPT(KRESMANAGER, Kern::Printf("Potential shared resource ID = %d\n",iCandidateSharedResIds[iNoCandidateAsyncRes]));
+				iHaveLongLatencyResource = ETrue;
+				++iNoCandidateSharedRes;
+				}
+			}
+		}
+	}
+
+void DChannelResManUs::GetNumCandidateSharedResources(TUint& aNumResources)
+	{
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::GetNumCandidateSharedResources"));
+
+	aNumResources = iNoCandidateSharedRes;
+	}
+
+TInt DChannelResManUs::GetCandidateSharedResourceId(TUint aIndex, TUint& aResourceId)
+	{
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::GetCandidateSharedResourceId"));
+	TInt r = KErrNone;
+	if(aIndex>=iNoCandidateSharedRes)
+		r = KErrNotFound;
+	else
+		aResourceId = iCandidateSharedResIds[aIndex];
+	return r;
+	}
+
+#endif
+
+TInt DChannelResManUs::ExtractResourceInfo(const TPowerResourceInfoV01* aPwrResInfo, TResourceInfoBuf& aInfo)
+	{
+// Extract data from a TPowerResourceInfoV01 object to a TResourceInfo instance
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::ExtractResourceInfo"));
+
+	TInt r=KErrNone;
+	TInt copyLength=(((aInfo().iName).MaxLength())<((aPwrResInfo->iResourceName)->Length()))?
+					(aInfo().iName).MaxLength():
+					(aPwrResInfo->iResourceName)->Length();
+	(aInfo().iName).Copy((aPwrResInfo->iResourceName)->Ptr(),copyLength);
+	aInfo().iId = aPwrResInfo->iResourceId;
+	aInfo().iClass	= (TResourceClass)aPwrResInfo->iClass;
+	aInfo().iType	= (TResourceType)aPwrResInfo->iType;
+	aInfo().iUsage	= (TResourceUsage)aPwrResInfo->iUsage;
+	aInfo().iSense	= (TResourceSense)aPwrResInfo->iSense;
+	aInfo().iMinLevel = aPwrResInfo->iMinLevel;
+	aInfo().iMaxLevel = aPwrResInfo->iMaxLevel;
+
+#ifdef _DUMP_TRACKERS
+	r=DumpResource(aPwrResInfo);
+#endif
+	return r;
+	}
+
+#ifdef _DUMP_TRACKERS
+TInt DChannelResManUs::DumpResource(const TPowerResourceInfoV01* aResource)
+	{
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::DumpResource"));
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("Resource name = %S \n",aResource->iResourceName));
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("Resource ID = 0x%d \n",aResource->iResourceId));
+	switch(aResource->iClass)
+		{
+		case DStaticPowerResource::EPhysical:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("class = EPhysical\n"));
+			break;
+			}
+		case DStaticPowerResource::ELogical:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("class = ELogical\n"));
+			break;
+			}
+		default:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("class = % is UNKNOWN!\n"));
+			return KErrGeneral;
+			}
+		}
+	switch(aResource->iType)
+		{
+		case DStaticPowerResource::EBinary:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("type = EBinary\n"));
+			break;
+			}
+		case DStaticPowerResource::EMultilevel:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("type = EMultilevel\n"));
+			break;
+			}
+		case DStaticPowerResource::EMultiProperty:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("type = EMultiProperty\n"));
+			break;
+			}
+		default:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("type = % is UNKNOWN!\n"));
+			return KErrGeneral;
+			}
+		}
+	switch(aResource->iUsage)
+		{
+		case DStaticPowerResource::ESingleUse:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("usage = ESingleUse\n"));
+			break;
+			}
+		case DStaticPowerResource::EShared:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("usage = EShared\n"));
+			break;
+			}
+		default:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("usage = % is UNKNOWN!\n"));
+			return KErrGeneral;
+			}
+		}
+	switch(aResource->iSense)
+		{
+		case DStaticPowerResource::EPositive:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("sense = EPositive\n"));
+			break;
+			}
+		case DStaticPowerResource::ENegative:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("sense = ENegative\n"));
+			break;
+			}
+		case DStaticPowerResource::ECustom:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("sense = ECustom\n"));
+			break;
+			}
+		default:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("sense = % is UNKNOWN!\n"));
+			return KErrGeneral;
+			}
+		}
+	switch(aResource->iLatencyGet)
+		{
+		case DStaticPowerResource::EInstantaneous:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("latency get = EInstantaneous\n"));
+			break;
+			}
+		case DStaticPowerResource::ENegative:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("latency get = ELongLatency\n"));
+			break;
+			}
+		default:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("latency get = % is UNKNOWN!\n"));
+			return KErrGeneral;
+			}
+		}
+	switch(aResource->iLatencySet)
+		{
+		case DStaticPowerResource::EInstantaneous:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("latency set = EInstantaneous\n"));
+			break;
+			}
+		case DStaticPowerResource::ENegative:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("latency set = ELongLatency\n"));
+			break;
+			}
+		default:
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("latency set = % is UNKNOWN!\n"));
+			return KErrGeneral;
+			}
+		}
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("DefaultLevel = %d\n",aResource->iDefaultLevel));
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("MinLevel = %d\n",aResource->iMinLevel));
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("MaxLevel = %d\n",aResource->iMaxLevel));
+
+	return KErrNone;
+	}
+#endif
+
+#ifndef RESOURCE_MANAGER_SIMULATED_PSL
+DECLARE_EXTENSION_LDD()
+	{
+	return new DDeviceResManUs;
+	}
+
+
+DECLARE_STANDARD_EXTENSION()
+	{
+	DDeviceResManUs* device = new DDeviceResManUs;
+	__KTRACE_OPT(KBOOT, Kern::Printf("DECLARE_STANDARD_EXTENSION, device = 0x%x\n",device));
+
+	if(device == NULL)
+		return KErrNoMemory;
+	else
+		{
+		device->iSharedDfcQue = new TDfcQue();
+		if(device->iSharedDfcQue==NULL)
+			return KErrNoMemory;
+
+		return (Kern::InstallLogicalDevice(device));
+		}
+	}
+#else
+DECLARE_STANDARD_LDD()
+	{
+	TInt r = DSimulatedPowerResourceController::CompleteResourceControllerInitialisation();
+	if(r != KErrNone)
+		{
+		// Unconditionally print message 
+		__KTRACE_OPT(KRESMANAGER, Kern::Printf("DECLARE_STANDARD_LDD: initialise Resource Controller failed with %d\n",r));
+		return NULL;
+		}
+	DDeviceResManUs* device = new DDeviceResManUs;
+	return device;
+	}
+#endif