os/kernelhwsrv/kernel/eka/drivers/resourceman/resourcecontrol.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32\drivers\resourceman\resourcecontrol.cpp
    15 // 
    16 //
    17 
    18 #include <drivers/resourcecontrol.h>
    19 #include <drivers/resourcecontrol_trace.h>
    20 #ifdef DEBUG_VERSION
    21 #define GET_CRITICAL_SECTION_COUNT				\
    22 	DThread& thread = Kern::CurrentThread();	\
    23 	TInt CsCount = thread.iNThread.iCsCount;
    24 
    25 #define LOCK_AND_CRITICAL_SECTION_COUNT_CHECK						\
    26 	if(thread.iNThread.iCsCount != CsCount)							\
    27 		Kern::Fault("PowerResourceController CScount", __LINE__);	\
    28 	if(PowerResourceController->iResourceMutex->iHoldCount != 0)	\
    29 		Kern::Fault("PowerResourceController HoldCount", __LINE__);
    30 #else
    31 #define GET_CRITICAL_SECTION_COUNT
    32 #define LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
    33 #endif
    34 
    35 /** Allow interface class to call this. */
    36 DPowerResourceController* PowerResourceController = NULL;
    37 
    38 /** Resource Controller factory class implementation */
    39 #ifdef RESOURCE_MANAGER_SIMULATED_PSL
    40 #ifndef PRM_ENABLE_EXTENDED_VERSION
    41 _LIT(KPddName,"resourcecontroller.pdd");
    42 #else
    43 _LIT(KPddName, "resourcecontrollerextended.pdd");
    44 #endif
    45 #else
    46 #ifndef PRM_ENABLE_EXTENDED_VERSION
    47 _LIT(KPddName, "resman.pdd");
    48 #else
    49 _LIT(KPddName, "resmanextended.pdd");
    50 #endif
    51 #endif
    52 
    53 /** Factory class constructor */
    54 DResConPddFactory::DResConPddFactory()
    55 	{
    56     //Set Version number
    57     iVersion = DResConPddFactory::VersionRequired();
    58 	}
    59 
    60 TInt DResConPddFactory::Install()
    61     {
    62     // Set a Name for Resource Controller Factory class object.
    63     return(SetName(&KPddName));
    64     }
    65 
    66 /**  Called by the kernel's device driver framework to create a Physical Channel. */
    67 TInt DResConPddFactory::Create(DBase*& aChannel, TInt /*aUint*/, const TDesC8* /*anInfo*/, const TVersion& /*aVer*/)
    68     {
    69     //Create new interface for each channel.
    70 	DUserSideProxyInterface *pI = new (DUserSideProxyInterface);
    71 	if(!pI)
    72 		return KErrNoMemory;
    73 	pI->iController = PowerResourceController; //Store the resource controller. 
    74 	aChannel = (DBase*)pI;
    75     return KErrNone;
    76     }
    77 
    78 /**  Called by the kernel's device driver framework to check if this PDD is suitable for use with a Logical Channel.*/
    79 TInt DResConPddFactory::Validate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
    80     {
    81    	if (!Kern::QueryVersionSupported(DResConPddFactory::VersionRequired(),aVer))
    82 		return(KErrNotSupported);
    83     return KErrNone;
    84     }
    85 
    86 /** Return the driver capabilities */
    87 void DResConPddFactory::GetCaps(TDes8& aDes) const
    88     {
    89 	// Create a capabilities object
    90 	TCaps caps;
    91 	caps.iVersion = iVersion;
    92 	// Zero the buffer
    93 	TInt maxLen = aDes.MaxLength();
    94 	aDes.FillZ(maxLen);
    95 	// Copy cpabilities
    96 	TInt size=sizeof(caps);
    97 	if(size>maxLen)
    98 	   size=maxLen;
    99 	aDes.Copy((TUint8*)&caps,size);
   100     }
   101 
   102 /** Entry point for a standard physical device driver (PDD) that is also an extension */
   103 #ifndef RESOURCE_MANAGER_SIMULATED_PSL
   104 DECLARE_EXTENSION_PDD()
   105     {
   106     return new DResConPddFactory;
   107     }
   108 #endif
   109 
   110 /** Interface class implementation */
   111 TInt TInterface::RegisterClient(TUint& aClientId, const TDesC8& aName, TOwnerType aType)
   112     {
   113 	GET_CRITICAL_SECTION_COUNT
   114 	TInt r;
   115     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::RegisterClient"));
   116 	r = PowerResourceController->RegisterClient(aClientId, aName, aType);
   117 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
   118 	return r;
   119     }
   120  
   121 TInt TInterface::DeRegisterClient(TUint aClientId)
   122     {
   123 	GET_CRITICAL_SECTION_COUNT
   124 	TInt r;
   125     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::DeRegisterClient"));
   126 	r = PowerResourceController->DeRegisterClient(aClientId);
   127 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
   128 	return r;
   129     }
   130 
   131 TInt TInterface::GetClientName(TUint aClientId, TUint aTargetClientId, TDes8& aName)
   132     {
   133 	GET_CRITICAL_SECTION_COUNT
   134 	TInt r;
   135     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetClientName"));
   136 	r = PowerResourceController->GetClientName(aClientId, aTargetClientId, aName);
   137 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
   138 	return r;
   139     }
   140 
   141 TInt TInterface::GetClientId(TUint aClientId, TDesC8& aClientName, TUint& aTargetClientId)
   142     {
   143 	GET_CRITICAL_SECTION_COUNT
   144 	TInt r;
   145     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetClientId"));
   146 	r = PowerResourceController->GetClientId(aClientId, aClientName, aTargetClientId);
   147 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
   148 	return r;
   149     }
   150 
   151 TInt TInterface::GetResourceId(TUint aClientId, TDesC8& aResourceName, TUint& aResourceId)
   152     {
   153 	GET_CRITICAL_SECTION_COUNT
   154 	TInt r;
   155     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetResourceId"));
   156 	r = PowerResourceController->GetResourceId(aClientId, aResourceName, aResourceId);
   157 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
   158 	return r;
   159     }
   160 
   161 TInt TInterface::GetResourceInfo(TUint aClientId, TUint aResourceId, TAny* aInfo)
   162     {
   163 	GET_CRITICAL_SECTION_COUNT
   164 	TInt r;
   165     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetResourceInfo"));
   166 	r = PowerResourceController->GetResourceInfo(aClientId, aResourceId, aInfo);
   167 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
   168 	return r;
   169     }
   170 
   171 TInt TInterface::GetNumResourcesInUseByClient(TUint aClientId, TUint aTargetClientId, TUint& aNumResource)
   172     {
   173 	GET_CRITICAL_SECTION_COUNT
   174 	TInt r;
   175     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetNumResourcesInUseByClient"));
   176 	r = PowerResourceController->GetNumResourcesInUseByClient(aClientId, aTargetClientId, aNumResource);
   177 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
   178 	return r;
   179     }
   180 
   181 TInt TInterface::GetInfoOnResourcesInUseByClient(TUint aClientId, TUint aTargetClientId, TUint& aNumResources, TAny* aInfo)
   182     {
   183 	GET_CRITICAL_SECTION_COUNT
   184 	TInt r;
   185     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetInfoOnResourcesInUseByClient"));
   186 	r = PowerResourceController->GetInfoOnResourcesInUseByClient(aClientId, aTargetClientId, aNumResources, aInfo);
   187 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
   188 	return r;
   189     }
   190 
   191 TInt TInterface::GetNumClientsUsingResource(TUint aClientId, TUint aResourceId, TUint& aNumClients)
   192     {
   193 	GET_CRITICAL_SECTION_COUNT
   194 	TInt r;
   195     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetNumClientsUsingResource"));
   196 	r = PowerResourceController->GetNumClientsUsingResource(aClientId, aResourceId, aNumClients);
   197 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
   198 	return r;
   199     }
   200 
   201 TInt TInterface::GetInfoOnClientsUsingResource(TUint aClientId, TUint aResourceId, TUint& aNumClients, TAny* aInfo)
   202     {
   203 	GET_CRITICAL_SECTION_COUNT
   204 	TInt r;
   205     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetInfoOnClientsUsingResource"));
   206 	r = PowerResourceController->GetInfoOnClientsUsingResource(aClientId, aResourceId, aNumClients, aInfo);
   207 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
   208 	return r;
   209     }
   210 
   211 TInt TInterface::ChangeResourceState(TUint aClientId, TUint aResourceId, TInt aNewState, TPowerResourceCb* aCb)
   212     {
   213 	GET_CRITICAL_SECTION_COUNT
   214 	TInt r;
   215     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::ChangeResourceState"));
   216 	r = PowerResourceController->ChangeResourceState(aClientId, aResourceId, aNewState, aCb);
   217 	if(!aCb) //Not checking incase of asynchronous function as mutex might be held in RC thread, when this is checked.
   218 		{
   219 		LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
   220 		}
   221 	return r;
   222     }
   223 
   224 TInt TInterface::GetResourceState(TUint aClientId, TUint aResourceId, TBool aCached, TInt& aState, TInt& aLevelOwnerId)
   225     {
   226 	GET_CRITICAL_SECTION_COUNT
   227 	TInt r;
   228     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetResourceState"));
   229     r = PowerResourceController->GetResourceState(aClientId, aResourceId, aCached, aState, aLevelOwnerId);
   230 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
   231 	return r;
   232     }
   233 
   234 TInt TInterface::GetResourceState(TUint aClientId, TUint aResourceId, TBool aCached, TPowerResourceCb& aCb)
   235     {
   236 	TInt r;
   237     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetResourceState"));
   238     r = PowerResourceController->GetResourceState(aClientId, aResourceId, aCached, aCb);
   239 	return r;
   240     }
   241 
   242 TInt TInterface::CancelAsyncRequestCallBack(TUint aClientId, TUint aResourceId, TPowerResourceCb& aCb)
   243     {
   244 	GET_CRITICAL_SECTION_COUNT
   245 	TInt r;
   246     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::CancelAsyncRequestCallback"));
   247     r = PowerResourceController->CancelAsyncRequestCallBack(aClientId, aResourceId, aCb);
   248 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
   249 	return r;
   250     }
   251 
   252 TInt TInterface::RequestNotification(TUint aClientId, TUint aResourceId, DPowerResourceNotification& aN)
   253     {
   254 	GET_CRITICAL_SECTION_COUNT
   255 	TInt r;
   256     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::RequestNotification"));
   257     r = PowerResourceController->RequestNotification(aClientId, aResourceId, aN);
   258 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
   259 	return r;
   260     }
   261 
   262 TInt TInterface::RequestNotification(TUint aClientId, TUint aResourceId, DPowerResourceNotification& aN, TInt aThreshold, 
   263 									                                                               TBool aDirection)
   264     {
   265 	GET_CRITICAL_SECTION_COUNT
   266 	TInt r;
   267     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::RequestNotification"));
   268     r = PowerResourceController->RequestNotification(aClientId, aResourceId, aN, aThreshold, aDirection);
   269 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
   270 	return r;
   271     }
   272 
   273 TInt TInterface::CancelNotification(TUint aClientId, TUint aResourceId, DPowerResourceNotification& aN)
   274     {
   275 	GET_CRITICAL_SECTION_COUNT
   276 	TInt r;
   277     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::CancelNotification"));
   278     r = PowerResourceController->CancelNotification(aClientId, aResourceId, aN);
   279 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
   280 	return r;
   281     }
   282 
   283 TInt TInterface::DeRegisterClientLevelFromResource(TUint aClientId, TUint aResourceId)
   284 	{
   285 	GET_CRITICAL_SECTION_COUNT
   286 	TInt r;
   287     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::DeRegisterClientLevelFromResource"));
   288     r = PowerResourceController->DeRegisterClientLevelFromResource(aClientId, aResourceId);
   289 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
   290 	return r;
   291     }
   292 
   293 TInt TInterface::AllocReserve(TUint aClientId, TUint8 aNumCl, TUint8 aNumRm)
   294     {
   295 	GET_CRITICAL_SECTION_COUNT
   296 	TInt r;
   297     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::AllocReserve"));
   298     r = PowerResourceController->AllocReserve(aClientId, aNumCl, aNumRm);
   299 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
   300 	return r;
   301     }
   302 
   303 /** This function is used by export functions of Resource contoller defined in seperate file */
   304 DPowerResourceController* TInterface::GetPowerResourceController(void)
   305     {
   306     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetPowerResourceController"));
   307     return PowerResourceController;
   308     }
   309 
   310 TInt TInterface::ControlIO(TUint aClientId, TUint aFunction, TAny* aParam1, TAny* aParam2, TAny* aParam3)
   311     {
   312     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::ControlIO"));
   313     return PowerResourceController->GetInterface(aClientId, aFunction, aParam1, aParam2, aParam3);
   314     }
   315 
   316 /** Resouce controller panic */
   317 void DPowerResourceController::Panic(TUint8 aPanic)
   318 	{
   319 	Kern::Fault("Power Resource Controller", aPanic);
   320 	}
   321 
   322 /** Constructor for power controller. Creates message queue and generates ID for power controller to use. */
   323 DPowerResourceController::DPowerResourceController()
   324 	{
   325     __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::DPowerResouceController()"));
   326 	//Constructor is expected to invoke multiple times (during creation, variant init 0 and extension init 1)
   327 	if(PowerResourceController) 
   328 		return;
   329     PowerResourceController = this;
   330 	iClientList.Initialise(0);
   331 	iUserSideClientList.Initialise(0);
   332 	iInitialised = EResConCreated;
   333 #ifdef PRM_ENABLE_EXTENDED_VERSION
   334 	iDynamicResourceList.Initialise(0);
   335 	iDynamicResDependencyList.Initialise(0);
   336 #endif
   337 	}
   338 
   339 /** Destructor for power controller. Frees the memory allocated in kernel heap. */
   340 DPowerResourceController::~DPowerResourceController()
   341 	{
   342 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::~DPowerResourceController()"));
   343 #ifdef RESOURCE_MANAGER_SIMULATED_PSL
   344 	iCleanList.ResetAndDestroy();
   345 #endif
   346 	iClientList.Delete();
   347 	iUserSideClientList.Delete();
   348 
   349 
   350 		
   351 #ifdef PRM_ENABLE_EXTENDED_VERSION
   352 	iDynamicResourceList.Delete();
   353 	iDynamicResDependencyList.Delete();
   354 #endif
   355 
   356 	SPowerResourceClientLevel *pCL = iClientLevelPool;
   357 	while(iClientLevelPool) //Find the starting position of array to delete
   358 		{
   359 		if(iClientLevelPool < pCL)
   360 			pCL = iClientLevelPool;
   361 		iClientLevelPool = iClientLevelPool->iNextInList;
   362 		}
   363 	//delete pCL;
   364 	delete []pCL;
   365 	SPowerRequest *pReq = iRequestPool;
   366 	while(iRequestPool) //Find the starting position of array to delete
   367 		{
   368 		if(iRequestPool < pReq)
   369 			pReq = iRequestPool;
   370 		iRequestPool = iRequestPool->iNext;
   371 		}
   372 	//delete pR
   373 	delete []pReq;
   374 #ifdef PRM_ENABLE_EXTENDED_VERSION
   375 	pCL = iResourceLevelPool;
   376 	while(iResourceLevelPool)
   377 		{
   378 		if(iResourceLevelPool < pCL)
   379 			pCL = iResourceLevelPool;
   380 		iResourceLevelPool = iResourceLevelPool->iNextInList;
   381 		}
   382 	//delete resource pool
   383 	delete []pCL;
   384 	//delete Message Queue dependency
   385 	delete iMsgQDependency;
   386 #endif
   387 	//delete Message Queue
   388 	delete iMsgQ;
   389 	}
   390 
   391 /** Send notificatins to clients registered for it for the specified resource. */
   392 void DPowerResourceController::CompleteNotifications(TInt aClientId, DStaticPowerResource* aResource, TInt aState, 
   393 													      TInt aReturnCode, TInt aLevelOwnerId, TBool aLock)
   394 	{
   395     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::CompleteNotifications"));
   396     if(aLock)
   397 		Lock();
   398     DPowerResourceNotification*pN=NULL;
   399     for(SDblQueLink* pNL=aResource->iNotificationList.First();pNL!=&aResource->iNotificationList.iA; pNL=pNL->iNext)
   400 		{
   401         pN = _LOFF(pNL, DPowerResourceNotification, iNotificationLink);
   402 #ifdef PRM_ENABLE_EXTENDED_VERSION
   403 		//If dyanmic resource is deregistering, send notification to all clients requested for it
   404 		if((pN->iCallback.iResourceId & KIdMaskDynamic) && (aClientId == KDynamicResourceDeRegistering))
   405 			{
   406 			pN->iCallback.iResult = aReturnCode;
   407 			pN->iCallback.iLevel = aState;
   408 			pN->iCallback.iClientId = aClientId;
   409 			pN->iCallback.iLevelOwnerId = aLevelOwnerId;
   410 			__KTRACE_OPT(KRESMANAGER, Kern::Printf("Notification ClientId = 0x%x, ResourceId = %d, state = %d, Result = %d", 
   411 									pN->iCallback.iClientId, pN->iCallback.iResourceId, aState, aReturnCode));
   412 			PRM_POSTNOTIFICATION_SENT_TRACE
   413 			pN->iCallback.Enque();
   414 			continue;
   415 			}	
   416 #endif
   417 		if((pN->iType==DPowerResourceNotification::EUnconditional) || 
   418 				(pN->iDirection && ((pN->iPreviousLevel < pN->iThreshold) && (aState >= pN->iThreshold))) ||
   419 				(!pN->iDirection && ((pN->iPreviousLevel > pN->iThreshold) && (aState <= pN->iThreshold))))
   420 			{
   421             pN->iCallback.iResult=aReturnCode;
   422             pN->iCallback.iLevel=aState;
   423             pN->iCallback.iClientId = aClientId;
   424 			pN->iCallback.iLevelOwnerId = aLevelOwnerId;
   425 			__KTRACE_OPT(KRESMANAGER, Kern::Printf("Notifications ClientId = 0x%x, ResourceId = %d, State = %d, Result = %d",
   426 										pN->iCallback.iClientId, pN->iCallback.iResourceId, aState, aReturnCode));
   427 			PRM_POSTNOTIFICATION_SENT_TRACE
   428             pN->iCallback.Enque();
   429 			}
   430 		pN->iPreviousLevel = aState; //Update the state
   431 		}
   432 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::CompleteNotifications"));
   433 	if(aLock)
   434 		UnLock();
   435 	return;
   436 	}
   437 
   438 /** Complete the asynchronous request. */
   439 void DPowerResourceController::CompleteRequest(TPowerRequest& aRequest)
   440 	{
   441     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::CompleteRequest"));
   442  	// Complete notification for state change operation
   443     DStaticPowerResource* pR=aRequest.Resource();
   444 	//If request in EChange or ESetDefaultValue and no error and if shared resources and if change is done then 
   445 	//issue notification.
   446 	if(((aRequest.ReqType() == TPowerRequest::EChange) || (aRequest.ReqType() == TPowerRequest::ESetDefaultLevel)) 
   447 		         && (aRequest.ReturnCode() == KErrNone) && ((!pR->Usage()) || (pR->Usage() && aRequest.RequiresChange())))
   448 		{	
   449     	CompleteNotifications(aRequest.ClientId(), aRequest.Resource(), aRequest.Level(), 
   450 		                                                     aRequest.ReturnCode(), aRequest.ClientId());
   451 		}
   452 	//Do not update the level if the resource is shared and change is not required or any error.
   453     if(aRequest.ReturnCode()==KErrNone && ((aRequest.ReqType() ==TPowerRequest::EGet) || 
   454 		       (((aRequest.ReqType()==TPowerRequest::EChange) || (aRequest.ReqType()==TPowerRequest::ESetDefaultLevel)) 
   455 			   && ((!pR->Usage()) || (pR->Usage() && aRequest.RequiresChange())))))
   456         {
   457         Lock();
   458 		// Cache the latest value
   459         pR->iCachedLevel=aRequest.Level();
   460 		//Need to update client ID only during state change.
   461 		if(aRequest.ReqType() != TPowerRequest::EGet)
   462 			pR->iLevelOwnerId=aRequest.ClientId();
   463 		// Cache Idle list entry for this reosurce if requested.
   464         if(pR->iIdleListEntry)
   465             {
   466             SIdleResourceInfo* pI=pR->iIdleListEntry;
   467             if(aRequest.ReqType() != TPowerRequest::EGet)
   468 				pI->iLevelOwnerId= aRequest.ClientId();
   469             pI->iCurrentLevel=aRequest.Level();
   470             }
   471          UnLock();
   472         }
   473 	
   474 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::CompleteRequest"));
   475 	}
   476 
   477 /** Handle/process the asynchronous request sent to resource controller.
   478    The request can be one of the following
   479    1) State change of long latency reosurce
   480    2) Get the state of long latency resource
   481    3) Set the default value of long latency resource */
   482 void DPowerResourceController::HandleMsg(TPowerRequest& aRequest)
   483 	{
   484 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::HandleMsg"));
   485     DStaticPowerResource* pR=aRequest.Resource();
   486 	//Get client using client ID
   487 	TUint aClientId = aRequest.ClientId();
   488 	SPowerResourceClient* pC = NULL;
   489 #ifdef PRM_ENABLE_EXTENDED_VERSION
   490 	if((TInt)aClientId != KDynamicResourceDeRegistering)
   491 		{
   492 		if(aClientId & USER_SIDE_CLIENT_BIT_MASK)
   493 			pC = iUserSideClientList[TUint16(aClientId & ID_INDEX_BIT_MASK)];
   494 		else
   495 			pC = iClientList[TUint16(aClientId & ID_INDEX_BIT_MASK)];
   496 		}
   497 #else
   498 		if(aClientId & USER_SIDE_CLIENT_BIT_MASK)
   499 			pC = iUserSideClientList[TUint16(aClientId & ID_INDEX_BIT_MASK)];
   500 		else
   501 			pC = iClientList[TUint16(aClientId & ID_INDEX_BIT_MASK)];
   502 #endif		
   503 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("Request Type = %d, ClientId = 0x%x, ResourceId = %d",
   504 		                             aRequest.ReqType(), aRequest.ClientId(), aRequest.ResourceId()));
   505     if(aRequest.ReqType()==TPowerRequest::EChange)
   506 		{
   507         if(pR->Usage()) //Handling shared resource
   508 			{
   509 			Lock(); //To avoid race condition between deregister resource level.
   510 			aRequest.ReturnCode() = CheckLevelAndAddClient(pC, &aRequest);
   511 			UnLock();
   512 			if((aRequest.ReturnCode()!= KErrNone) || (!aRequest.RequiresChange()))
   513 				{
   514 				aRequest.Level() = pR->iCachedLevel; //If no change then send the current level back.
   515     			CompleteRequest(aRequest);
   516 				return;
   517 				}
   518 			}
   519 		else if(pR->iLevelOwnerId ==-1)  //No existing client.
   520 			{
   521 			// Add client Level
   522 			if(pC->iReservedCl==0 && !iClientLevelPoolCount)
   523 				{
   524 				__KTRACE_OPT(KRESMANAGER, Kern::Printf("Reserved Client Level exhausted and its free pool empty"));
   525                 aRequest.ReturnCode() = KErrUnderflow;
   526                 CompleteRequest(aRequest);
   527 				return;
   528 				}
   529 			SPowerResourceClientLevel* pSCL=NULL;
   530 			LIST_POP(iClientLevelPool, pSCL, iNextInList);
   531 			pSCL->iClientId=aClientId;
   532 			pSCL->iResourceId=aRequest.ResourceId();
   533 			pSCL->iLevel=aRequest.Level();
   534 			LIST_PUSH(pC->iLevelList, pSCL, iNextInList); //Add to client
   535 			pR->iClientList.Add(pSCL); //Add in resource
   536 			if(pC->iReservedCl==0)
   537 				{
   538 				iClientLevelPoolCount--;
   539 				pC->iUnderFlowClCount++;
   540 				}
   541             else
   542 			   pC->iReservedCl--;
   543 			}
   544 		else
   545 			{
   546 			//Update the level in the client list.
   547 			SPowerResourceClientLevel* pSCL = (SPowerResourceClientLevel*)pR->iClientList.First();
   548 			pSCL->iLevel = aRequest.Level();
   549 			}
   550 		}
   551 	else if(aRequest.ReqType()==TPowerRequest::ESetDefaultLevel)	
   552 		{
   553 #ifdef PRM_ENABLE_EXTENDED_VERSION
   554 		if((aRequest.ResourceId() & KIdMaskDynamic) && ((TInt)aClientId == KDynamicResourceDeRegistering))
   555 			{
   556 			//Try to change the resource to requested level and if that fails try to change it to default level
   557 			if(pR->iDefaultLevel != aRequest.Level())
   558 				{
   559 				aRequest.ReqType() = TPowerRequest::EChange;
   560 				aRequest.ReturnCode() = pR->DoRequest(aRequest);
   561 				if(aRequest.ReturnCode() != KErrNone)
   562 					{
   563 					aRequest.ReqType() = TPowerRequest::ESetDefaultLevel;
   564 					aRequest.Level() = pR->iDefaultLevel;
   565 					pR->DoRequest(aRequest);
   566 					}
   567 				}
   568 			else
   569 				pR->DoRequest(aRequest);
   570 			aRequest.ReturnCode() = KErrNone;
   571 			aRequest.RequiresChange() = ETrue;
   572 			CompleteRequest(aRequest);
   573 			return;
   574 			}
   575 #endif
   576         if(pR->Usage())
   577 			{
   578 			aRequest.ReturnCode() = CheckLevelAndAddClient(pC, &aRequest);
   579 			if((aRequest.ReturnCode()!= KErrNone) || (!aRequest.RequiresChange()))
   580 				{
   581 				aRequest.Level() = pR->iCachedLevel; //If no change then send the current level back.
   582     			CompleteRequest(aRequest);
   583 				return;
   584 				}
   585 			}
   586 		else
   587 			{
   588 			aRequest.ClientId() = -1;
   589 			aRequest.Level() = pR->iDefaultLevel;
   590 			}
   591 		}
   592 	if((aRequest.ReqType() == TPowerRequest::EGet) || (pR->iCachedLevel != aRequest.Level()))
   593 		aRequest.ReturnCode() = pR->DoRequest(aRequest);
   594 	CompleteRequest(aRequest);
   595 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::HandleMsg"));
   596 	}
   597 
   598 #ifdef PRM_ENABLE_EXTENDED_VERSION
   599 /** Handle/process the dependency resource.
   600    The request can be one of the following
   601    1) State change of a dependency resource
   602    2) Get the state of a dependency resource
   603    3) Set the default value of a dependency resource */
   604 void DPowerResourceController::HandleDependencyMsg(TPowerRequest& aRequest)
   605 	{
   606 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::HandleDependencyMsg"));
   607     DStaticPowerResource* pR=aRequest.Resource();
   608 	//Get client using client ID
   609 	TUint aClientId = aRequest.ClientId();
   610 	SPowerResourceClient* pC = NULL;
   611 
   612 	if((TInt)aClientId != KDynamicResourceDeRegistering)
   613 		{
   614 		if(aClientId & USER_SIDE_CLIENT_BIT_MASK)
   615 			pC = iUserSideClientList[TUint16(aClientId & ID_INDEX_BIT_MASK)];
   616 		else
   617 			pC = iClientList[TUint16(aClientId & ID_INDEX_BIT_MASK)];
   618 		}
   619 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("Request Type = %d, ClientId = 0x%x, ResourceId = %d",  
   620 		                             aRequest.ReqType(), aRequest.ClientId(), aRequest.ResourceId()));
   621 	if((aRequest.ResourceId() & KIdMaskResourceWithDependencies) && (aRequest.ReqType() != TPowerRequest::EGet))
   622 		{
   623 		Lock();
   624 		iDfcQDependencyLock = ETrue;
   625 		UnLock();
   626 		PowerResourceController->HandleDependencyResourceStateChange(pC, aRequest);
   627 		Lock();
   628 		iDfcQDependencyLock = EFalse;
   629 		UnLock();		
   630 		return;
   631 		}
   632 	//Get the resource current level.
   633 	aRequest.ReturnCode() = pR->DoRequest(aRequest);
   634 	CompleteRequest(aRequest);
   635 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::HandleDependencyMsg"));
   636 	}
   637 #endif
   638 
   639 /** Function called whenever there is a message in resource controller message queue. */
   640 void DPowerResourceController::MsgQFunc(TAny* aPtr)
   641 	{
   642     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::MsgQFunc"));
   643     DPowerResourceController* pRC=(DPowerResourceController*)aPtr;
   644     TPowerRequest* aReq=(TPowerRequest*)pRC->iMsgQ->iMessage;
   645 	DStaticPowerResource *pR = aReq->Resource();
   646 	if(aReq->ReqType() == TPowerRequest::EAllocReserve)
   647 		{
   648 		aReq->ReturnCode() = pRC->HandleReservationOfObjects(*aReq);
   649 		aReq->Complete(aReq->ReturnCode(),ETrue);
   650 		return;
   651 		}
   652 	if((aReq->ReqType() == TPowerRequest::ERegisterKernelClient) || (aReq->ReqType() == TPowerRequest::ERegisterUsersideClient))
   653 		{
   654 		aReq->ReturnCode() = pRC->HandleClientRegistration(*aReq);
   655 		aReq->Complete(aReq->ReturnCode(), ETrue);
   656 		return;
   657 		}
   658 #ifdef PRM_ENABLE_EXTENDED_VERSION
   659 	if(aReq->ReqType() == TPowerRequest::ERegisterDynamicResource)
   660 		{
   661 		aReq->ReturnCode() = pRC->HandleResourceRegistration(*aReq);
   662 		aReq->Complete(aReq->ReturnCode(), ETrue);
   663 		return;
   664 		}
   665 #endif
   666     pRC->HandleMsg(*aReq);
   667 #ifdef PRM_ENABLE_EXTENDED_VERSION
   668 	if((aReq->ResourceId() & KIdMaskDynamic) && (aReq->ResourceCb()))
   669 		{
   670 		pRC->Lock();
   671 		((DDynamicPowerResource*)aReq->Resource())->UnLock();
   672 		pRC->UnLock();
   673 		}
   674 #endif
   675 	//Below code is for Btrace
   676 #ifdef PRM_INSTRUMENTATION_MACRO
   677 	SPowerResourceClient* pC = NULL;
   678 	SPowerResourceClient tRes;
   679 #ifdef PRM_ENABLE_EXTENDED_VERSION
   680  if((aReq->ClientId() == -1) || (aReq->ClientId() == KDynamicResourceDeRegistering))
   681 #else
   682 	if(aReq->ClientId() == -1)
   683 #endif
   684 		{
   685         pC = &tRes;
   686         pC->iClientId = (TUint)-1;
   687         pC->iName = &KNoClient;
   688 		}
   689     else if(aReq->ClientId() & USER_SIDE_CLIENT_BIT_MASK)
   690 		pC = pRC->iUserSideClientList[TUint16(aReq->ClientId() & ID_INDEX_BIT_MASK)];
   691 	else
   692 		pC = pRC->iClientList[TUint16(aReq->ClientId() & ID_INDEX_BIT_MASK)];
   693 
   694     TUint aResourceId = aReq->ResourceId();
   695     TInt r = aReq->ReturnCode();
   696     if(aReq->ReqType()==TPowerRequest::EGet)
   697 		{
   698 		TInt aState = aReq->Level();
   699 		PRM_RESOURCE_GET_STATE_END_TRACE
   700 		}
   701     else
   702 		{
   703 		TInt aNewState = aReq->Level();
   704 		PRM_CLIENT_CHANGE_STATE_END_TRACE
   705 		}
   706 #endif
   707 	//Check whether callback is cancelled and if not queue the DFC.
   708     TPowerResourceCb* pCb = aReq->ResourceCb();
   709     if(pCb)
   710 		{
   711         pCb->iResult=aReq->ReturnCode();
   712         pCb->iLevel=aReq->Level();
   713         pCb->iResourceId=aReq->ResourceId();
   714         pCb->iClientId=aReq->ClientId();
   715 		pCb->iLevelOwnerId = pR->iLevelOwnerId;
   716 	    pCb->Enque();
   717 		}
   718     aReq->Complete(aReq->ReturnCode(),ETrue);
   719 	if(aReq->ResourceCb())
   720 		pRC->MoveRequestToFreePool(aReq);
   721 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::MsgQFunc"));
   722 	return;
   723     }
   724 
   725 #ifdef PRM_ENABLE_EXTENDED_VERSION
   726 /** Function called whenever there is a message in resource controller Dependency message queue. */
   727 void DPowerResourceController::MsgQDependencyFunc(TAny* aPtr)
   728 	{
   729     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::MsgQDependencyFunc"));
   730     DPowerResourceController* pRC=(DPowerResourceController*)aPtr;
   731     TPowerRequest* aReq=(TPowerRequest*)pRC->iMsgQDependency->iMessage;
   732 	DStaticPowerResource *pR = aReq->Resource();
   733 	pRC->HandleDependencyMsg(*aReq);
   734 	if((aReq->ResourceId() & KIdMaskDynamic) && (aReq->ResourceCb()))
   735 		{
   736 		pRC->Lock();
   737 		((DDynamicPowerResource*)aReq->Resource())->UnLock();
   738 		pRC->UnLock();
   739 		}
   740 	//Below code is for Btrace
   741 #ifdef PRM_INSTRUMENTATION_MACRO
   742 	SPowerResourceClient* pC = NULL;
   743 	SPowerResourceClient tRes;
   744 	if((aReq->ClientId() != -1) && (aReq->ClientId() != KDynamicResourceDeRegistering) && 
   745 		                                        (aReq->ClientId() & KIdMaskResourceWithDependencies))
   746 		{
   747 		pC = &tRes;
   748 		pC->iClientId = aReq->ClientId();
   749 		DDynamicPowerResourceD* pDRes;
   750 		if(aReq->ClientId() & KIdMaskDynamic)
   751 			pDRes = pRC->iDynamicResDependencyList[(TUint16)(aReq->ClientId() & ID_INDEX_BIT_MASK)];	
   752 		else
   753 			pDRes = (DDynamicPowerResourceD*)pRC->iStaticResDependencyArray[(aReq->ClientId() & ID_INDEX_BIT_MASK) - 1];
   754 		pC->iName = pDRes->iName;
   755 		}
   756 	else if((aReq->ClientId() == -1) || (aReq->ClientId() == KDynamicResourceDeRegistering))
   757 		{
   758         pC = &tRes;
   759         pC->iClientId = (TUint)-1;
   760         pC->iName = &KNoClient;
   761 		}
   762     else if(aReq->ClientId() & USER_SIDE_CLIENT_BIT_MASK)
   763 		pC = pRC->iUserSideClientList[TUint16(aReq->ClientId() & ID_INDEX_BIT_MASK)];
   764 	else
   765 		pC = pRC->iClientList[TUint16(aReq->ClientId() & ID_INDEX_BIT_MASK)];
   766 
   767     TUint aResourceId = aReq->ResourceId();
   768     TInt r = aReq->ReturnCode();
   769     if(aReq->ReqType()==TPowerRequest::EGet)
   770 		{
   771 		TInt aState = aReq->Level();
   772 		PRM_RESOURCE_GET_STATE_END_TRACE
   773 		}
   774     else
   775 		{
   776 		TInt aNewState = aReq->Level();
   777 		PRM_CLIENT_CHANGE_STATE_END_TRACE
   778 		}
   779 #endif
   780 	//Check whether callback is cancelled and if not queue the DFC.
   781     TPowerResourceCb* pCb = aReq->ResourceCb();
   782     if(pCb)
   783 		{
   784         pCb->iResult=aReq->ReturnCode();
   785         pCb->iLevel=aReq->Level();
   786         pCb->iResourceId=aReq->ResourceId();
   787         pCb->iClientId=aReq->ClientId();
   788 		pCb->iLevelOwnerId = pR->iLevelOwnerId;
   789 	    pCb->Enque();
   790 		}
   791     aReq->Complete(aReq->ReturnCode(),ETrue);
   792 	if(aReq->ResourceCb())
   793 		pRC->MoveRequestToFreePool(aReq);
   794 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::MsgQDependencyFunc"));
   795 	return;
   796     }
   797 #endif
   798 /** Function to move the request object to free pool and update client request count accordingly. */
   799 void DPowerResourceController::MoveRequestToFreePool(TPowerRequest *aReq)
   800 	{
   801     //Return request to free pool
   802     SPowerRequest* pS=_LOFF(aReq, SPowerRequest, iRequest);
   803     Lock();
   804     LIST_PUSH(iRequestPool, pS, iNext);
   805 	SPowerResourceClient* pC = NULL;
   806 	if(aReq->ClientId() & USER_SIDE_CLIENT_BIT_MASK)
   807 		pC = iUserSideClientList[TUint16(aReq->ClientId() & ID_INDEX_BIT_MASK)];
   808 	else
   809 		pC = iClientList[TUint16(aReq->ClientId() & ID_INDEX_BIT_MASK)];
   810 	pC->iPendingReqCount--;
   811 	if(pC->iUnderFlowRmCount > 0)
   812 		{
   813         iRequestPoolCount++;
   814         pC->iUnderFlowRmCount--;
   815 		}
   816     else
   817         pC->iReservedRm++;
   818     UnLock();
   819     return;
   820 	}
   821 
   822 /** This function is called by PSL to set the DFC queue created */
   823 void DPowerResourceController::SetDfcQ(TDfcQue* aDfcQ)
   824 	{
   825     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::SetDfcQ"));
   826     iDfcQ=aDfcQ;
   827     iMsgQ->SetDfcQ(iDfcQ);
   828 	}
   829 
   830 #ifdef PRM_ENABLE_EXTENDED_VERSION
   831 /** This function is called by PSL to set the DFC Dependency queue created */
   832 void DPowerResourceController::SetDfcQDependency(TDfcQue* aDfcQDependency)
   833 	{
   834     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::SetDfcQDependency"));
   835     iDfcQDependency=aDfcQDependency;
   836     iMsgQDependency->SetDfcQ(iDfcQDependency);
   837 	}
   838 #endif
   839 /**This is called as a result of DFC queued in supervisor thread to complete the initialisation
   840    of resource controller.It registers the resource controller with the power controller. It also
   841    calls PSL (DoInitResources()) to initialise all static resources to their post-reboot state.
   842    Finally mark resource controller as fully initialised (ready to accept state change and get request)
   843    and start the message queue if exists. */
   844 TInt DPowerResourceController::InitResources()
   845 	{
   846     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::InitResources()"));
   847 	TUint16 count;
   848 	//Create a Kernel client object for Power Controller
   849 	Lock();
   850 	SPowerResourceClient * pC = NULL;
   851 	// By now client pool should be created
   852 	LIST_POP(iClientPool, pC, iNextInList);
   853 	TUint16 growBy = iClientList.GrowBy();
   854 	if(!pC)
   855 		{
   856 		UnLock();
   857 		// coverity[alloc_fn]
   858 		SPowerResourceClient *pCL = new SPowerResourceClient[growBy];
   859 		if(!pCL)
   860 			{
   861 			__KTRACE_OPT(KRESMANAGER, Kern::Printf("No memory to grow client pool"));
   862 			Panic(ENoMemToCreatePowerControllerClient);
   863 			}
   864 #ifdef RESOURCE_MANAGER_SIMULATED_PSL
   865 		iCleanList.Append(pCL);
   866 #endif
   867 		Lock();
   868         for(count = 0; count < growBy-1; count++)
   869 			LIST_PUSH(iClientPool, &pCL[count], iNextInList);
   870 		pC = &pCL[count];
   871 #ifdef PRM_INSTRUMENTATION_MACRO
   872 	TUint size = growBy *sizeof(SPowerResourceClient);
   873 	PRM_MEMORY_USAGE_TRACE
   874 #endif
   875 		}
   876 	pC->iName = (const TDesC8*)&KPowerController;
   877 	UnLock();
   878 	if(iClientList.Allocd()==iClientList.Count())
   879 		{
   880 		if(iClientList.ReSize(growBy))
   881 			{
   882 			Panic(ENoMemToCreatePowerControllerClient);
   883 			}
   884 		}
   885 	Lock();
   886 	iClientList.Add(pC, iPowerControllerId);
   887 	pC->iClientId = iPowerControllerId | CLIENT_POWER_CONTROLLER_BIT_MASK;
   888 	iPowerControllerId = pC->iClientId;
   889     iClientCount++;
   890     if(TPowerController::PowerController())
   891        TPowerController::PowerController()->RegisterResourceController(this, iPowerControllerId);
   892 	iInitialised =EResConStartupCompleted;
   893 	UnLock();
   894 	//Check the resource for postboot level and send notifications to clients registered for it.
   895 	DStaticPowerResource *pR = NULL;
   896 	TInt r;
   897 	TPowerRequest req = TPowerRequest::Get();
   898 	//For Static resource with no dependencies
   899     for(count = 0; count< iStaticResourceArrayEntries; count++)
   900 		{
   901 		pR = iStaticResourceArray[count];
   902 		if(pR && (pR->iFlags & SET_VALID_POST_BOOT_LEVEL))
   903 			{
   904             //Form the request message
   905 			req.ReqType() = TPowerRequest::EChange;
   906 			req.ResourceId() = count+1;
   907 			req.ClientId() = -1;
   908 			req.Level() = pR->iPostBootLevel;
   909 			req.Resource() = pR;
   910 			req.ResourceCb() = NULL;
   911 			req.RequiresChange() = ETrue;
   912 			r = pR->DoRequest(req);
   913 			if(r == KErrNone)
   914 				{
   915 				CompleteNotifications(-1, pR, req.Level(), r, -1, ETrue);
   916 				pR->iCachedLevel = req.Level(); //Update the cached level.
   917 				}
   918 			}
   919 		}
   920 #ifdef PRM_ENABLE_EXTENDED_VERSION
   921 	//For Static resource with dependencies 
   922 	for(count = 0; count < iStaticResDependencyCount; count++)
   923 		{
   924 		pR = iStaticResDependencyArray[count];
   925 		if(pR->iFlags & SET_VALID_POST_BOOT_LEVEL)
   926 			{
   927 			req.ReqType() = TPowerRequest::EChange;
   928 			req.ResourceId() = ((DStaticPowerResourceD*)pR)->iResourceId;
   929 			req.ClientId() = -1;
   930 			req.Level() = pR->iPostBootLevel;
   931 			req.Resource() = pR;
   932 			req.ResourceCb() = NULL;
   933 			req.RequiresChange() = ETrue;
   934 			//Form the request message
   935 			((DStaticPowerResourceD*)pR)->HandleChangePropagation(req, EChangeStart, req.ClientId(), KNoClient);
   936 			}
   937 		}
   938 #endif
   939 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::InitResources()"));
   940     return KErrNone;
   941 	}
   942 
   943 /** @internalComponent
   944    This function is called for shared resources to determine level for the shared resource.
   945    This takes care of updating the resource level for each client. 
   946 */
   947 TInt DPowerResourceController::CheckLevelAndAddClient(SPowerResourceClient* pC, TPowerRequest* aReq)
   948 	{
   949     //Client level addition in state change needs to be taken care.
   950     __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient, ClientId = 0x%x, ResourceId = %d, ReqType = %d",
   951 													pC->iClientId, aReq->ResourceId(), aReq->ReqType()));
   952 	
   953 	SPowerResourceClientLevel* pSCL=NULL; //Place to hold the current client
   954 	SPowerResourceClientLevel* pMCL=NULL; //Place to hold the prevailing client.
   955 	DStaticPowerResource* aResource = aReq->Resource();
   956     aReq->RequiresChange() = EFalse;
   957     TInt maxLevel=KMinTInt;
   958    	TInt CurrentLevel;
   959 	TInt count = 0;
   960 	//Get the nextmaximum, current client information.If the change is requested by client holding the prevailing
   961 	//level of the resource then maxlevel will be next highest level with respect to sense. Otherwise will contain
   962 	//the maximum level.
   963 	SPowerResourceClientLevel* pL = NULL;
   964     for(SDblQueLink* pCL=aResource->iClientList.First();pCL!=&aResource->iClientList.iA;pCL=pCL->iNext,count++)
   965 		{
   966         pL=(SPowerResourceClientLevel*)pCL;
   967 		if(pL->iClientId == pC->iClientId)
   968 			{
   969 			pSCL=pL;
   970 			if(aResource->Sense() == DStaticPowerResource::ECustom)
   971 				break;
   972 			continue;
   973 			}
   974 		
   975 		if((count == 0) || ((pSCL != NULL) && (maxLevel == KMinTInt)))
   976 			{
   977 			maxLevel = pL->iLevel;
   978 			pMCL = pL;
   979 			continue;
   980 			}
   981 		if(((aResource->Sense() == DStaticPowerResource::ENegative) && (pL->iLevel < maxLevel)) || 
   982 			                      ((aResource->Sense() == DStaticPowerResource::EPositive) && (pL->iLevel > maxLevel)))
   983 			{
   984 			maxLevel=pL->iLevel;
   985 			pMCL = pL;
   986 		    }
   987 		}
   988 	//Get the current level.
   989 	if(((TInt)pC->iClientId == aResource->iLevelOwnerId))
   990 		// coverity[var_deref_op]
   991 		CurrentLevel = pSCL->iLevel;
   992     else
   993 		CurrentLevel = maxLevel;
   994 
   995 #ifdef PRM_ENABLE_EXTENDED_VERSION
   996 	if(aResource->iLevelOwnerId & KIdMaskResourceWithDependencies)
   997 		{
   998 		CurrentLevel = aResource->iCachedLevel;
   999 		}
  1000 #endif
  1001 	TBool newClient = EFalse;
  1002     if(!pSCL)
  1003 		{
  1004 		// If the client is new, get free client level from pool and populate with client information
  1005 		// and add it to the client list and in resource list.
  1006         if((pC->iReservedCl ==0) && !iClientLevelPoolCount)
  1007 			{
  1008 			__KTRACE_OPT(KRESMANAGER, Kern::Printf("Client level quota exhausted and its free pool empty, iReservedCl = %d, iClientLevelPoolCount = %d", 
  1009 													pC->iReservedCl, iClientLevelPoolCount));
  1010 			return KErrUnderflow;
  1011 			}
  1012         LIST_POP(iClientLevelPool, pSCL, iNextInList);
  1013         pSCL->iClientId=pC->iClientId;
  1014         pSCL->iResourceId=aReq->ResourceId();
  1015         pSCL->iLevel = aReq->Level();
  1016         //Add to the resource list
  1017         aResource->iClientList.Add(pSCL);
  1018         //Add to the client List
  1019         LIST_PUSH(pC->iLevelList, pSCL, iNextInList);
  1020         if(pC->iReservedCl == 0)
  1021 			{
  1022 			iClientLevelPoolCount--;
  1023 			pC->iUnderFlowClCount++;
  1024 			}
  1025         else
  1026           pC->iReservedCl--;
  1027 		//If no client is holding the resource already and is not custom sense resource, then change is allowed
  1028         if((aResource->iLevelOwnerId == -1) && (aResource->Sense() != DStaticPowerResource::ECustom))
  1029 			{
  1030 			aReq->RequiresChange() = ETrue;
  1031 			__KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
  1032 			return KErrNone;
  1033 			}
  1034 		if(aResource->Sense() == DStaticPowerResource::ECustom)
  1035 			newClient = ETrue;
  1036 		}
  1037     else
  1038 		// Capture the new level requested by the client.
  1039         pSCL->iLevel=aReq->Level();
  1040 
  1041     if(aResource->Sense() == DStaticPowerResource::ECustom)
  1042 		{
  1043 		
  1044         if(!aResource->iCustomFunction)
  1045             Panic(ECustomFunctionNotSet);
  1046 		// coverity[var_deref_op]
  1047 		if(aReq->ReqType() == TPowerRequest::EChange)
  1048 		    {
  1049             aReq->RequiresChange() = aResource->iCustomFunction(aReq->ClientId(), *(pC->iName), aReq->ResourceId(),
  1050                                                                 newClient ? EClientRequestLevel : EClientChangeLevel,
  1051                                                                 aReq->Level(), (TAny*)&aResource->iClientList, NULL);
  1052 		    }
  1053 		else
  1054 		    {
  1055             aReq->RequiresChange() = aResource->iCustomFunction(aReq->ClientId(), *(pC->iName), aReq->ResourceId(),
  1056                                                                 EClientRelinquishLevel,
  1057                                                                 aReq->Level(), (TAny*)&aResource->iClientList, NULL);
  1058 		    }
  1059 		if((aReq->ClientId() != -1) && (aReq->ClientId() != (TInt)pC->iClientId) )
  1060 			{
  1061 			//Check whether the updated client Id (by custom function) is in the client level list. 
  1062 			for(SDblQueLink* pCL=aResource->iClientList.First();pCL!=&aResource->iClientList.iA;pCL=pCL->iNext)
  1063 				{
  1064 				pL = (SPowerResourceClientLevel*)pCL;
  1065 				if((TInt)pL->iClientId == aReq->ClientId())
  1066 					break;
  1067 				}
  1068 #ifdef PRM_ENABLE_EXTENDED_VERSION
  1069 			if(aReq->ClientId() & (1 << RESOURCE_BIT_IN_ID_CHECK))
  1070 				{
  1071 				if(aResource->iResourceId & KIdMaskDynamic)
  1072 					pL = ((DDynamicPowerResourceD*)aResource)->iResourceClientList;
  1073 				else
  1074 					pL = ((DStaticPowerResourceD*)aResource)->iResourceClientList;
  1075 				while(pL != NULL)
  1076 					{
  1077 					if((TInt)pL->iClientId == aReq->ClientId())
  1078 						break;
  1079 					}
  1080 				}
  1081 #endif
  1082 			// coverity[var_deref_op]
  1083 			if((TInt)pL->iClientId != aReq->ClientId())
  1084 				Panic(EClientIdNotInClientLevelList);
  1085 			}
  1086 		if(!aReq->RequiresChange() && (aReq->ClientId() != (TInt)pC->iClientId))
  1087 	        {
  1088 		    aResource->iLevelOwnerId=aReq->ClientId();
  1089 			//Update resource details for Idle
  1090 		    if(aResource->iIdleListEntry)
  1091 				aResource->iIdleListEntry->iLevelOwnerId=aReq->ClientId();
  1092 			}
  1093 		__KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
  1094         return KErrNone;
  1095 		}
  1096     //Handle client deregistration
  1097 	if(aReq->ReqType() == TPowerRequest::ESetDefaultLevel) 
  1098 		{
  1099 		aReq->RequiresChange() = ETrue;
  1100 		// If the client is the only ask PSL to set to default level.
  1101 		if(count == 1)
  1102 			{
  1103 			aReq->ReqType() = TPowerRequest::ESetDefaultLevel;
  1104 			aReq->Level() = aResource->iDefaultLevel;
  1105 			aReq->ClientId() = -1;
  1106 			}
  1107         else
  1108 			{
  1109 			//Change the state to next maximum level with respect to sense.
  1110 			aReq->ReqType() = TPowerRequest::EChange;
  1111 			// coverity[var_deref_op]
  1112 			aReq->ClientId() = pMCL->iClientId;
  1113 			aReq->Level() = pMCL->iLevel;
  1114 			if(pSCL->iLevel == pMCL->iLevel)
  1115 				{
  1116                 //Change the client alone and level remains the same.
  1117                 aResource->iLevelOwnerId = pMCL->iClientId;
  1118                 if(aResource->iIdleListEntry)
  1119                     aResource->iIdleListEntry->iLevelOwnerId = pMCL->iClientId;
  1120                 aReq->RequiresChange() = EFalse;
  1121 				}
  1122 			}
  1123 		__KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
  1124 		return KErrNone;
  1125 		}
  1126 
  1127 	//If the level is in increasing order with respect to sense the change is allowed.
  1128     if(((aResource->Sense() == DStaticPowerResource::ENegative) && aReq->Level()<CurrentLevel) || 
  1129 		                 ((aResource->Sense() == DStaticPowerResource::EPositive) && aReq->Level()>CurrentLevel))
  1130 		{
  1131 		__KTRACE_OPT(KRESMANAGER, Kern::Printf("Resource is in increasing order with respect to sense and level is %d",
  1132 			                                                                                           aReq->Level()));
  1133         aReq->RequiresChange()=ETrue;
  1134         return KErrNone;
  1135 		}
  1136     if((TInt)pC->iClientId == aResource->iLevelOwnerId)
  1137 		{
  1138          if(aReq->Level() == CurrentLevel)
  1139 			{
  1140 			 __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
  1141 			return KErrNone;
  1142 			}
  1143          if(count == 1)
  1144            {
  1145            aReq->RequiresChange() = ETrue;
  1146 		   __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
  1147            return KErrNone;
  1148            }
  1149 		// If the client requesting is the client holding current level, then chnage it to the nextmaximum level.
  1150 		// Next maximum level is the max of requesting level or next maximum level.
  1151 		if(((aResource->Sense()==DStaticPowerResource::ENegative) && maxLevel < aReq->Level()) || 
  1152 			                  ((aResource->Sense()==DStaticPowerResource::EPositive) && maxLevel > aReq->Level()))
  1153 		    {
  1154 			aReq->Level() = maxLevel;
  1155 			aReq->ClientId() = pMCL->iClientId;
  1156 			if(maxLevel == CurrentLevel)
  1157 				{
  1158        			aResource->iLevelOwnerId=pMCL->iClientId;
  1159 				//Update resource details for Idle
  1160 				if(aResource->iIdleListEntry)
  1161              		aResource->iIdleListEntry->iLevelOwnerId=pMCL->iClientId;
  1162 				aReq->RequiresChange() = EFalse;
  1163 				__KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
  1164 				return KErrNone;
  1165 				}
  1166 			}
  1167 	      	aReq->RequiresChange() = ETrue;
  1168 		}
  1169 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
  1170     return KErrNone;
  1171 	}
  1172 
  1173 /**
  1174     Initialise pools of request structures, client strutures and client power level structures. 
  1175 	By preallocating sufficiently large structures we remove any allocations whilst the resource manager mutex is held.
  1176     The function basically ensures that sufficient memory is preallocated to the resource manager to ensure that none is
  1177     required at run time.
  1178     @param aKClients number of kernel side clients expected in the resource manager
  1179     @param aUClients number of user side clients expected in the resource manager
  1180     @param aNClientLevels number of client levels the RM should preallocate. This is roughly the number of clients
  1181         that are expected to use shared resources multiplied by the number of shared resources.
  1182     @param aNRequest number of simultaneous asynchronous requests the resource manager is likely to handle
  1183     @return KErrNone if preallocations succeed
  1184     @return KErrNoMemory if one the prealocations fails
  1185     */
  1186 TInt DPowerResourceController::InitPools(TUint16 aKClients, TUint16 aUClients, TUint16 aNClientLevels, TUint16 aNRequests)
  1187 	{
  1188     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::InitPools"));
  1189 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("aKClients = %d, aUClients = %d, aNClientLevels = %d, aNRequests = %d",
  1190 		                                                     aKClients, aUClients, aNClientLevels, aNRequests));
  1191     __ASSERT_ALWAYS((iInitialised == EResConCreated) && !(iClientPool || iRequestPool || iClientLevelPool), Kern::Fault("Already initialized"
  1192 		                                                     __FILE__, __LINE__));
  1193 
  1194     // Create client pool
  1195 	SPowerResourceClient* pC = NULL;
  1196 	SPowerResourceClientLevel* pCL = NULL;
  1197 	SPowerRequest* pR = NULL;
  1198 	aKClients++; //Add one default for PowerController
  1199 	if(aKClients + aUClients)
  1200 		{
  1201 		// coverity[alloc_fn]
  1202 		pC = new SPowerResourceClient[aKClients+aUClients];
  1203 		if(!pC)
  1204 			{
  1205 			__KTRACE_OPT(KRESMANAGER, Kern::Printf("Client Pool Allocation Failed"));
  1206 			return KErrNoMemory;
  1207 			}
  1208 		}
  1209     // Create Client level pool
  1210 	if(aNClientLevels)
  1211 		{
  1212 		// coverity[alloc_fn]
  1213 		pCL = new SPowerResourceClientLevel[aNClientLevels];
  1214 		if(!pCL)
  1215 			{
  1216 			__KTRACE_OPT(KRESMANAGER, Kern::Printf("Client Level Pool Allocation Failed"));
  1217 			delete []pC;
  1218 			return KErrNoMemory;
  1219 			}
  1220 		}
  1221     // Create Request pool
  1222 	if(aNRequests)
  1223 		{
  1224 		// coverity[alloc_fn]
  1225 		pR = new SPowerRequest[aNRequests];
  1226 		if(!pR)
  1227 			{
  1228 			__KTRACE_OPT(KRESMANAGER, Kern::Printf("Request Pool Allocation Failed"));
  1229 			delete []pC;
  1230 			delete []pCL;
  1231 			return KErrNoMemory;
  1232 			}
  1233 		}
  1234     //Create the client Array for kernel and user side clients.
  1235 	if(iClientList.Initialise(aKClients))
  1236 		{
  1237         delete []pC;
  1238         delete []pCL;
  1239         delete []pR;
  1240         return KErrNoMemory;
  1241 		}
  1242  	if(iUserSideClientList.Initialise(aUClients))
  1243  		{
  1244         delete []pC;
  1245         delete []pCL;
  1246         delete []pR;
  1247         iClientList.Delete();
  1248 		return KErrNoMemory;
  1249 		}
  1250 #ifdef PRM_ENABLE_EXTENDED_VERSION
  1251 	SPowerResourceClientLevel* pRL = NULL;
  1252 	if(iStaticResDependencyCount)
  1253 		{
  1254 		pRL = new SPowerResourceClientLevel[iStaticResDependencyCount];
  1255 		if(!pRL)
  1256 			{
  1257 			__KTRACE_OPT(KRESMANAGER, Kern::Printf("Resource level Pool Allocation Failed"));
  1258 			delete []pC;
  1259 			delete []pCL;
  1260 			delete []pR;
  1261 			iClientList.Delete();
  1262 			iUserSideClientList.Delete();
  1263 			return KErrNoMemory;
  1264 			}
  1265 		}
  1266 #ifdef RESOURCE_MANAGER_SIMULATED_PSL
  1267 	iCleanList.Append(pC);
  1268 #endif
  1269 	Lock();
  1270 	TUint16 c;
  1271 	for(c = 0; c < iStaticResDependencyCount; c++)
  1272 		{
  1273 		LIST_PUSH(iResourceLevelPool, &pRL[c], iNextInList);
  1274 		}
  1275 	iResourceLevelPoolCount = iStaticResDependencyCount;
  1276 #else
  1277 #ifdef RESOURCE_MANAGER_SIMULATED_PSL
  1278     iCleanList.Append(pC);
  1279 #endif
  1280     Lock();
  1281     TUint16 c;
  1282 #endif
  1283     // Create Client pool list
  1284     for(c = 0; c< (aKClients + aUClients); c++)
  1285 		{
  1286         LIST_PUSH(iClientPool, &pC[c], iNextInList);
  1287 		}
  1288     // Create client level pool list
  1289     for(c = 0; c < aNClientLevels; c++)
  1290 		{
  1291         LIST_PUSH(iClientLevelPool, &pCL[c], iNextInList);
  1292 		}
  1293     // Create request pool list
  1294     for(c = 0; c < aNRequests; c++)
  1295 		{
  1296         LIST_PUSH(iRequestPool, &pR[c], iNext);
  1297 		}
  1298     // When the pool is exhausted they are increased by half of initial size. */
  1299     iClientLevelPoolGrowBy=(TUint16)(aNClientLevels/2);
  1300     iRequestPoolGrowBy=(TUint16)(aNRequests/2);
  1301     // Initialise the free pool size
  1302     iClientLevelPoolCount=aNClientLevels;
  1303     iRequestPoolCount=aNRequests;
  1304 #ifdef PRM_INSTRUMENTATION_MACRO
  1305 	TUint size = (((aKClients + aUClients)*sizeof(SPowerResourceClient)) + 
  1306 		         (aNClientLevels * sizeof(SPowerResourceClientLevel)) + (aNRequests * sizeof(SPowerRequest)));
  1307     PRM_MEMORY_USAGE_TRACE
  1308 #endif
  1309 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::InitPools"));
  1310     UNLOCK_RETURN(KErrNone);
  1311 	}
  1312 
  1313 /**
  1314 @publishedPartner
  1315 @prototype 9.5
  1316 
  1317 Register a client with the Resource Manager. 
  1318 
  1319 @param aClientId  A reference to a client ID: returns a unique handle if registration was
  1320                   successful, 0 otherwise.
  1321 @param aName      Descriptor with name for client. The descriptor is created by the client
  1322                   in kernel data space or its user address space.
  1323                   NOTE: Name should ideally relate to component name and should take care
  1324                   of name uniqueness as it is checked only if DEBUG_VERSION macro is enabled.
  1325 @param aType      Defines ownership
  1326                   EOwnerProcess - The client ID can be used by all thread in the process to
  1327                   call the resource manager API's
  1328                   EOwnerThread - The client ID can only be used by the thread that registered
  1329                   the client to resource manager to call the PRM API's
  1330                   By default this is set to EOwnerProcess.
  1331 
  1332 @return           KErrNone if the operation was successful,
  1333                   KErrNoMemory if a new client link was needed but could not be created and
  1334 								added to the client list,
  1335                   KErrTooBig if the length of the descriptor passed is greater than 32.
  1336 				  KErrAlreadyExists if the specified name already exists. This is valid only if
  1337 								DEBUG_VERSION macro is enabled. 
  1338 				  KErrNotSupported if number of expected kernel side clients is set to zero by 
  1339 								PSL.
  1340 
  1341 @pre Interrupts must be enabled.
  1342 @pre Kernel must be unlocked.
  1343 @pre No fast mutex can be held.
  1344 @pre Call in a thread context, but not from null thread or DFC thread1.
  1345 @pre Can be used in a device driver
  1346 */
  1347 TInt DPowerResourceController::RegisterClient(TUint& aClientId, const TDesC8& aName, TOwnerType aType)
  1348 	{
  1349 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterClient, Name = %S, Type = %d", &aName, aType));
  1350 	DThread& thread = Kern::CurrentThread();	
  1351 	CHECK_CONTEXT(thread)
  1352 	//If number of expected kernel side clients is set to 0 during initial configuration
  1353 	//then dont allow to configure kernel side clients.
  1354 	if(!iClientList.GrowBy())
  1355 		return KErrNotSupported;
  1356 	if (aName.Length() > KMaxClientNameLength) return KErrTooBig;
  1357 	SPowerResourceClient *pC = NULL;
  1358 	Lock();
  1359 #ifdef DEBUG_VERSION
  1360    if(!iClientList.Find(pC, (TDesC8&)aName))
  1361        UNLOCK_RETURN(KErrAlreadyExists);
  1362 #endif
  1363 	//Call from thread Id.
  1364 	TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
  1365 	req->ReqType() = TPowerRequest::ERegisterKernelClient;
  1366 	UnLock();
  1367 	req->SendReceive(iMsgQ);
  1368 	if(req->ReturnCode() == KErrNone)
  1369 		{
  1370 		pC = iClientList[(TUint16)(req->ClientId() & ID_INDEX_BIT_MASK)];
  1371 		if(aType == EOwnerThread)
  1372 			{
  1373 			pC->iClientId |= CLIENT_THREAD_RELATIVE_BIT_MASK; //Set 31st bit;
  1374 			//Store the current thread Id;
  1375 			pC->iThreadId = thread.iId;
  1376 			}
  1377 		pC->iName = &aName;
  1378 		aClientId = pC->iClientId;
  1379 		}
  1380     PRM_CLIENT_REGISTER_TRACE
  1381 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterClient, clientId = 0x%x", aClientId));
  1382 	return(req->ReturnCode());
  1383 	}
  1384 
  1385 #ifdef PRM_ENABLE_EXTENDED_VERSION
  1386 TInt DPowerResourceController::HandleResourceRegistration(TPowerRequest& aReq)
  1387 	{
  1388 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::HandleResourceRegistration"));
  1389 	DDynamicPowerResource* pDRes = (DDynamicPowerResource*)aReq.Resource();
  1390 		//Add to appropriate container
  1391 	if(pDRes->iResourceId & KIdMaskResourceWithDependencies)
  1392 		ADD_TO_RESOURCE_CONTAINER(iDynamicResDependencyList, ((DDynamicPowerResourceD*)pDRes), aReq.ResourceId(), 
  1393 		                                                                   iDynamicResDependencyCount)
  1394 	else 
  1395 		ADD_TO_RESOURCE_CONTAINER(iDynamicResourceList, pDRes, aReq.ResourceId(), iDynamicResourceCount)
  1396 
  1397 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::HandleResourceRegistration"));
  1398 	return KErrNone;
  1399 	}
  1400 #endif
  1401 
  1402 /**
  1403 @internalComponent
  1404 @prototype 9.5
  1405 
  1406 This function runs in the context of the RC thread and 
  1407 handles registration of client (kernel and user side). 
  1408 */
  1409 TInt DPowerResourceController::HandleClientRegistration(TPowerRequest& aRequest)
  1410 	{
  1411 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterClient"));
  1412 	SPowerResourceClient* pC = NULL;
  1413 	TUint clientId;
  1414 	if(aRequest.ReqType() == TPowerRequest::ERegisterKernelClient)
  1415 		{
  1416 		//Get Next client from FreePool
  1417 		LIST_POP(iClientPool, pC, iNextInList);
  1418 
  1419 		TUint16 growBy = iClientList.GrowBy();
  1420 		if(!pC)
  1421 			{
  1422 			//Free Pool is empty, so try to grow the pool.
  1423 			__KTRACE_OPT(KRESMANAGER, Kern::Printf("Client pool exhausted so growing client Pool by %d", growBy));
  1424 			// coverity[alloc_fn]
  1425 			SPowerResourceClient *pCL = (SPowerResourceClient*)Kern::Alloc(sizeof(SPowerResourceClient) * growBy);
  1426 			if(!pCL)
  1427 				{
  1428 				__KTRACE_OPT(KRESMANAGER, Kern::Printf("No memory to grow client pool"));
  1429 				return(KErrNoMemory);
  1430 				}
  1431 #ifdef RESOURCE_MANAGER_SIMULATED_PSL
  1432 			iCleanList.Append(pCL);
  1433 #endif
  1434 			Lock();
  1435 			TUint16 count;
  1436 			for(count = 0; count < growBy-1; count++)
  1437 				LIST_PUSH(iClientPool, &pCL[count], iNextInList);
  1438 			UnLock();
  1439 #ifdef PRM_INSTRUMENTATION_MACRO
  1440 	TUint size = growBy *sizeof(SPowerResourceClient);
  1441 	PRM_MEMORY_USAGE_TRACE
  1442 #endif
  1443 			pC = &pCL[count];
  1444 			}
  1445 		pC->iClientId = 0;
  1446 		if(iClientList.Allocd()==iClientList.Count())
  1447 			{
  1448 			//Resize the container for holding client list
  1449 			if(iClientList.ReSize(growBy)!=KErrNone)
  1450 				{
  1451 				__KTRACE_OPT(KRESMANAGER, Kern::Printf("No memory for client container allocation"));
  1452 				return(KErrNoMemory);
  1453 				}
  1454 			}
  1455 		Lock();
  1456 		iClientList.Add(pC, clientId);
  1457 		++iClientCount;
  1458 		UnLock();
  1459 		}
  1460 	else // Request is registration of user side client
  1461 		{
  1462 		//Get Next client from FreePool
  1463 		LIST_POP(iClientPool, pC, iNextInList);
  1464 		TUint16 growBy = iUserSideClientList.GrowBy();
  1465 		if(!pC)
  1466 			{
  1467 			//Free Pool is empty, so try to grow the pool.
  1468 			SPowerResourceClient *pCL = (SPowerResourceClient*)Kern::Alloc(sizeof(SPowerResourceClient) * growBy);
  1469 			if(!pCL)
  1470 				{
  1471 				return KErrNoMemory;
  1472 				}
  1473 #ifdef RESOURCE_MANAGER_SIMULATED_PSL
  1474 			iCleanList.Append(pCL);
  1475 #endif
  1476 			Lock();
  1477 			TUint16 count;
  1478 			for(count = 0; count < growBy - 1; count++)
  1479 				LIST_PUSH(iClientPool, &pCL[count], iNextInList);
  1480 			UnLock();
  1481 #ifdef PRM_INSTRUMENTATION_MACRO
  1482 		TUint size = growBy * sizeof(SPowerResourceClient);
  1483 		PRM_MEMORY_USAGE_TRACE
  1484 #endif
  1485     		pC = &pCL[count];
  1486 			}
  1487 		pC->iClientId = 0;
  1488 		//User side clients are always thread relative as they execute in the context of proxy driver.
  1489 		pC->iClientId = CLIENT_THREAD_RELATIVE_BIT_MASK; //Set 31st bit;
  1490 		pC->iClientId|=USER_SIDE_CLIENT_BIT_MASK;
  1491 		if(iUserSideClientList.Allocd()==iUserSideClientList.Count())
  1492 			{
  1493 			//Resize the container for holding client list
  1494 			if(iUserSideClientList.ReSize(growBy)!=KErrNone)
  1495 				{
  1496 				__KTRACE_OPT(KRESMANAGER, Kern::Printf("No memory for container class allocation"));
  1497 				return KErrNoMemory;
  1498 				}
  1499 			}
  1500 		Lock();
  1501 		iUserSideClientList.Add(pC, clientId);
  1502 		++iUserSideClientCount;
  1503 		UnLock();
  1504 		}
  1505 	//Create the unique handle for each client
  1506 	//Client Handle format
  1507 	//  31  30								   18 16    15    14 13	                                 0
  1508 	// ¦----¦-----------------------------------¦----¦-----¦-----¦-----------------------------------¦
  1509 	// ¦ T/P¦ Container's instance count(15 bits¦C/R ¦  PC ¦ K/U ¦ Index into Client array container ¦
  1510 	// ¦----¦-----------------------------------¦----¦-----¦-----¦-----------------------------------¦
  1511 	// T/P -> Thread / process relative
  1512 	// PC -> Power Controller reserved ID.
  1513 	// K/U -> Kernel / User side clients
  1514 	// C/R -> Client / Resource Id. This bit will be set for dependency resource Id, zero for clientId.
  1515   	pC->iLevelList = NULL;
  1516     pC->iNotificationList = NULL;
  1517 	pC->iDynamicResCount = 0; 	
  1518     pC->iReservedCl = 0;
  1519     pC->iReservedRm = 0;
  1520     pC->iPendingReqCount = 0;
  1521     pC->iUnderFlowRmCount = 0;
  1522     pC->iUnderFlowClCount = 0;
  1523 	pC->iClientId |= clientId;
  1524 	aRequest.ClientId() = pC->iClientId;
  1525 	return KErrNone;
  1526 	}
  1527 
  1528 /**	@internalComponent
  1529 	@prototype 9.5
  1530 	This is called as the result of client deregistration and takes care of resource state changes
  1531 	(to appropriate levels) of all the resources the client is holding active requirement. */
  1532 void DPowerResourceController::ResourceStateChangeOfClientLevels(SPowerResourceClient* pC)
  1533 	{
  1534 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::ResourceStateChangeOfClientLevels"));
  1535     TPowerRequest* pReq = (TPowerRequest*)&TPowerRequest::Get();
  1536     DStaticPowerResource* pR = NULL;
  1537     SPowerResourceClientLevel* pCL = pC->iLevelList;
  1538     SPowerResourceClientLevel* pCLL = NULL;
  1539 	while(pCL != NULL)
  1540 		{
  1541         __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client 0x%x has requirement on resource %d", pCL->iClientId, pCL->iResourceId));
  1542 #ifdef PRM_ENABLE_EXTENDED_VERSION
  1543 		switch((pCL->iResourceId >>RESOURCE_BIT_IN_ID_CHECK) & 0x3)													
  1544 		{																		
  1545 		case PRM_STATIC_RESOURCE:												
  1546 			pR = iStaticResourceArray[pCL->iResourceId - 1];								
  1547 			break;																
  1548 		case PRM_DYNAMIC_RESOURCE:												
  1549 			pR = (iDynamicResourceList[(TUint16)(pCL->iResourceId & ID_INDEX_BIT_MASK)]);			
  1550 			break;																
  1551 		case PRM_STATIC_DEPENDENCY_RESOURCE:									
  1552 			pR = (iStaticResDependencyArray[(TUint16)(pCL->iResourceId & ID_INDEX_BIT_MASK) - 1]);						
  1553 			break;																
  1554 		case PRM_DYNAMIC_DEPENDENCY_RESOURCE:									
  1555 			pR = (iDynamicResDependencyList[(TUint16)(pCL->iResourceId & ID_INDEX_BIT_MASK)]);		
  1556 			break;																
  1557 		}
  1558 #else
  1559 		pR = iStaticResourceArray[pCL->iResourceId -1];
  1560 #endif
  1561 #ifdef PRM_ENABLE_EXTENDED_VERSION
  1562 		if(((pR->Sense() == DStaticPowerResource::ECustom) || ((TInt)pCL->iClientId == pR->iLevelOwnerId)) && (!(pCL->iResourceId & KIdMaskDynamic) ||
  1563 			         ((pCL->iResourceId & KIdMaskDynamic) && (((DDynamicPowerResource*)pR)->LockCount() != 0))))
  1564 #else
  1565 		if((pR->Sense() == DStaticPowerResource::ECustom) || ((TInt)pCL->iClientId == pR->iLevelOwnerId)) 
  1566 #endif
  1567 		    {
  1568             pReq->ReqType() = TPowerRequest::ESetDefaultLevel;
  1569             pReq->ResourceId() = pCL->iResourceId;
  1570             pReq->ClientId() = pCL->iClientId;
  1571             pReq->Resource() = pR;
  1572 			pReq->Level() = pR->iCachedLevel;
  1573             pReq->ResourceCb() = NULL;
  1574 			pReq->ReturnCode() = KErrNone;
  1575 #ifdef PRM_INSTRUMENTATION_MACRO
  1576 			//Setting level to current level as correct level will be known only at the end,
  1577 			TInt aNewState = pR->iCachedLevel; 
  1578 			TUint aResourceId = pReq->ResourceId(); 
  1579 			PRM_CLIENT_CHANGE_STATE_START_TRACE
  1580 #endif
  1581 			TInt r = KErrNone;
  1582 			if(pR->LatencySet())
  1583 				{
  1584 #ifdef PRM_ENABLE_EXTENDED_VERSION
  1585 				if(pCL->iResourceId & KIdMaskDynamic)
  1586 					((DDynamicPowerResource*)pR)->Lock();
  1587 #endif
  1588 				UnLock();
  1589 #ifdef PRM_ENABLE_EXTENDED_VERSION
  1590 				if(pR->iResourceId & KIdMaskResourceWithDependencies) //Dependency resource
  1591 					r = pReq->SendReceive(iMsgQDependency);	
  1592 				else
  1593 #endif
  1594 				r = pReq->SendReceive(iMsgQ);
  1595 				Lock();
  1596 #ifdef PRM_ENABLE_EXTENDED_VERSION
  1597 				if(pCL->iResourceId & KIdMaskDynamic)
  1598 					((DDynamicPowerResource*)pR)->UnLock();
  1599 #endif
  1600 				}
  1601 			else
  1602 				{
  1603 	            if(pR->Usage())
  1604 					{
  1605 					//Not checking return value as there is no memory allocation at this point
  1606 					CheckLevelAndAddClient(pC, pReq); 
  1607 					}
  1608 				else
  1609 					{
  1610 					pReq->ClientId() = -1;
  1611 					pReq->Level() = pR->iDefaultLevel;
  1612 					}
  1613 
  1614 				if((!pR->Usage()) || (pR->Usage() && pReq->RequiresChange()))
  1615 					{
  1616 					// NOTE:Not checking error here as no action can be taken based on error.
  1617 					if(pR->iCachedLevel != pReq->Level())
  1618 						{
  1619 						UnLock();
  1620 						r = pR->DoRequest(*pReq);
  1621 						Lock();
  1622 						}
  1623 					CompleteNotifications(pReq->ClientId(), pReq->Resource(), pReq->Level(), 
  1624 						                            pReq->ReturnCode(), pReq->ClientId(), EFalse);
  1625 #ifdef PRM_INSTRUMENTATION_MACRO
  1626 					PRM_CLIENT_CHANGE_STATE_END_TRACE
  1627 #endif
  1628 					pR->iLevelOwnerId = pReq->ClientId();
  1629 					pR->iCachedLevel = pReq->Level();
  1630 					if(pR->iIdleListEntry)
  1631 						{
  1632 						SIdleResourceInfo* pI = (SIdleResourceInfo*)pR->iIdleListEntry;
  1633 						pI->iLevelOwnerId = pReq->ClientId();
  1634 						pI->iCurrentLevel = pReq->Level();
  1635 						}
  1636 					}
  1637 				}
  1638 
  1639 			}
  1640 		/* Deque from resource */
  1641 		pCLL = pCL;
  1642 		pCL = pCL->iNextInList;
  1643 		pCLL->Deque();
  1644 		iClientLevelPoolCount++;
  1645 		LIST_PUSH(iClientLevelPool,pCLL,iNextInList); // back to free pool
  1646 		}
  1647 	pC->iLevelList = NULL;
  1648 	//Add reserved client level to free pool
  1649 	iClientLevelPoolCount = (TUint16)(iClientLevelPoolCount + (TUint16)pC->iReservedCl);
  1650 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::ResourceStateChangeOfClientLevels"));
  1651 	}
  1652 
  1653 /**
  1654 @publishedPartner
  1655 @prototype 9.5
  1656 
  1657 Deregister a client with the resource manager
  1658 
  1659 @param aClientId    The ID of the client which is being deregistered
  1660 
  1661 @return KErrNone if the operation was successful
  1662         KErrNotFound if this client ID could not be found in the current
  1663 					 list of clients
  1664 		KErrArgument if user side client Id is specified or client ID to be used 
  1665 					 by Power Controller is specified.
  1666 		KErrAccessDenied if client was registered to be thread relative and this 
  1667 						 API is not called from the same thread.							
  1668 
  1669 @pre Interrupts must be enabled
  1670 @pre Kernel must be unlocked
  1671 @pre No fast mutex can be held
  1672 @pre Call in a thread context but not from null thread or DFC thread1
  1673 @pre Can be used in a device driver
  1674 */
  1675 TInt DPowerResourceController::DeRegisterClient(TUint aClientId)
  1676 	{
  1677 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::DeRegisterClient, ClientId = 0x%x", aClientId));
  1678 	DThread& thread = Kern::CurrentThread();	
  1679 	CHECK_CONTEXT(thread)
  1680 	if((aClientId & USER_SIDE_CLIENT_BIT_MASK) || (aClientId == iPowerControllerId))
  1681 		return KErrArgument;
  1682 	//Get the index from client ID
  1683 	Lock();
  1684 	SPowerResourceClient* pC = iClientList[(TUint16)(aClientId & ID_INDEX_BIT_MASK)];
  1685     if(!pC)
  1686 	    {
  1687         __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client ID not Found"));
  1688         UNLOCK_RETURN(KErrNotFound);
  1689 		}
  1690 	if(pC->iClientId != aClientId)
  1691 		{
  1692         __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client ID does not match"));
  1693 	     UNLOCK_RETURN(KErrNotFound);
  1694 		}
  1695 	if(pC->iClientId & CLIENT_THREAD_RELATIVE_BIT_MASK)
  1696 		{
  1697         if(pC->iThreadId != thread.iId)
  1698 			{
  1699             __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client not called from thread context(Thread Relative)"));
  1700             UNLOCK_RETURN(KErrAccessDenied);
  1701 			}
  1702 		}	
  1703 	//Check for any pending request
  1704 	if(pC->iPendingReqCount)
  1705 		{
  1706 		UnLock();
  1707 		Panic(EClientHasPendingAsyncRequest);
  1708 		}
  1709 	//Check for notification request
  1710 	if(pC->iNotificationList)
  1711 		{
  1712 		UnLock();
  1713 		Panic(EClientHasNotificationObject);
  1714 		}
  1715 #ifdef PRM_ENABLE_EXTENDED_VERSION
  1716 	if(pC->iDynamicResCount)
  1717 		{
  1718 		UnLock();
  1719 		Panic(DPowerResourceController::EClientHasDynamicResourceRegistered);
  1720 		}
  1721 #endif
  1722 	//Check for registration of dynamic resource
  1723 	ResourceStateChangeOfClientLevels(pC);
  1724 	// Add reserved request to pool
  1725 	iRequestPoolCount = (TUint16)(iRequestPoolCount + (TUint16)pC->iReservedRm);
  1726 	PRM_CLIENT_DEREGISTER_TRACE
  1727 	//Increment the free pool count for client level and request level.
  1728 	iClientList.Remove(pC, (TUint16)(pC->iClientId & ID_INDEX_BIT_MASK));
  1729 	pC->iName = NULL;
  1730 	iClientCount--; //Decrement client count
  1731 	LIST_PUSH(iClientPool, pC, iNextInList);
  1732 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::DeRegisterClient"));
  1733 	UNLOCK_RETURN(KErrNone);
  1734 	}
  1735 
  1736 /**
  1737 @publishedPartner
  1738 @prototype 9.5
  1739 
  1740 Obtain the name of a registered client of the resource manager
  1741 
  1742 @param aClientId   The ID of the client which is requesting the name of
  1743                    another client whose ID is specified in aTargetClientId.
  1744 @param aTargetClientId The ID of the client whose name is being requested.
  1745 @param aName       Descriptor to be filled with the name of the client. The descriptor
  1746                    is created by the client in kernel stack or heap.
  1747 
  1748 @return            KErrNone if the operation was successful
  1749                    KErrNotFound if this client ID (aTargetClientId) could not be
  1750                    found in the current list of registered clients.
  1751                    KErrAccessDenied if the client ID (aClientId) could not be found
  1752                    in the current list of registered clients or if client was registered
  1753 				   to be thread relative and this API is not called from the same thread. 
  1754                    KErrArgument if size of aName is less than 32.
  1755 
  1756 @pre Interrupts must be enabled
  1757 @pre Kernel must be unlocked
  1758 @pre No fast mutex can be held
  1759 @pre Call in a thread context but not from null thread or DFC thread1
  1760 @pre Can be used in a device driver
  1761 */
  1762 TInt DPowerResourceController::GetClientName(TUint aClientId, TUint aTargetClientId, TDes8& aName)
  1763 	{
  1764 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetClientName, CallingClientId = 0x%x, TargetClientId = 0x%x", aClientId, aTargetClientId));
  1765 	DThread& thread = Kern::CurrentThread();	
  1766 	CHECK_CONTEXT(thread)
  1767 	if((aName.MaxLength() - aName.Length()) < KMaxClientNameLength)
  1768 		return KErrArgument;
  1769 	SPowerResourceClient* pC = NULL;
  1770 	Lock();
  1771 	VALIDATE_CLIENT(thread);
  1772 	GET_TARGET_CLIENT();
  1773 	aName.Append(*pC->iName);
  1774 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetClientName, ClientName = %S", &aName));
  1775 	UNLOCK_RETURN(KErrNone);
  1776 	}
  1777 
  1778 /**
  1779 @publishedPartner
  1780 @prototype 9.5
  1781 
  1782 Obtain the Id of registered client of the resource manager
  1783 
  1784 @param aClientId   ID of the client which is requesting the ID of the another
  1785                    client whose name is specified in aClientName
  1786 @param aClientName Descriptor containing the name of the client whose ID is being
  1787                    requested. The client must create the descriptor in kernel stack
  1788                    or heap.
  1789                    NOTE: Resource manager does not check for uniqueness of client
  1790                    name during registration, so if there are multiple clients registered
  1791                    to PRM with same name it will return the ID of the first client it encounters.
  1792 @param aTargetClientId Updates with ID of the requested client on success
  1793 
  1794 @return  KErrNone if the operation was successful
  1795          KErrNotFound if this client name could not be found in the current list of registered
  1796                       client
  1797          KErrAccessDenied if the client ID (aClientId) could not be found in the current
  1798                           list of registered client or if the client was registered to be 
  1799 						  thread relative and this API is not called from the same thread. 
  1800          KErrTooBig if the length of the descriptor passed is greater than 32.
  1801 
  1802 @pre Interrupts must be enabled
  1803 @pre Kernel must be unlocked
  1804 @pre No fast mutex can be held
  1805 @pre Call in a thread context but not from null thread or DFC thread1
  1806 @pre Can be used in a device driver
  1807 */
  1808 TInt DPowerResourceController::GetClientId(TUint aClientId, TDesC8& aClientName, TUint& aTargetClientId)
  1809 	{
  1810 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetClientId CallingClientId = 0x%x, ClientName = %S", aClientId, &aClientName));
  1811 	DThread& thread = Kern::CurrentThread();	
  1812 	CHECK_CONTEXT(thread)
  1813 	if(aClientName.Length() > KMaxClientNameLength)
  1814 		return KErrTooBig;
  1815 	SPowerResourceClient* pC = NULL;
  1816 	Lock();
  1817 	VALIDATE_CLIENT(thread);
  1818 	//Find the client ID with the specified name first from kernel client list & then user side.
  1819 	if(iClientList.Find(pC, aClientName) && iUserSideClientList.Find(pC, aClientName))
  1820 		UNLOCK_RETURN(KErrNotFound);
  1821 	aTargetClientId = pC->iClientId;
  1822 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetClientId TargetClientId = 0x%x", aTargetClientId));
  1823 	UNLOCK_RETURN(KErrNone);
  1824 	}
  1825 
  1826 /**
  1827 @publishedPartner
  1828 @prototype 9.5
  1829 
  1830 Obtain the ID of registered resource of the resource manager.
  1831 NOTE: ID of the first matching name found in the resource list will be returned
  1832 
  1833 @param aClientId      ID of the client which is requesting the ID of the
  1834                       resource, by specifying its name.
  1835 @param aResourceName  Descriptor containing the name of the resource whose
  1836                       ID is being requested.
  1837 @param aResourceId    Updates with ID of the requested resource on success
  1838 
  1839 @return KErrNone if the operation was successful
  1840         KErrAccessDenied if the ID of the client could not be found in the
  1841                          current list of registered clients or if the client was 
  1842 						 registered to be thread relative and this API is not called
  1843 						 from the same thread. 
  1844         KErrNotFound if this resource name could not be found in the current
  1845                      list of registered resources.
  1846 		KErrTooBig if the length of the descriptor passed is greater than maximum
  1847 				   allowable resource name length (32).
  1848 @pre Interrupts must be enabled
  1849 @pre Kernel must be unlocked
  1850 @pre No fast mutex can be held
  1851 @pre Call in a thread context but not from null thread or DFC thread1
  1852 @pre Can be used in a device driver
  1853 */
  1854 TInt DPowerResourceController::GetResourceId(TUint aClientId, TDesC8& aResourceName, TUint& aResourceId)
  1855 	{
  1856 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetResourceId"));
  1857 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("CallingClientId = 0x%x, ResourceName = %S", aClientId, &aResourceName));
  1858 	DThread& thread = Kern::CurrentThread();	
  1859 	CHECK_CONTEXT(thread)
  1860 	SPowerResourceClient* pC;
  1861 	if(aResourceName.Length() > KMaxResourceNameLength)
  1862 		return KErrTooBig;
  1863 	Lock();
  1864 	VALIDATE_CLIENT(thread);
  1865 	TUint count = 0;
  1866 	//Search in static resource with no dependencies array for specified resource name.
  1867 	for(count = 0; count < iStaticResourceArrayEntries; count++)
  1868 		{
  1869 		if((iStaticResourceArray[count]) && (!(aResourceName.Compare(*(const TDesC8*)iStaticResourceArray[count]->iName))))
  1870 			{
  1871 			aResourceId = ++count;
  1872 			__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetResourceId, ResourceId = 0x%x", aResourceId));
  1873 			UNLOCK_RETURN(KErrNone);
  1874 			}
  1875 		}
  1876 #ifdef PRM_ENABLE_EXTENDED_VERSION
  1877 	//Search in dynamic resource with no dependencies array for specified resource name.
  1878 	DDynamicPowerResource* pDR = NULL;
  1879 	if(PowerResourceController->iDynamicResourceCount && 
  1880 		           !PowerResourceController->iDynamicResourceList.Find(pDR, aResourceName))
  1881 		{
  1882 		aResourceId = pDR->iResourceId;
  1883 		__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetResourceId, ResourceId = 0x%x", aResourceId));
  1884 		UNLOCK_RETURN(KErrNone);
  1885 		}
  1886 	//Search in static resource with dependencies (if exists) for specified resource name
  1887 	for(count = 0; count < iStaticResDependencyCount; count++)
  1888 		{
  1889 		if(!(aResourceName.Compare(*(const TDesC8*)iStaticResDependencyArray[count]->iName)))
  1890 			{
  1891 			aResourceId = iStaticResDependencyArray[count]->iResourceId;
  1892 			__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetResourceId, ResourceId = 0x%x", aResourceId));
  1893 			UNLOCK_RETURN(KErrNone);
  1894 			}
  1895 		}
  1896 	//Search in dynamic resource with dependencies (if exists) for specified resource name
  1897 	DDynamicPowerResourceD* pDRD;
  1898 	if(iDynamicResDependencyCount && !iDynamicResDependencyList.Find(pDRD, aResourceName))
  1899 		{
  1900 		aResourceId = pDRD->iResourceId;
  1901 		__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetResourceId, ResourceId = 0x%x", aResourceId));
  1902 		UNLOCK_RETURN(KErrNone);
  1903 		}
  1904 #endif
  1905 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetResourceId, ResourceID not found"));
  1906 	UNLOCK_RETURN(KErrNotFound);
  1907 	}
  1908 
  1909 /**
  1910 @publishedPartner
  1911 @prototype 9.5
  1912 
  1913 Request a structure containing information on a resource.
  1914 
  1915 @param aClientId    ID of the client which is requesting the resource information
  1916 @param aResourceId  ID of the resource whose information is being requested.
  1917 @param aInfo        A pointer to descriptor containing resource information
  1918                     structure (TPowerResourceInfoV01) to be filled in
  1919                     with the requested resource information. The client must
  1920                     create the descriptor in kernel stack or heap.
  1921 
  1922 @return KErrNone if the operation was successful
  1923         KErrAccessDenied if the client ID could not be found in the current list
  1924                          of registered clients or if the client was registered to be 
  1925 						 thread relative and this API is not called from the same thread.
  1926         KErrNotFound if this resource ID could not be found in the current list
  1927                      of controllable resource.
  1928         KErrArgument if aInfo is NULL or size of descriptor passed is less than size of
  1929 					 TPowerResourceInfoV01.
  1930 @pre Interrupts must be enabled
  1931 @pre Kernel must be unlocked
  1932 @pre No fast mutex can be held
  1933 @pre Call in a thread context but not from null thread or DFC thread1
  1934 @pre Can be used in a device driver
  1935 */
  1936 TInt DPowerResourceController::GetResourceInfo(TUint aClientId, TUint aResourceId, TAny* aInfo)
  1937 	{
  1938 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetResourceInfo"));
  1939 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("CallingClientId = 0x%x, ResourceId = %d", aClientId, aResourceId));
  1940 	DThread& thread = Kern::CurrentThread();	
  1941 	CHECK_CONTEXT(thread)
  1942 	if(!aInfo)
  1943 		return KErrArgument;
  1944 	SPowerResourceClient* pC = NULL;
  1945 	Lock();
  1946 	VALIDATE_CLIENT(thread);
  1947 	TDes8* buf = (TDes8*)aInfo;
  1948 	TInt r = KErrNone;
  1949 	DStaticPowerResource *pR = NULL; 
  1950 
  1951 	//Validate buffer size
  1952 	if((TUint)(buf->MaxLength() - buf->Length()) < sizeof(TPowerResourceInfoV01))
  1953 	   UNLOCK_RETURN(KErrArgument);
  1954 
  1955 #ifndef PRM_ENABLE_EXTENDED_VERSION
  1956 	if((!aResourceId) || (aResourceId > iStaticResourceArrayEntries))
  1957 		UNLOCK_RETURN(KErrNotFound);
  1958 	//Get resource from static resource array. 0(1) operation.
  1959 	pR = iStaticResourceArray[aResourceId-1];
  1960 	if(!pR)
  1961 		{
  1962 		UNLOCK_RETURN(KErrNotFound);
  1963 		}
  1964 #else
  1965 	if(!aResourceId)
  1966 		{
  1967 		__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetResourceInfo, return value = %d", KErrNotFound));
  1968 		UNLOCK_RETURN(KErrNotFound);
  1969 		}
  1970 	//Get resource from corresponding container
  1971 	GET_RESOURCE_FROM_LIST(aResourceId, pR) 
  1972 #endif
  1973 	//Update resource info
  1974 	TPowerResourceInfoBuf01 infoBuf;
  1975 	r = pR->GetInfo((TDes8*)infoBuf.Ptr());
  1976 	//Update ResourceId
  1977 	((TPowerResourceInfoV01*)infoBuf.Ptr())->iResourceId = aResourceId;
  1978 	if(r == KErrNone)
  1979 	   buf->Append(infoBuf);
  1980 	UNLOCK_RETURN(r);
  1981 	}
  1982 
  1983 /**
  1984 @publishedPartner
  1985 @prototype 9.5
  1986 
  1987 Request number of resources the specified client (aTargetClientId) has
  1988 requirement on resource level. Client ID starts from 1, so if 0 is specified in
  1989 aTargetClientId, returns the number of controllable resources registered with PRM.
  1990 
  1991 @param aClientId ID of the client which is requesting the number of resources
  1992                  the specified client (aTargetClientId) holds requirement on
  1993                  resource level change.
  1994 @param aTargetClientId ID of the client. The number of resources on which it
  1995                        has requirement on resource level change is requested.
  1996 @param aNumResource Updated with the number of resources the specified client
  1997                     has requirement on resource level change, if valid client
  1998                     ID is passed. If client ID is 0, updates the total number
  1999                     of resources registered with resource manager.
  2000 
  2001 @return KErrNone if the operation was successful.
  2002         KErrAccessDenied if the client ID (aClientId) could not be found in the
  2003                          current list of registered clients or if the client was registered
  2004 						 to be thread relative and this API is not called from the same thread. 
  2005         KErrNotFound if the client ID (aTargetClientId) could not be found in the
  2006                      current list of registered clients and is not 0.
  2007 
  2008 @pre Interrupts must be enabled
  2009 @pre Kernel must be unlocked
  2010 @pre No fast mutex can be held
  2011 @pre Call in a thread context but not from null thread or DFC thread1
  2012 @pre Can be used in a device driver
  2013 */
  2014 TInt DPowerResourceController::GetNumResourcesInUseByClient(TUint aClientId, TUint aTargetClientId, TUint& aNumResource)
  2015 	{
  2016 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetNumResourcesInUseByClient"));
  2017 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("CallingClientId = 0x%x, TargetClientId = 0x%x", aClientId, aTargetClientId));
  2018 	DThread& thread = Kern::CurrentThread();	
  2019 	CHECK_CONTEXT(thread)
  2020 	SPowerResourceClient* pC = NULL;
  2021 	Lock();
  2022 	VALIDATE_CLIENT(thread);
  2023 	//Special case, return number of resources registered resource controller.
  2024 	if(!aTargetClientId)
  2025 		{
  2026 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2027 		aNumResource = iStaticResourceCount + iDynamicResourceCount + iStaticResDependencyCount + 
  2028 			                                                          iDynamicResDependencyCount; 
  2029 #else
  2030 		aNumResource = iStaticResourceCount;
  2031 #endif
  2032 		__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetNumResourcesInUseByClient, numResources = %d", aNumResource));
  2033 		UNLOCK_RETURN(KErrNone);
  2034 		}
  2035 	GET_TARGET_CLIENT();
  2036 	SPowerResourceClientLevel* pCL = pC->iLevelList;
  2037 	aNumResource = 0;
  2038 	while(pCL)
  2039 		{
  2040 		aNumResource++;
  2041 		pCL = pCL->iNextInList;
  2042 		}
  2043 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetNumResourcesInUseByClient, numResources = %d", aNumResource));
  2044 	UNLOCK_RETURN(KErrNone);
  2045 	}
  2046 
  2047 /**
  2048 @publishedPartner
  2049 @prototype 9.5
  2050 
  2051 Request information on resources.
  2052 If client ID (aTargetClientId) is valid, aInfo is updated with the information of the resources 
  2053 this client hold requirement on the resource level.
  2054 If client ID (aTargetClientId) is 0, aInfo is updated with the information of the resources 
  2055 registered with resource controller.
  2056 Number of resource information updated will be equal or less than the number specified in aNumResources.
  2057 
  2058 @param aClientId   ID of the client which is requesting the resource information.
  2059 @param aTargetClientId ID of the client. The information of all the resources on
  2060                        which it has requirement on resource level change is requested.
  2061                        Client ID starts from 1, so calling this API with client ID 0 will
  2062                        fill the details of all the controllable resource registered with
  2063                        resource manager.
  2064 @param aNumResources   Number of resource whose information needs to be filled in aInfo i.e,
  2065                        it specifies the size of aInfo array.
  2066 @param aInfo           A pointer to an array of descriptor containing an information structure
  2067                        (TPowerResourceInfoV01) to be filled in with the information
  2068                        on the resources. It will be assumed that array allocated will be equal
  2069                        to the number passed in aNumResources. The client must create the array
  2070                        in Kernel stack or heap.
  2071 
  2072 @return KErrNone if the operation was successful
  2073         KErrAccessDenied if client ID (aClientId) could not be found in the registered
  2074                          client list or if the client was registered to be thread relative
  2075 						 and this API is not called from the same thread. 
  2076         KErrNotFound if client ID (aTargetClientId) could not be found in the current list
  2077                      of registered client and is also not 0.
  2078         KErrArgument if aNumResources is 0 or aInfo is NULL or if size of aInfo is not sufficient
  2079 				     to hold the resource information of number of resources specified in aNumResources.
  2080 
  2081 @pre Interrupts must be enabled
  2082 @pre Kernel must be unlocked
  2083 @pre No fast mutex can be held
  2084 @pre Call in a thread context but not from null thread or DFC thread1
  2085 @pre Can be used in a device driver
  2086 */
  2087 TInt DPowerResourceController::GetInfoOnResourcesInUseByClient(TUint aClientId, TUint aTargetClientId, 
  2088 															    TUint& aNumResources, TAny* anInfo)
  2089 	{
  2090 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetInfoOnResourcesInUseByClient"));
  2091 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("CallingClientId = 0x%x, TargetClientId = 0x%x, NumResources = %d", \
  2092 		                                                            aClientId, aTargetClientId, aNumResources));
  2093 	DThread& thread = Kern::CurrentThread();	
  2094 	CHECK_CONTEXT(thread)
  2095 	if(!anInfo || !aNumResources)
  2096 		return KErrArgument;
  2097 	SPowerResourceClient* pC = NULL;
  2098 	Lock();
  2099 	VALIDATE_CLIENT(thread);
  2100 	DStaticPowerResource* pR = NULL;
  2101     TDes8 *pInfo = (TDes8*)anInfo;
  2102     if((TUint)(pInfo->MaxLength() - pInfo->Length()) < (sizeof(TPowerResourceInfoV01) * aNumResources))
  2103          UNLOCK_RETURN(KErrArgument);
  2104     TPowerResourceInfoBuf01 buf;
  2105 
  2106 	TUint16 count = 0;
  2107 	TInt r = KErrNone;
  2108 	//Special case, if aTargetClientId is 0 fill with all the resource
  2109 	if(!aTargetClientId)
  2110 		{
  2111 		TUint numResources = aNumResources;
  2112 #ifndef PRM_ENABLE_EXTENDED_VERSION
  2113 		aNumResources = iStaticResourceCount;
  2114 #else
  2115 		aNumResources = iStaticResourceCount + iDynamicResourceCount + iStaticResDependencyCount + 
  2116 			                                                           iDynamicResDependencyCount;
  2117 #endif
  2118 		UnLock();
  2119 		while(count < iStaticResourceArrayEntries)
  2120 			{
  2121 			if(numResources <=0)
  2122 				return KErrNone;
  2123 			pR = iStaticResourceArray[count++];
  2124 			if(!pR)
  2125 				continue;
  2126             r = pR->GetInfo((TDes8*)buf.Ptr());
  2127 			if(r != KErrNone)
  2128 				return r;
  2129             //Update Resource Id.
  2130             ((TPowerResourceInfoV01*)buf.Ptr())->iResourceId = count;
  2131 			pInfo->Append(buf);
  2132 			numResources--;
  2133 			}	
  2134 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2135 		count = 0;
  2136 		while(count < iStaticResDependencyCount)
  2137 			{
  2138 			if(count >= numResources)
  2139 				return KErrNone;
  2140 			pR = iStaticResDependencyArray[count++];
  2141 			r = pR->GetInfo((TDes8*)buf.Ptr());
  2142 			//Update Resource Id.
  2143 			((TPowerResourceInfoV01*)buf.Ptr())->iResourceId = ((DStaticPowerResourceD*)pR)->iResourceId;
  2144 			if(r != KErrNone)
  2145 				return r;
  2146 			pInfo->Append(buf);
  2147 			}
  2148 		numResources -= iStaticResDependencyCount;
  2149 		if((!numResources) || (!iDynamicResourceCount && !iDynamicResDependencyCount))
  2150 			return r;
  2151 		Lock();
  2152 		TUint resCount = 0;
  2153 		for(count = 0; count < iDynamicResourceList.Allocd(); count++)
  2154 			{
  2155 			pR = iDynamicResourceList[count];
  2156 			if(!pR)
  2157 				continue;
  2158 			if((resCount >= iDynamicResourceCount) || (resCount >= numResources))
  2159 				UNLOCK_RETURN(KErrNone);
  2160 			r = pR->GetInfo((TDes8*)buf.Ptr());  
  2161 			if(r != KErrNone)
  2162 				UNLOCK_RETURN(r);
  2163 			((TPowerResourceInfoV01*)buf.Ptr())->iResourceId = ((DDynamicPowerResource*)pR)->iResourceId;
  2164 			pInfo->Append(buf);
  2165 			resCount++;
  2166 			}
  2167 		numResources -= resCount;
  2168 		resCount = 0;
  2169 		for(count = 0; count < iDynamicResDependencyList.Allocd(); count++) 
  2170 			{
  2171 			pR = iDynamicResDependencyList[count];
  2172 			if(!pR)
  2173 				continue;
  2174 			if((resCount >= iDynamicResDependencyCount) || (resCount >= numResources))
  2175 				UNLOCK_RETURN(KErrNone);
  2176 			r = pR->GetInfo((TDes8*)buf.Ptr());
  2177 			if(r != KErrNone)
  2178 				UNLOCK_RETURN(r);
  2179 			((TPowerResourceInfoV01*)buf.Ptr())->iResourceId = ((DDynamicPowerResourceD*)pR)->iResourceId;
  2180 			pInfo->Append(buf);
  2181 			resCount++;
  2182 			}
  2183 		UnLock();
  2184 #endif
  2185 		return r;
  2186 		}
  2187 	GET_TARGET_CLIENT();
  2188 	SPowerResourceClientLevel* pCL = pC->iLevelList;
  2189 	for (count= 0; pCL; count++, pCL = pCL->iNextInList)
  2190 		{
  2191 		if(count >= aNumResources)
  2192 			continue;
  2193 #ifndef PRM_ENABLE_EXTENDED_VERSION
  2194 		pR = iStaticResourceArray[pCL->iResourceId-1];
  2195 #else
  2196 		GET_RESOURCE_FROM_LIST(pCL->iResourceId, pR);
  2197 #endif
  2198 		r = pR->GetInfo((TDes8*)buf.Ptr());
  2199         //Update Resource Id.
  2200         ((TPowerResourceInfoV01*)buf.Ptr())->iResourceId = pCL->iResourceId;
  2201 		if(r != KErrNone)
  2202 			UNLOCK_RETURN(r);
  2203 		pInfo->Append(buf);
  2204 		}
  2205 	aNumResources = count;
  2206 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetInfoOnResourcesInUseByClient, AcutalNoOfResources = %d", aNumResources));
  2207 	UNLOCK_RETURN(KErrNone);
  2208 	}
  2209 
  2210 /**
  2211 @publishedPartner
  2212 @prototype 9.5
  2213 
  2214 Request number of clients which has requirements on the resource level of the specified
  2215 resource. Resource ID starts from 1, so 0 can be used to get the number of clients
  2216 registered with resource manager.
  2217 
  2218 @param aClientId         ID of the client which is requesting number of clients
  2219                          holding requirement on specified resource.
  2220 @param aResourceId       ID of the resource. 
  2221 @param aNumClient        This is updated with number of clients having a requirement
  2222                          on resource level if valid resource ID is specified.
  2223                          If resource ID is 0, then it is updated with number of clients
  2224                          registered with PRM.
  2225 
  2226 @return  KErrNone if the operation was successful
  2227          KErrAccessDenied if the client ID could not found in the current list of
  2228                           registered clients or if the client was registered to be thread 
  2229 						  relative and this API is not called from the same thread. 
  2230          KErrNotFound     If this resource ID could not be found in the current list
  2231                           of registered resource and is also not 0.
  2232 
  2233 @pre Interrupts must be enabled
  2234 @pre Kernel must be unlocked
  2235 @pre No fast mutex can be held
  2236 @pre Call in a thread context but not from null thread or DFC thread1
  2237 @pre Can be used in a device driver
  2238 */
  2239 TInt DPowerResourceController::GetNumClientsUsingResource(TUint aClientId, TUint aResourceId, TUint& aNumClients)
  2240 	{
  2241 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetNumClientsUsingResource"));
  2242 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d", aClientId, aResourceId));
  2243 	DThread& thread = Kern::CurrentThread();	
  2244 	CHECK_CONTEXT(thread)
  2245 	SPowerResourceClient* pC = NULL;
  2246 	Lock();
  2247 	VALIDATE_CLIENT(thread);
  2248 	if(!aResourceId)
  2249 		{
  2250 		//Special case return the number of clients registered with resource controller.
  2251 		aNumClients = iClientCount + iUserSideClientCount;
  2252 		UNLOCK_RETURN(KErrNone);
  2253 		}
  2254 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2255 	DStaticPowerResource* pR = NULL;
  2256 	GET_RESOURCE_FROM_LIST(aResourceId, pR) 
  2257 #else
  2258 	if(aResourceId > iStaticResourceArrayEntries)
  2259 		UNLOCK_RETURN(KErrNotFound);
  2260 	DStaticPowerResource* pR = iStaticResourceArray[aResourceId-1];
  2261 	if(!pR)
  2262 		UNLOCK_RETURN(KErrNotFound);
  2263 #endif
  2264 	aNumClients = 0;
  2265 	for(SDblQueLink*pCL = pR->iClientList.First(); pCL != &pR->iClientList.iA; pCL=pCL->iNext)
  2266 	   aNumClients++;
  2267 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetNumClientsUsingResource, NumClients = %d", aNumClients));
  2268 	UNLOCK_RETURN(KErrNone);
  2269 	}
  2270 
  2271 /**
  2272 @publishedPartner
  2273 @prototype 9.5
  2274 
  2275 Request information on clients
  2276 If resource ID is valid, aInfo is updated with the information of the clients
  2277 which have a requirement on the resource level for the specified resource
  2278 If resource ID is 0, aInfo is updated with the information of the clients registered
  2279 with resource manager, starting from client ID 1.
  2280 The number of clients for which information will be provided will be equal to or less 
  2281 than the number specified in aNumClients.
  2282 @param aClientId        ID of the client which is requesting the information on
  2283                         the clients which holds requirement on specified
  2284                         resource's level change.
  2285 @param aResourceId      Id of the resource.
  2286 @param aNumClients		Number of clients whose information needs to be filled in aInfo
  2287 						i.e., it specifies the size of aInfo array.
  2288 @param aInfo            A pointer to an array of descriptor containing an information
  2289                         structure (TPowerClientInfoV01) to be filled in with
  2290                         the information on the client. It will be assumed that array
  2291                         allocated will be equal to the number passed in aNumClients.
  2292                         The Client must create the array of descriptors in kernel stack
  2293                         or heap.
  2294 
  2295 @return KErrNone if the operation was successful.
  2296         KErrNotFound if resource ID could not be found in the registered resource list and is not 0.
  2297 		KErrAccessDenied if client ID (aClientId) could not be found in the registered client
  2298 						 list or if the client was registered to be thread relative and this API is not
  2299 						 called from the same thread.
  2300         KErrArgument if aNumClients is 0 or aInfo is NULL or if size of aInfo is not sufficient to hold
  2301 					 client information of specified client number in aNumClients.
  2302 
  2303 @pre Interrupts must be enabled
  2304 @pre Kernel must be unlocked
  2305 @pre No fast mutex can be held
  2306 @pre Call in a thread context but not from null thread or DFC thread1
  2307 @pre Can be used in a device driver
  2308 */
  2309 TInt DPowerResourceController::GetInfoOnClientsUsingResource(TUint aClientId, TUint aResourceId, 
  2310 															  TUint& aNumClients, TAny* anInfo)
  2311 	{
  2312 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetInfoOnClientsUsingResource"));
  2313 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d, NumClients = %d", \
  2314 		                                                      aClientId, aResourceId, aNumClients));
  2315 	DThread& thread = Kern::CurrentThread();	
  2316 	CHECK_CONTEXT(thread)
  2317 	if(!anInfo || !aNumClients)
  2318 		return KErrArgument;
  2319 	SPowerResourceClient* pC = NULL;
  2320 	Lock();
  2321 	VALIDATE_CLIENT(thread);
  2322     TDes8 *pInfo = (TDes8*)anInfo;
  2323     if((TUint)(pInfo->MaxLength() - pInfo->Length()) < (sizeof(TPowerClientInfoV01) * aNumClients))
  2324         UNLOCK_RETURN(KErrArgument);
  2325     TPowerClientInfoV01 info;
  2326 	if(aResourceId == 0)
  2327 		{
  2328         TUint16 count = 0, resCount = 0;
  2329         for(count = 0; count < iClientList.Allocd(); count++)
  2330 		    {
  2331             if((resCount >= iClientCount) || (resCount >= aNumClients))
  2332 				break;
  2333             pC = iClientList[count];
  2334             if(!pC)
  2335 				continue;
  2336             resCount++;
  2337             info.iClientId = pC->iClientId;
  2338             info.iClientName = (TDesC8*)pC->iName;
  2339             pInfo->Append(TPckgC<TPowerClientInfoV01>(info));
  2340 	        }
  2341         aNumClients -= resCount;
  2342         resCount = 0;
  2343         for(count = 0; count < iUserSideClientList.Allocd(); count++)
  2344 	        {
  2345             if((resCount >= iUserSideClientCount) || (resCount >= aNumClients))
  2346 				break;
  2347             pC = iUserSideClientList[count];
  2348             if(!pC)
  2349 				continue;
  2350             resCount++;
  2351             info.iClientId = pC->iClientId;
  2352             info.iClientName = (TDesC8*)pC->iName;
  2353             pInfo->Append(TPckgC<TPowerClientInfoV01>(info));
  2354 			}
  2355 		aNumClients = iClientCount + iUserSideClientCount;
  2356 		UNLOCK_RETURN(KErrNone);
  2357 		}
  2358 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2359 	DStaticPowerResource* pR = NULL;
  2360 	GET_RESOURCE_FROM_LIST(aResourceId, pR) 
  2361 #else
  2362 	if(aResourceId > iStaticResourceArrayEntries)
  2363 		UNLOCK_RETURN(KErrNotFound);
  2364 	DStaticPowerResource* pR = iStaticResourceArray[aResourceId-1];
  2365 	if(!pR)
  2366 		UNLOCK_RETURN(KErrNotFound);
  2367 #endif
  2368 	SPowerResourceClientLevel* pCL = NULL;
  2369     TUint c = 0;
  2370 	for(SDblQueLink* pRC = pR->iClientList.First(); pRC != &pR->iClientList.iA; pRC = pRC->iNext, c++)
  2371 		{
  2372 		if(c >= aNumClients)
  2373 			continue;
  2374 		pCL = (SPowerResourceClientLevel*)pRC;
  2375 		if(pCL->iClientId & USER_SIDE_CLIENT_BIT_MASK)
  2376 			pC = iUserSideClientList[(TUint16)(pCL->iClientId & ID_INDEX_BIT_MASK)];
  2377 		else
  2378 			pC = iClientList[(TUint16)(pCL->iClientId & ID_INDEX_BIT_MASK)];
  2379 		info.iClientId = pC->iClientId;
  2380 		info.iClientName =  (TDesC8*)pC->iName;
  2381         pInfo->Append(TPckgC<TPowerClientInfoV01>(info));
  2382 		}
  2383 	aNumClients = c;
  2384 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetInfoOnClientsUsingResource, NumClients = %d", aNumClients));
  2385 	UNLOCK_RETURN(KErrNone);
  2386 	}
  2387 
  2388 /**
  2389 @publishedPartner
  2390 @prototype 9.5
  2391 
  2392 Request changing the state of a resource
  2393 NOTE: If a resource callback is specified for instantaneous resource, then callback
  2394       will be called after resource change and will be executed in the context of the
  2395       client thread.
  2396       If a resource callback is specified for long latency reosurces, then it will be
  2397       executed asynchronously.When the request is accepted the API returns immediately
  2398 	  and the calling thread is unblocked: the callback (called in the client's context) 
  2399 	  will be invoked when the resource change finally takes place.
  2400       If aCb is not specified (NULL by default) the API executes synchronously and will
  2401       only return when the resource change has taken place for long latency resource.
  2402       The client thread is blocked throughout
  2403       When state change for a shared resource is requested, only minimum state that
  2404       satisfy the requirement is guaranteed and it is not guaranteed for the absolute
  2405       value change.
  2406 
  2407 @param aClientId   ID of the client which is requesting the resource change.
  2408 @param aResourceId ID of the resource whose state is to be changed.
  2409 @param aNewState   The new state of the resource. This could be a binary value for a
  2410                    binary resource, an integer level for a multilevel resource or some
  2411                    platform specific token for a multi-property resource.
  2412 @param aCb         For Long latency resource
  2413                        A pointer to a resource callback object which encapsulates a
  2414                        callback function to be called whenever the resource state change
  2415                        happens (if left NULL the API will execute synchrounously).
  2416                    For Instantaneous resource
  2417                        A pointer to a resource callback object which encapsulates a callback
  2418                        function to be called after resource change. This executes in the
  2419                        context of the client thread.
  2420 
  2421 @return KErrNone   If the API is to be executed synchronously it indicates the change was
  2422                    successful, if the API is to be executed asynchronously it indicates
  2423                    the request to change the resource state has been accepted.
  2424         KErrNotFound if the resource ID could not be found in the current list of
  2425                      controllable resources.
  2426         KErrAccessDenied if the client ID could not be found in the list of
  2427                          registered clients or if the client was registered to be thread 
  2428 						 relative and this API is not called from the same thread or if the
  2429 						 resource is single user resource and another client is already holding 
  2430 						 the resource.
  2431         KErrNotReady if the request is issued before the resource controller completes its
  2432                      internal initialisation.
  2433         KErrUnderflow if the client has exceeded the reserved number of
  2434                       SPowerResourceClientLevel and the free pool is empty or if it is
  2435                       an asynchronous operation on a long latency resource and the client has 
  2436 					  exceeded the reserved number of TPowerRequest and the free pool is empty.
  2437 		KErrArgument if requested level is out of range (outside of min and max levels).
  2438 		KErrCorrupt  if internal data structure is corrupted.
  2439 		KErrPermissionDenied if the requested state of the resource is not accepted by its dependents. 
  2440 							 This error is valid only for dependent resource state change in extended version
  2441 							 of PRM.
  2442 
  2443 @pre Interrupts must be enabled
  2444 @pre Kernel must be unlocked
  2445 @pre No fast mutex can be held
  2446 @pre Call in a thread context but not from null thread or DFC thread1
  2447 @pre Can be used in a device driver
  2448 @pre Do not call synchronous version from DFC thread 0 for long latency resource 
  2449 */
  2450 TInt DPowerResourceController::ChangeResourceState(TUint aClientId, TUint aResourceId, TInt aNewState, 
  2451 												                                TPowerResourceCb* aCb)
  2452 	{
  2453 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::ChangeResourceState"));
  2454 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d, NewState = %d", aClientId, \
  2455 		                                                                          aResourceId, aNewState));
  2456 	DThread& thread = Kern::CurrentThread();	
  2457 	CHECK_CONTEXT(thread)
  2458 	if(iInitialised <= EResConCreated)
  2459 		return KErrNotReady;
  2460 	if(!aResourceId)
  2461 		return KErrNotFound;
  2462 	SPowerResourceClient* pC = NULL;
  2463 	TInt r = KErrNone;
  2464 	Lock();
  2465 	VALIDATE_CLIENT(thread);
  2466 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2467 	DStaticPowerResource *pR = NULL;
  2468 	GET_RESOURCE_FROM_LIST(aResourceId, pR) 
  2469 #else
  2470 	if(aResourceId > iStaticResourceArrayEntries)
  2471 		UNLOCK_RETURN(KErrNotFound);
  2472 	DStaticPowerResource* pR = iStaticResourceArray[aResourceId-1];
  2473 	if(!pR)
  2474 		UNLOCK_RETURN(KErrNotFound);
  2475 #endif
  2476 	//Return if the resource is already in that state and client is also the same.
  2477 	if((aNewState == pR->iCachedLevel) && ((TInt)aClientId == pR->iLevelOwnerId))
  2478 		UNLOCK_RETURN(KErrNone);
  2479 
  2480 	
  2481 	PRM_CLIENT_CHANGE_STATE_START_TRACE
  2482 	//If long latency resource requested synchronously from DFC thread 0 Panic
  2483 
  2484     const TDesC8* pDfc0 = &KDfcThread0Name;
  2485 	if((pR->LatencySet() && !aCb) && !(pDfc0->Compare(*(TDesC8*)thread.iName)))
  2486 		{
  2487 		UnLock();
  2488 		Panic(ECalledFromDfcThread0);
  2489 		}
  2490 	if(!pR->Usage() && !pR->iClientList.IsEmpty())
  2491 		{
  2492 		SPowerResourceClientLevel* pCL = (SPowerResourceClientLevel*)pR->iClientList.First();
  2493 		if((pCL != NULL) && (pCL->iClientId != pC->iClientId))
  2494 			{
  2495 			r = KErrAccessDenied;
  2496 			PRM_CLIENT_CHANGE_STATE_END_TRACE
  2497 			UNLOCK_RETURN(r);
  2498 			}
  2499 		}
  2500 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2501 	if(aResourceId & KIdMaskDynamic)
  2502 		{
  2503 		//Resource in the process of deregistration
  2504 		if(((DDynamicPowerResource*)pR)->LockCount() == 0) 
  2505 			{
  2506 			r = KErrNotFound;
  2507 			PRM_CLIENT_CHANGE_STATE_END_TRACE
  2508 			UNLOCK_RETURN(r);
  2509 			}
  2510 		}
  2511 #endif
  2512     //Validate requested level
  2513     TPowerResourceInfoBuf01 buf;
  2514     r = pR->GetInfo((TDes8*)buf.Ptr());
  2515     if(r != KErrNone)
  2516 		{
  2517 		PRM_CLIENT_CHANGE_STATE_END_TRACE
  2518 		UNLOCK_RETURN(r);
  2519 		}
  2520     TPowerResourceInfoV01 *pBuf = (TPowerResourceInfoV01*)buf.Ptr();
  2521     if(((pBuf->iMinLevel > pBuf->iMaxLevel) && ((aNewState > pBuf->iMinLevel) || (aNewState < pBuf->iMaxLevel))) 
  2522 		    || ((pBuf->iMaxLevel > pBuf->iMinLevel) && ((aNewState > pBuf->iMaxLevel) || (aNewState < pBuf->iMinLevel))))
  2523 		{
  2524         r = KErrArgument;
  2525         PRM_CLIENT_CHANGE_STATE_END_TRACE
  2526         UNLOCK_RETURN(r);
  2527 		}
  2528 
  2529 	TPowerRequest* req;
  2530 	SPowerRequest* pS=NULL;
  2531 	if(pR->LatencySet() && aCb)
  2532 		{
  2533 		// Get request object from free pool, as it is long latency reosurce as client
  2534 		// will be unblocked once message is sent to controller, so cant use thread message.
  2535 		if(pC->iReservedRm ==0 && !iRequestPoolCount)
  2536 			{
  2537             r = KErrUnderflow;
  2538             PRM_CLIENT_CHANGE_STATE_END_TRACE
  2539 			UNLOCK_RETURN(r);
  2540 			}
  2541 
  2542 		LIST_POP(iRequestPool, pS, iNext);
  2543 		if(!pS)
  2544 			UNLOCK_RETURN(KErrCorrupt); //This should not happen
  2545 		if(pC->iReservedRm==0)
  2546 			{
  2547 			iRequestPoolCount--;
  2548 			pC->iUnderFlowRmCount++;
  2549 			}
  2550 		else
  2551 		    pC->iReservedRm--;
  2552 		req=&pS->iRequest;
  2553 		pC->iPendingReqCount++;
  2554 		}
  2555 	else
  2556         req=(TPowerRequest*)&TPowerRequest::Get();
  2557 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2558 	if(aResourceId & KIdMaskDynamic)
  2559 		((DDynamicPowerResource*)pR)->Lock();
  2560 #endif
  2561 	req->Level() = aNewState;
  2562 	req->ResourceId() = aResourceId;
  2563 	req->ClientId() = aClientId;
  2564 	req->ReqType() = TPowerRequest::EChange;
  2565 	req->Resource() = pR;
  2566 	if(aCb)
  2567 		{
  2568 		aCb->iResult = KErrNone;
  2569 		aCb->iResourceId = aResourceId;
  2570 		aCb->iClientId = aClientId;
  2571 		}
  2572 	req->ResourceCb() = aCb;
  2573 	if(pR->LatencySet())
  2574 		{
  2575 		UnLock();
  2576 		if(aCb)
  2577 			{
  2578 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2579 			if (aCb->iResourceId & KIdMaskResourceWithDependencies) //Dependency resource
  2580 				{
  2581 				req->Send(iMsgQDependency); // Send the request to DFC thread.
  2582 				return KErrNone;
  2583 				}
  2584 			else
  2585 #endif
  2586 				{
  2587 				req->Send(iMsgQ); // Send the request to Resource Controler thread.
  2588 				return KErrNone;
  2589 				}
  2590 			}
  2591 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2592 		if(aResourceId & KIdMaskResourceWithDependencies) //Dependency resource
  2593 			{
  2594 			r = req->SendReceive(iMsgQDependency); // Send the request to DFC thread.
  2595 			}
  2596 #endif
  2597 		else
  2598 			{
  2599 			r = req->SendReceive(iMsgQ); // Block till the controller completes with the request.
  2600 			}
  2601 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2602 		Lock();
  2603 		if(aResourceId & KIdMaskDynamic)
  2604 			((DDynamicPowerResource*)pR)->UnLock();
  2605 		UnLock();
  2606 #endif
  2607 		return r;
  2608 		}
  2609 	if(pR->Usage())
  2610 		{
  2611 		r = CheckLevelAndAddClient(pC, req);
  2612 		if((r != KErrNone)|| !req->RequiresChange())
  2613 			{
  2614 			req->Level() = pR->iCachedLevel;
  2615 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2616 		    if(aResourceId & KIdMaskDynamic)
  2617 				((DDynamicPowerResource*)pR)->UnLock();
  2618 #endif
  2619 			UnLock();
  2620 			if(aCb)
  2621 				{
  2622 				//Invoke callback function
  2623 				aCb->iCallback(req->ClientId(), aResourceId, req->Level(), pR->iLevelOwnerId, r, aCb->iParam);
  2624 				//Mark the callback object to act properly during cancellation of this request.
  2625 				aCb->iResult = KErrCompletion; 
  2626 				}
  2627 			PRM_CLIENT_CHANGE_STATE_END_TRACE
  2628 			return(r);
  2629 			}
  2630 		}
  2631 	else if(pR->iLevelOwnerId == -1)
  2632 		{
  2633 		/* Add client Level */
  2634 		if(pC->iReservedCl<=0 && !iClientLevelPoolCount)
  2635 			{
  2636 			r = KErrUnderflow;
  2637 			PRM_CLIENT_CHANGE_STATE_END_TRACE
  2638 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2639 			if(aResourceId & KIdMaskDynamic)
  2640 				((DDynamicPowerResource*)pR)->UnLock();
  2641 #endif
  2642 			UnLock();
  2643      		return(r);
  2644 			}
  2645 		SPowerResourceClientLevel* pSCL=NULL;
  2646 		LIST_POP(iClientLevelPool, pSCL, iNextInList);
  2647 		pSCL->iClientId=aClientId;
  2648 		pSCL->iResourceId=aResourceId;
  2649 		pSCL->iLevel=aNewState;
  2650 		LIST_PUSH(pC->iLevelList, pSCL, iNextInList);
  2651 		pR->iClientList.Add(pSCL);
  2652 		if(pC->iReservedCl==0)
  2653 			{
  2654 			iClientLevelPoolCount--;
  2655 			pC->iUnderFlowClCount++;
  2656 			}
  2657 		else
  2658 		     pC->iReservedCl--;
  2659 		}
  2660 	else
  2661 		{
  2662 		//Update the level in the client list.
  2663 		SPowerResourceClientLevel* pSCL = (SPowerResourceClientLevel*)pR->iClientList.First();
  2664 		pSCL->iLevel = aNewState;
  2665 		}
  2666 	UnLock();
  2667 	r = pR->DoRequest(*req);
  2668 	Lock();
  2669 	if(r==KErrNone)
  2670 		{
  2671 		//Notification to clients
  2672 		CompleteNotifications(req->ClientId(), pR, req->Level(), r, aClientId, EFalse);
  2673 		//Cache the state
  2674 		pR->iCachedLevel=req->Level();
  2675 		pR->iLevelOwnerId=req->ClientId();
  2676 		//Update resource details for Idle
  2677 		if(pR->iIdleListEntry)
  2678 			{
  2679             pR->iIdleListEntry->iLevelOwnerId=req->ClientId();
  2680 			pR->iIdleListEntry->iCurrentLevel=req->Level();
  2681 			}
  2682 		}
  2683 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2684 	if(aResourceId & KIdMaskDynamic)
  2685 		((DDynamicPowerResource*)pR)->UnLock();
  2686 #endif
  2687 	UnLock();
  2688 	if(aCb)
  2689 		{
  2690 		//Invoke callback function
  2691 		aCb->iCallback(req->ClientId(), aResourceId, req->Level(), pR->iLevelOwnerId, r, aCb->iParam);
  2692 		aCb->iResult = KErrCompletion; //Mark the callback object to act properly during cancellation of this request.
  2693 		}
  2694 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::ChangeResourceState, Level = %d", req->Level()));
  2695     PRM_CLIENT_CHANGE_STATE_END_TRACE
  2696     return r;
  2697 	}
  2698 
  2699 /**
  2700 @publishedPartner
  2701 @prototype 9.5
  2702 
  2703 Request the state of the resource synchronously
  2704 
  2705 @param aClientId  ID of the client which is requesting the resource state.
  2706 @param aResourceId ID of the resource whose state is being requested.
  2707 @param aCached     If ETrue, cached value will be updated in aState.
  2708                    If EFalse, aState will be updated after the resource
  2709                    state is read from resource.
  2710 @param aState      Returns the resource state if operation was successful. This
  2711                    could be a binary value for a binary resource, an integer level
  2712                    for a multilevel resource or some platform specific tolen for a
  2713                    multi-property resource.
  2714 @param aLevelOwnerId Returns the Id of the client that is currently holding the resource.
  2715 					 -1	is returned when no client is holding the resource.
  2716 
  2717 @return KErrNone   if operation was successful
  2718         KErrAccessDenied if the client ID could not be found in the current list
  2719                          of registered clients or if the client was registered to be thread
  2720 						 relative and this API is not called from the same thread. 
  2721         KErrNotFound if this resource ID could not be found in the current list
  2722                      of controllable resources.
  2723         KErrNotReady if the request is issued before the resource controller completes
  2724                      its internal initialization.
  2725 
  2726 
  2727 @pre Interrupts must be enabled
  2728 @pre Kernel must be unlocked
  2729 @pre No fast mutex can be held
  2730 @pre Call in a thread context but not from null thread or DFC thread1
  2731 @pre Can be used in a device driver
  2732 @pre Do not call from DFC thread 0 for long latency resource with caching disabled.
  2733 */
  2734 TInt DPowerResourceController::GetResourceState(TUint aClientId, TUint aResourceId, TBool aCached, TInt& aState, 
  2735 																						TInt& aLevelOwnerId)
  2736 	{
  2737 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetResourceState(synchronous)"));
  2738 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d, Cached = %d", aClientId, aResourceId, aCached));
  2739 
  2740 	DThread& thread = Kern::CurrentThread();	
  2741 	CHECK_CONTEXT(thread)
  2742 	if(iInitialised <= EResConCreated) 
  2743 		return KErrNotReady;
  2744 	SPowerResourceClient* pC = NULL;
  2745 	TInt r = KErrNone;
  2746 	Lock();
  2747 	VALIDATE_CLIENT(thread);
  2748 	if(!aResourceId)
  2749 		UNLOCK_RETURN(KErrNotFound);
  2750 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2751 	DStaticPowerResource *pR = NULL;
  2752 	GET_RESOURCE_FROM_LIST(aResourceId, pR) 
  2753 	if(aResourceId & KIdMaskDynamic)
  2754 		{
  2755 		if(((DDynamicPowerResource*)pR)->LockCount() == 0)
  2756 			UNLOCK_RETURN(KErrNotFound);
  2757 		}
  2758 #else
  2759 	if(aResourceId > iStaticResourceArrayEntries)
  2760 		UNLOCK_RETURN(KErrNotFound);
  2761 	DStaticPowerResource *pR = iStaticResourceArray[aResourceId-1];
  2762 	if(!pR)
  2763 		UNLOCK_RETURN(KErrNotFound);
  2764 #endif
  2765 	PRM_RESOURCE_GET_STATE_START_TRACE
  2766 	//Panic if long latency resource called to execute synchronously from DFC thread0
  2767 	const TDesC8* pDfc0 = &KDfcThread0Name;
  2768 	if((!aCached && pR->LatencyGet()) && !(pDfc0->Compare(*(TDesC*)thread.iName)))
  2769 		{
  2770 		UnLock();
  2771 		Panic(ECalledFromDfcThread0);
  2772 		}
  2773 	if(aCached)
  2774 		{
  2775 		//Return the cached value.
  2776 		aState = pR->iCachedLevel;
  2777 		aLevelOwnerId = pR->iLevelOwnerId;
  2778         PRM_RESOURCE_GET_STATE_END_TRACE
  2779     	UNLOCK_RETURN(KErrNone);
  2780 		}
  2781 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2782 	if(aResourceId & KIdMaskDynamic)
  2783 		((DDynamicPowerResource*)pR)->Lock();
  2784 #endif
  2785 	//Call from thread Id.
  2786 	TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
  2787 	req->ResourceId() = aResourceId;
  2788 	req->ReqType() = TPowerRequest::EGet;
  2789 	req->ClientId() = aClientId;
  2790 	req->Resource() = pR;
  2791 	req->ResourceCb() = NULL;
  2792 	if(pR->LatencyGet())
  2793 		{
  2794 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2795 		if(	req->ResourceId() & KIdMaskResourceWithDependencies ) // Dependency Resource
  2796 			{
  2797 			UnLock();
  2798 			req->SendReceive(iMsgQDependency); //Send the request to DFC Thread
  2799 			Lock();
  2800 			}
  2801 		else  // Plain resource
  2802 #endif
  2803 			{
  2804 			UnLock();
  2805 			req->SendReceive(iMsgQ);
  2806 			Lock();
  2807 			}
  2808 		}
  2809 	else
  2810 		{
  2811 		UnLock();
  2812 		r = pR->DoRequest(*req); // Call PSL to get the state of resource.
  2813 		Lock();
  2814 		if(r==KErrNone)
  2815 			{
  2816 			//Update the cache value and cache for idle thread usage if requested for this resource.
  2817 			pR->iCachedLevel=req->Level();
  2818 			if(pR->iIdleListEntry)
  2819 				{
  2820 				SIdleResourceInfo* pI=pR->iIdleListEntry;
  2821 				pI->iCurrentLevel=req->Level();
  2822 				}
  2823 			}
  2824 		}
  2825 	aState = req->Level();
  2826 	aLevelOwnerId = pR->iLevelOwnerId;
  2827 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2828 	if(aResourceId & KIdMaskDynamic)
  2829 		((DDynamicPowerResource*)pR)->UnLock();
  2830 #endif
  2831 	UnLock();
  2832     __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetResourceState(synchronous), Level = %d", aState));
  2833 	if(pR->LatencyGet()) //For long latency resource btrace is done in controller thread.
  2834 		return r;
  2835 	PRM_RESOURCE_GET_STATE_END_TRACE
  2836 	return r;
  2837 	}
  2838 
  2839 /**   
  2840 @publishedPartner
  2841 @prototype 9.5
  2842 
  2843 Request the state of the resource asynchrounously for long latency resource and
  2844 synchronously for instantaneous resource
  2845 
  2846 @param aClientId  ID of the client which is requesting the resource state.
  2847 @param aResourceId ID of the resource whose state is being requested.
  2848 @param aCached If ETrue, cached value will be updated in aState
  2849                If EFalse, will be updated after the resource state is read from resource
  2850 @param aCb     For long latency resource:
  2851                A pointer to a resource callback object which encapsulates a callback function
  2852                to be called whenever the state of the resource is available for the long
  2853                latency resource (executes in the context of resource manager)
  2854                For instantaneous resource:
  2855                A pointer to a resource callback object which encapsulates a callback
  2856                function to be called after the resource state is read. This is executed
  2857                synchronously in the context of the calling thread.
  2858                NOTE: The client must create the callback object in kernel heap or
  2859                data section.
  2860 
  2861 @return KErrNone if the operation was successful
  2862 		KErrArgument if callback object is NULL
  2863         KErrAccessDenied if the client ID could not be found in the current list
  2864                          of registered clients or if the client was registered to be thread
  2865 						 relative and this API is not called from the same thread.
  2866         KErrNotFound if this resource ID could not be found in the current list
  2867                      of controllable resources.
  2868         KErrNotReady if the request is issued before the resource controller completes
  2869                      its internal initialisation
  2870         KErrUnderflow if the client has exceeded the reserved number of TPowerRequest
  2871                       and the TPowerRequest free pool is empty for long latency resource.
  2872 		KErrCorrupt if internal data structure is corrupt.
  2873 
  2874 @pre Interrupts must be enabled
  2875 @pre Kernel must be unlocked
  2876 @pre No fast mutex can be held
  2877 @pre Call in a thread context but not from null thread or DFC thread1
  2878 @pre Can be used in a device driver
  2879 */
  2880 TInt DPowerResourceController::GetResourceState(TUint aClientId, TUint aResourceId, TBool aCached,  TPowerResourceCb& aCb)
  2881 	{
  2882 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetResourceState(asynchronous)"));
  2883 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d, Cached = %d", aClientId, aResourceId, aCached));
  2884 
  2885 	DThread& thread = Kern::CurrentThread();	
  2886 	CHECK_CONTEXT(thread)
  2887 	if(iInitialised <= EResConCreated) 
  2888 		return KErrNotReady;
  2889 	SPowerResourceClient* pC = NULL;
  2890 	TInt r = KErrNone;
  2891 	Lock();
  2892 	VALIDATE_CLIENT(thread);
  2893 	if(!aResourceId)
  2894 		UNLOCK_RETURN(KErrNotFound);
  2895 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2896 	DStaticPowerResource *pR = NULL;
  2897 	GET_RESOURCE_FROM_LIST(aResourceId, pR) 
  2898 	if(aResourceId & KIdMaskDynamic)
  2899 		{
  2900 		//Dynamic resource in process of deregistration
  2901 		if(((DDynamicPowerResource*)pR)->LockCount() == 0)
  2902 			UNLOCK_RETURN(KErrNotFound);
  2903 		}
  2904 #else
  2905 	if(aResourceId > iStaticResourceArrayEntries)
  2906 		UNLOCK_RETURN(KErrNotFound);
  2907 	DStaticPowerResource *pR = iStaticResourceArray[aResourceId-1];
  2908 	if(!pR)
  2909 		UNLOCK_RETURN(KErrNotFound);
  2910 #endif
  2911 	aCb.iResult = KErrNone;
  2912 	aCb.iResourceId = aResourceId;
  2913 	aCb.iClientId = aClientId;
  2914 
  2915 	PRM_RESOURCE_GET_STATE_START_TRACE
  2916 	if(aCached) //Call the callback directly
  2917 		{
  2918 		UnLock();
  2919 		aCb.iCallback(aClientId, aResourceId, pR->iCachedLevel, pR->iLevelOwnerId, KErrNone, aCb.iParam);
  2920 		aCb.iResult = KErrCompletion; //Mark the callback object to act properly during cancellation of this request.
  2921 #ifdef PRM_INSTRUMENTATION_MACRO
  2922 		TInt aState = pR->iCachedLevel;
  2923         PRM_RESOURCE_GET_STATE_END_TRACE
  2924 #endif
  2925 		return(KErrNone);
  2926 		}
  2927 	TPowerRequest* req=NULL;
  2928 	if(pR->LatencyGet())
  2929 		{
  2930 		//Check the client quota of requests
  2931 		if(pC->iReservedRm==0 && !iRequestPoolCount)
  2932 			UNLOCK_RETURN(KErrUnderflow);
  2933 		if(pC->iReservedRm ==0)
  2934 			{
  2935 			iRequestPoolCount--;
  2936 			pC->iUnderFlowRmCount++;
  2937 			}
  2938 		else
  2939 		    pC->iReservedRm--;
  2940 		//Get the request from pool
  2941 		SPowerRequest* pS;
  2942 		LIST_POP(iRequestPool, pS, iNext);
  2943 		if(!pS)
  2944 			UNLOCK_RETURN(KErrCorrupt); //This should not be called
  2945 		req = &pS->iRequest;
  2946 		//Increment pending request count of the client
  2947 		pC->iPendingReqCount++;
  2948 		}
  2949 	else
  2950 		//Asynchronous instantaneous resource execute in the context of client thread.
  2951 		req = (TPowerRequest*)&TPowerRequest::Get();
  2952 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2953 	if(aResourceId & KIdMaskDynamic)
  2954 		((DDynamicPowerResource*)pR)->Lock();
  2955 #endif
  2956 	UnLock();
  2957 	req->ReqType() = TPowerRequest::EGet;
  2958 	req->ResourceId() = aResourceId;
  2959 	req->ClientId() = aClientId;
  2960 	req->Resource() = pR;
  2961 	req->ResourceCb() = &aCb;
  2962 	if(pR->LatencyGet())
  2963 		{
  2964 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2965 		if(	req->ResourceId() & KIdMaskResourceWithDependencies ) // Dependency Resource
  2966 			{
  2967 			req->Send(iMsgQDependency); // Send the request to DFC thread.
  2968 			}
  2969 		else  // Plain resource
  2970 #endif
  2971 			{
  2972 			req->Send(iMsgQ);
  2973 			}
  2974 		}
  2975 	else
  2976 		{
  2977 		r = pR->DoRequest(*req);
  2978 		Lock();
  2979 		if(r == KErrNone)
  2980 			{
  2981 			//Update the cache value and cache for idle thread usage if requested for this resource.
  2982 			pR->iCachedLevel = req->Level();
  2983 			if(pR->iIdleListEntry)
  2984 				pR->iIdleListEntry->iCurrentLevel=req->Level();
  2985 			}
  2986 #ifdef PRM_ENABLE_EXTENDED_VERSION
  2987 		if(aResourceId & KIdMaskDynamic)
  2988 			((DDynamicPowerResource*)pR)->UnLock();
  2989 #endif
  2990 		UnLock();
  2991 		// Call the client callback function directly as it is already executing in the context of client thread.
  2992 		aCb.iCallback(aClientId, aResourceId, req->Level(), pR->iLevelOwnerId, r, aCb.iParam);
  2993 		aCb.iResult = KErrCompletion; //Mark the callback object to act properly during cancellation of this request.
  2994 		}
  2995 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetResourceState(asynchronous), Level = %d", req->Level()));
  2996 	if(pR->LatencyGet())
  2997 		return r;
  2998 #ifdef PRM_INSTRUMENTATION_MACRO
  2999 	TInt aState = req->Level();
  3000 	PRM_RESOURCE_GET_STATE_END_TRACE
  3001 #endif
  3002 	return r;
  3003 	}
  3004 
  3005 
  3006 /**
  3007 @publishedPartner
  3008 @prototype 9.5
  3009 
  3010 Cancel an asynchronous request(or its callback).
  3011 
  3012 @param aClientId       ID of the client which is requesting the cancellation of the request.
  3013 @param aResourceId     ID for the resource which the request that is being cancelled operates
  3014                        upon.
  3015 @param aCb             A reference to the resource callback object specified with the request
  3016                        that is being cancelled.
  3017 
  3018 @return KErrCancel if the request was cancelled.
  3019         KErrNotFound if this resource ID could not be found in the current list of controllable
  3020                      resources.
  3021         KErrCompletion if request is no longer pending.
  3022         KErrAccessDenied if the client ID could not be found in the current list of registered
  3023 		clients or if the client was registered to be thread relative and this API is not called
  3024 		from the same thread or if client is not the same that requested the resource state change.
  3025 		KErrInUse if the request cannot be cancelled as processing of the request already started 
  3026 		and will run to completion. 
  3027 
  3028 @pre Interrupts must be enabled
  3029 @pre Kernel must be unlocked
  3030 @pre No fast mutex can be held
  3031 @pre Call in a thread context but not from null thread or DFC thread1
  3032 @pre Can be used in a device driver
  3033 */
  3034 TInt DPowerResourceController::CancelAsyncRequestCallBack(TUint aClientId, TUint aResourceId, TPowerResourceCb& aCb)
  3035 	{
  3036     TInt r = KErrInUse;
  3037 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::CancelAsyncRequestCallBack"));
  3038 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d", aClientId, aResourceId));
  3039 	DThread& thread = Kern::CurrentThread();	
  3040 	CHECK_CONTEXT(thread)
  3041 	SPowerResourceClient* pC = NULL;
  3042 	Lock();
  3043 	VALIDATE_CLIENT(thread);
  3044 	if((!aResourceId) || (aCb.iResourceId != aResourceId))
  3045 		UNLOCK_RETURN(KErrNotFound);
  3046 #ifdef PRM_INSTRUMENTATION_MACRO
  3047 #ifdef PRM_ENABLE_EXTENDED_VERSION
  3048     DStaticPowerResource *pR = NULL;
  3049 	GET_RESOURCE_FROM_LIST(aResourceId, pR)
  3050 #else
  3051 	DStaticPowerResource *pR = iStaticResourceArray[aResourceId-1];
  3052 	if(!pR)
  3053 		UNLOCK_RETURN(KErrNotFound);
  3054 #endif
  3055 #endif
  3056 	if(aCb.iClientId != aClientId)
  3057 		{
  3058         __KTRACE_OPT(KRESMANAGER, Kern::Printf("aCb.iClientId = 0x%x, aClientId = 0x%x", aCb.iClientId, aClientId));
  3059         r = KErrAccessDenied;
  3060 #ifdef PRM_INSTRUMENTATION_MACRO
  3061         PRM_RESOURCE_CANCEL_LONGLATENCY_OPERATION_TRACE
  3062 #endif
  3063         UNLOCK_RETURN(r);
  3064 		}
  3065 	if(aCb.iResult == KErrCompletion)
  3066 		{
  3067         r = KErrCompletion;
  3068 #ifdef PRM_INSTRUMENTATION_MACRO
  3069         PRM_RESOURCE_CANCEL_LONGLATENCY_OPERATION_TRACE
  3070 #endif
  3071 		UNLOCK_RETURN(r);
  3072 		}
  3073 	//Search in the controller message queue for this message
  3074 #ifdef PRM_ENABLE_EXTENDED_VERSION
  3075 	if(aResourceId & KIdMaskResourceWithDependencies) //long latency resource with dependency and will be processed in dependency thread.
  3076 		{
  3077 		//Search in the controller message queue for this message
  3078 		for(SDblQueLink* pRM = iMsgQDependency->iQ.First(); pRM != &(iMsgQDependency->iQ.iA); pRM = pRM->iNext)
  3079 			{
  3080 			TMessageBase* pMsgQ = (TMessageBase*)pRM;
  3081 			TPowerRequest* pReq=(TPowerRequest*)pMsgQ;
  3082 			if(pReq->ResourceCb() == &aCb)
  3083 				{
  3084 				r = KErrCancel;
  3085 				pRM->Deque();
  3086 				pMsgQ->iState = TMessageBase::EFree; //Reset the state
  3087 				MoveRequestToFreePool(pReq);
  3088 #ifdef PRM_INSTRUMENTATION_MACRO
  3089 				PRM_RESOURCE_CANCEL_LONGLATENCY_OPERATION_TRACE
  3090 #endif
  3091 				UNLOCK_RETURN(r);
  3092 				}
  3093 			}
  3094 		}
  3095 	else // long latency resource without dependency and will be processed in RC thread.
  3096 #endif
  3097 		{
  3098 		for(SDblQueLink* pRM = iMsgQ->iQ.First(); pRM != &(iMsgQ->iQ.iA); pRM = pRM->iNext)
  3099 			{
  3100 			TMessageBase* pMsgQ = (TMessageBase*)pRM;
  3101 			TPowerRequest* pReq=(TPowerRequest*)pMsgQ;
  3102 			if(pReq->ResourceCb() == &aCb)
  3103 				{
  3104 				r = KErrCancel;
  3105 				pRM->Deque();
  3106 				pMsgQ->iState = TMessageBase::EFree; //Reset the state
  3107 				MoveRequestToFreePool(pReq);
  3108 #ifdef PRM_INSTRUMENTATION_MACRO
  3109 				PRM_RESOURCE_CANCEL_LONGLATENCY_OPERATION_TRACE
  3110 #endif
  3111 				UNLOCK_RETURN(r);
  3112 				}
  3113 			}
  3114 		}
  3115 #ifdef PRM_INSTRUMENTATION_MACRO
  3116     PRM_RESOURCE_CANCEL_LONGLATENCY_OPERATION_TRACE
  3117 #endif
  3118 	UNLOCK_RETURN(r);
  3119 	}
  3120 
  3121 /**
  3122 @publishedPartner
  3123 @prototype 9.5
  3124 
  3125 Request notification of changes to the state of a resource.
  3126 
  3127 @param aClientId     ID of the client which is requesting the notification.
  3128 @param aResourceId   ID of the resource for which notification of state changes
  3129                      is being requested.
  3130 @param aN            A reference to a notification object which encapsulates a callback
  3131                      function to be called whenever a resource state change takes place.
  3132                      NOTE: The client must create the notification object in kernel heap
  3133                            or data section.
  3134 
  3135 @return KErrNone if the operation of requesting a notification was successful.
  3136         KErrNotFound if this resource ID could not be found in the current list
  3137                      of controllable resources.
  3138         KErrAccessDenied if the client ID could not be found in the current
  3139                          list of registered clients or if the client was registered to be 
  3140 						 thread relative and this API is not called from the same thread. 
  3141 		KErrInUse if the passed notification object is used already.
  3142 NOTE: This API should return immediately; however the notification will
  3143 only happen when a resource change occurs.Notification request is idempotent, 
  3144 if the same notification has already been requested for this resource ID, 
  3145 the API returns with no further action.Notifications remain queued until they are cancelled.
  3146 
  3147 @pre Interrupts must be enabled
  3148 @pre Kernel must be unlocked
  3149 @pre No fast mutex can be held
  3150 @pre Call in a thread context but not from null thread or DFC thread1
  3151 @pre Can be used in a device driver
  3152 */
  3153 TInt DPowerResourceController::RequestNotification(TUint aClientId, TUint aResourceId, DPowerResourceNotification& aN)
  3154 	{
  3155     TInt r = KErrNone;    
  3156 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RequestNotification(unconditional)"));
  3157 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d", aClientId, aResourceId));
  3158 	DThread& thread = Kern::CurrentThread();	
  3159 	CHECK_CONTEXT(thread)
  3160 	SPowerResourceClient* pC = NULL;
  3161 	Lock();
  3162 	VALIDATE_CLIENT(thread);
  3163 	if((!aResourceId))
  3164 		{
  3165         r = KErrNotFound;
  3166         PRM_POSTNOTIFICATION_REGISTER_TRACE
  3167 		UNLOCK_RETURN(r);
  3168 		}
  3169 #ifdef PRM_ENABLE_EXTENDED_VERSION
  3170 	DStaticPowerResource *pR = NULL;
  3171 	GET_RESOURCE_FROM_LIST(aResourceId, pR)
  3172 #else
  3173 	if(aResourceId > iStaticResourceArrayEntries)
  3174 		{
  3175         r = KErrNotFound;
  3176 		PRM_POSTNOTIFICATION_REGISTER_TRACE
  3177 		UNLOCK_RETURN(r);
  3178 		}
  3179 
  3180 	DStaticPowerResource *pR = iStaticResourceArray[aResourceId-1];
  3181 	if(!pR)
  3182 		{
  3183 		r = KErrNotFound;
  3184 		PRM_POSTNOTIFICATION_REGISTER_TRACE
  3185 		UNLOCK_RETURN(r);
  3186 		}
  3187 #endif
  3188 	if(aN.iRegistered) //Check if the same notification object is used already
  3189 		{
  3190         r = KErrInUse;
  3191         PRM_POSTNOTIFICATION_REGISTER_TRACE
  3192 		UNLOCK_RETURN(r);
  3193 		}
  3194 	aN.iRegistered++;
  3195 	aN.iType = DPowerResourceNotification::EUnconditional;
  3196 	aN.iOwnerId=(TUint16)aClientId;
  3197 	aN.iCallback.iClientId= aClientId;
  3198 	aN.iCallback.iResourceId=aResourceId;
  3199 	//Add to resource notification list
  3200 	pR->iNotificationList.Add(&(aN.iNotificationLink));
  3201 	//Add to client notification list
  3202 	LIST_PUSH(pC->iNotificationList, &aN, iNextInClient);
  3203     PRM_POSTNOTIFICATION_REGISTER_TRACE
  3204 	UNLOCK_RETURN(KErrNone);
  3205 	}
  3206 
  3207 /**
  3208 @publishedPartner
  3209 @prototype 9.5
  3210 
  3211 Request notification when the state of a resource reaches a specified threshold or
  3212 goes above or below that threshold (for multilevel resource only) based on direction.
  3213 In other words it is issued when a threshold on the specified resource state is crossed
  3214 in the direction specified.
  3215 
  3216 @param aClientId  ID of the client which is requesting the notification.
  3217 @param aResourceId ID for the resource whose notification of state changes is
  3218                    being requested.
  3219 @param aN          A reference to a notification object which encapsulates a callback
  3220                    function to be called whenever the conditions to issue the notification
  3221                    (specified in the API) are met.
  3222                    NOTE: The client must create the notification object in kernel heap
  3223                    or data section.
  3224 @param aThreshold  The level of the resource state that will trigger the notification
  3225                    when reached.
  3226 @param aDirection  Specifies the direction of change of the resource state that will
  3227                    trigger a notification. EFalse means the notification will be issued
  3228                    when the resource state change to a specified threshold value or below
  3229                    the specified threshold, ETrue means the notification will be issued
  3230                    when the resource state change to a specified threshold value or above
  3231                    the specified threshold.
  3232 
  3233 
  3234 
  3235 @return KErrNone if the operation of requesting a notification was successful.
  3236         KErrNotFound if this resource ID could not be found in the current list
  3237                      of controllable reosurces.
  3238         KErrAccessDenied if the client ID could not be found in the list of
  3239                          registered clients or if the client was registered to be thread
  3240 						 relative and this API is not called from the same thread. 
  3241 		KErrInUse if the passed notification object is used already.
  3242 		KErrArgument if the specified threshold is out of range.
  3243 NOTE: This API should return immediately; however the notification will only
  3244 happen when a resource change occurs. Notification request is idempotent, 
  3245 if the same notification has already been requested for this resource ID, 
  3246 the API returns with no further action. Notification remain queued until they are cancelled.
  3247 
  3248 @pre Interrupts must be enabled
  3249 @pre Kernel must be unlocked
  3250 @pre No fast mutex can be held
  3251 @pre Call in a thread context but not from null thread or DFC thread1
  3252 @pre Can be used in a device driver
  3253 */
  3254 TInt DPowerResourceController::RequestNotification(TUint aClientId, TUint aResourceId, DPowerResourceNotification& aN, 
  3255 																					TInt aThreshold, TBool aDirection)
  3256 	{
  3257     TInt r = KErrNone;
  3258 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RequestNotification(conditional)"));
  3259 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d, Threshold = %d, Direction = %d", \
  3260 																aClientId, aResourceId, aThreshold, aDirection));
  3261 	DThread& thread = Kern::CurrentThread();	
  3262 	CHECK_CONTEXT(thread)
  3263 	Lock();
  3264 	SPowerResourceClient* pC = NULL;
  3265 	VALIDATE_CLIENT(thread);
  3266 	if(!aResourceId)
  3267 		{
  3268         r = KErrNotFound;
  3269 		PRM_POSTNOTIFICATION_REGISTER_TRACE
  3270 		UNLOCK_RETURN(r);
  3271 		}
  3272 #ifdef PRM_ENABLE_EXTENDED_VERSION
  3273 	DStaticPowerResource *pR = NULL;
  3274 	GET_RESOURCE_FROM_LIST(aResourceId, pR)
  3275 #else
  3276 	if(aResourceId > iStaticResourceArrayEntries)
  3277 		{
  3278         r = KErrNotFound;
  3279         PRM_POSTNOTIFICATION_REGISTER_TRACE
  3280 		UNLOCK_RETURN(r);
  3281 		}
  3282 
  3283 	DStaticPowerResource *pR = iStaticResourceArray[aResourceId-1];
  3284 	if(!pR)
  3285 		{
  3286 		r = KErrNotFound;
  3287 		PRM_POSTNOTIFICATION_REGISTER_TRACE
  3288 		UNLOCK_RETURN(r);
  3289 		}
  3290 #endif
  3291 	if(aN.iRegistered) //Check if the same notification object is used already
  3292 		{
  3293         r = KErrInUse;
  3294         PRM_POSTNOTIFICATION_REGISTER_TRACE
  3295 		UNLOCK_RETURN(r);
  3296 		}
  3297 
  3298 	//Validate threshold for correctness
  3299     TPowerResourceInfoBuf01 buf;
  3300     r = pR->GetInfo((TDes8*)buf.Ptr());
  3301     if(r != KErrNone)
  3302 		{
  3303 		PRM_POSTNOTIFICATION_REGISTER_TRACE
  3304 		UNLOCK_RETURN(r);
  3305 		}
  3306     TPowerResourceInfoV01 *pBuf = (TPowerResourceInfoV01*)buf.Ptr();
  3307     if(((pBuf->iMinLevel > pBuf->iMaxLevel) && ((aThreshold > pBuf->iMinLevel) || (aThreshold < pBuf->iMaxLevel))) || 
  3308 		     ((pBuf->iMaxLevel > pBuf->iMinLevel) && ((aThreshold > pBuf->iMaxLevel) || (aThreshold < pBuf->iMinLevel))))
  3309 		{
  3310         r = KErrArgument;
  3311         PRM_POSTNOTIFICATION_REGISTER_TRACE
  3312         UNLOCK_RETURN(r);
  3313 		}
  3314 	aN.iRegistered++;
  3315 	aN.iType = DPowerResourceNotification::EConditional;
  3316 	aN.iThreshold = aThreshold;
  3317 	aN.iDirection = aDirection;
  3318 	aN.iOwnerId = (TUint16)aClientId;
  3319 	aN.iCallback.iClientId = aClientId;
  3320 	aN.iCallback.iResourceId = aResourceId;
  3321 	//Store the current level of the resource as will be used for issuing notification
  3322 	aN.iPreviousLevel = pR->iCachedLevel; 
  3323 	//Add to resource notification list
  3324 	pR->iNotificationList.Add(&(aN.iNotificationLink));
  3325 	//Add to client notification list
  3326 	LIST_PUSH(pC->iNotificationList, &aN, iNextInClient);
  3327 	PRM_POSTNOTIFICATION_REGISTER_TRACE
  3328 	UNLOCK_RETURN(KErrNone);
  3329 	}
  3330 
  3331 /**
  3332 @publishedPartner
  3333 @prototype 9.5
  3334 
  3335 Cancel and remove from queue a previously issued request for notification on a
  3336 resource state change.
  3337 
  3338 @param aClientId ID of the client which is requesting to cancel the notification
  3339 @param aResourceId for the resource whose pending notification of state changes
  3340                    is being cancelled.
  3341 @param aN          A reference to the notification object that was associated with
  3342                    the notification request that is being cancelled. This will be
  3343                    used to identify the notification that is being cancelled.
  3344 
  3345 @return KErrCancel if the notification request was successfully cancelled.
  3346         KErrNotFound if the specified notification object is 
  3347 					 not found in the current list of notification objects for the 
  3348 					 specified resource.
  3349         KErrAccessDenied if the client requesting the cancellation is not the same
  3350                          which registered the notification or if the resource id does not match or
  3351 						 if the client ID could not be found in the list of registered clients or 
  3352 						 if the client was registered to be thread relative and this API is 
  3353 						 not called from the same thread. 
  3354 
  3355 @pre Interrupts must be enabled
  3356 @pre Kernel must be unlocked
  3357 @pre No fast mutex can be held
  3358 @pre Call in a thread context but not from null thread or DFC thread1
  3359 @pre Can be used in a device driver
  3360 */
  3361 TInt DPowerResourceController::CancelNotification(TUint aClientId, TUint aResourceId, DPowerResourceNotification& aN)
  3362 	{
  3363      TInt r = KErrCancel;
  3364 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::CancelNotification"));
  3365 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d", aClientId, aResourceId));
  3366 	DThread& thread = Kern::CurrentThread();	
  3367 	CHECK_CONTEXT(thread)
  3368 	SPowerResourceClient* pC = NULL;
  3369 	Lock();
  3370 	VALIDATE_CLIENT(thread);
  3371 
  3372 	if(!aN.iRegistered)
  3373 		{
  3374         r = KErrNotFound;
  3375         PRM_POSTNOTIFICATION_DEREGISTER_TRACE
  3376 		UNLOCK_RETURN(r);
  3377 		}
  3378 	//Remove from the client list
  3379 	TBool found = EFalse;
  3380 	DPowerResourceNotification* pCNL = pC->iNotificationList;
  3381 	DPowerResourceNotification* pCNLNext = pCNL;
  3382 	if(pCNL == &aN)
  3383 		{
  3384         if(pCNL->iOwnerId != (TUint16)aClientId)
  3385 	        {
  3386             r = KErrAccessDenied;
  3387             PRM_POSTNOTIFICATION_DEREGISTER_TRACE
  3388            UNLOCK_RETURN(r);
  3389 		    }
  3390         found = ETrue;
  3391 		}
  3392     else
  3393 		{
  3394 		while(pCNLNext)
  3395 			{
  3396 			if(pCNLNext == &aN)
  3397 				{
  3398 				if(pCNL->iOwnerId != (TUint16)aClientId)
  3399 					{
  3400 					r = KErrAccessDenied;
  3401 					PRM_POSTNOTIFICATION_DEREGISTER_TRACE
  3402 					UNLOCK_RETURN(r);
  3403 					}
  3404 				pCNL->iNextInClient = pCNLNext->iNextInClient;
  3405 				pCNL = pCNLNext;
  3406 				found = ETrue;
  3407 				break;
  3408 				}
  3409 			pCNL = pCNLNext;
  3410 			pCNLNext = pCNLNext->iNextInClient;
  3411 			}
  3412 		}
  3413 	if(!found)
  3414 		{
  3415         r = KErrNotFound;
  3416         PRM_POSTNOTIFICATION_DEREGISTER_TRACE
  3417 		UNLOCK_RETURN(r);
  3418 		}
  3419 	if(pCNL->iCallback.iResourceId != aResourceId)
  3420 		{
  3421 		r = KErrAccessDenied;
  3422 		PRM_POSTNOTIFICATION_DEREGISTER_TRACE
  3423 		UNLOCK_RETURN(r);
  3424 		}
  3425 	//Remove from resource list
  3426 	pCNL->iNotificationLink.Deque();
  3427 	pCNL->iCallback.Cancel();
  3428 	//Remove from client list
  3429 	LIST_REMOVE(pC->iNotificationList, pCNL, iNextInClient, DPowerResourceNotification);
  3430 	pCNL->iRegistered--;
  3431 	PRM_POSTNOTIFICATION_DEREGISTER_TRACE
  3432 	UNLOCK_RETURN(KErrCancel);
  3433 	}
  3434 
  3435 /**
  3436 @publishedPartner
  3437 @prototype 9.5
  3438 
  3439 Request pre-allocation of specified number of client level and request message objects.
  3440 
  3441 @param aClientId  ID of the client which is requesting the pre-allocation.
  3442 @param aNumCl     Number of client level objects that needs to be pre-allocated
  3443                   for this client.
  3444 @param aNumRm     Number of request message objects that needs to be pre-allocated
  3445                   for this client.
  3446 
  3447 @return KErrNone if the allocation was successful
  3448         KErrAccessDenied if the client ID could not be found in the list of
  3449                          registered clients or if the client was registered to be thread
  3450 						 relative and this API is not called from the same thread. 
  3451         KErrNoMemory if there is no sufficient memory for allocation of requested
  3452                      number of objects.
  3453 
  3454 @pre Interrupts must be enabled
  3455 @pre Kernel must be unlocked
  3456 @pre No fast mutex can be held
  3457 @pre Call in a thread context but not from null thread or DFC thread1
  3458 @pre Can be used in a device driver
  3459 */
  3460 TInt DPowerResourceController::AllocReserve(TUint aClientId, TUint8 aNumCl, TUint8 aNumRm)
  3461 	{
  3462 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::AllocReserve"));
  3463 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, Numclients = %d, NumResource = %d", aClientId, aNumCl, aNumRm));
  3464 	DThread& thread = Kern::CurrentThread();	
  3465 	CHECK_CONTEXT(thread)
  3466 	SPowerResourceClient* pC = NULL;
  3467 	Lock();
  3468 	VALIDATE_CLIENT(thread);
  3469 	//Call from thread Id.
  3470 	TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
  3471 	req->ReqType() = TPowerRequest::EAllocReserve;
  3472 	req->ClientId() = aClientId;
  3473 	req->RequestCount() = aNumRm;
  3474 	req->ClientLevelCount() = aNumCl;
  3475 
  3476 	UnLock();
  3477 	req->SendReceive(iMsgQ);
  3478 	return (req->ReturnCode());
  3479 	}
  3480 /**
  3481 @internalComponent
  3482 @prototype 9.5
  3483 
  3484 This function runs in the context of the RC thread and 
  3485 handles creation of memory pools. 
  3486 */
  3487 TInt DPowerResourceController::HandleReservationOfObjects(TPowerRequest& aRequest)
  3488 	{
  3489 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::AllocReserve"));
  3490 
  3491 	SPowerResourceClientLevel* pCL = NULL;
  3492 	SPowerRequest* pR = NULL;
  3493 
  3494 	Lock();
  3495 	TInt clientPoolCount = iClientLevelPoolCount;
  3496 	TInt requestPoolCount = iRequestPoolCount;
  3497 	SPowerResourceClient* pC;
  3498 	if(aRequest.ClientId() & USER_SIDE_CLIENT_BIT_MASK)
  3499 		pC = iUserSideClientList[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)];
  3500 	else																				
  3501 		pC = iClientList[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)];
  3502 	UnLock();
  3503 
  3504 	if(clientPoolCount < aRequest.ClientLevelCount())
  3505 		{
  3506 		//Grow the client level pool
  3507 		// coverity[alloc_fn]
  3508 		pCL = new SPowerResourceClientLevel[iClientLevelPoolGrowBy + aRequest.ClientLevelCount()];
  3509 		if(!pCL)
  3510 			return(KErrNoMemory);
  3511 		}
  3512 	if(requestPoolCount < aRequest.RequestCount())
  3513 		{
  3514 		//Grow the request pool
  3515 		// coverity[alloc_fn]
  3516 		pR = new SPowerRequest[iRequestPoolGrowBy + aRequest.RequestCount()];
  3517 		if(!pR)
  3518 			{
  3519 			if(pCL) //If client level is allocated delete the same.
  3520 				delete []pCL;
  3521 			return(KErrNoMemory);
  3522 			}
  3523 		}
  3524 	//Push the memory to list and adjust the counter.
  3525 	Lock();
  3526 	TUint count;
  3527 	if(pCL)
  3528 		{
  3529 		for(count = 0;count<(TUint)(iClientLevelPoolGrowBy+aRequest.ClientLevelCount());count++)
  3530 			LIST_PUSH(iClientLevelPool, &pCL[count], iNextInList);
  3531 		iClientLevelPoolCount= (TUint16)(iClientLevelPoolCount + iClientLevelPoolGrowBy);
  3532 		pC->iReservedCl= (TUint8)(pC->iReservedCl + aRequest.ClientLevelCount());
  3533 		}
  3534 		else
  3535 		{
  3536 		//Reserve memory from free pool to this client
  3537 		iClientLevelPoolCount = (TUint16)(iClientLevelPoolCount - aRequest.ClientLevelCount());
  3538 		pC->iReservedCl = (TUint8)(pC->iReservedCl + aRequest.ClientLevelCount());
  3539 		}
  3540 
  3541 	if(pR)
  3542 		{
  3543 		for(count=0;count<(TUint)(iRequestPoolGrowBy+aRequest.RequestCount());count++)
  3544  			LIST_PUSH(iRequestPool, &pR[count], iNext);
  3545 		iRequestPoolCount = (TUint16)(iRequestPoolCount + iRequestPoolGrowBy);
  3546 		pC->iReservedRm =(TUint8)(pC->iReservedRm + aRequest.RequestCount());
  3547 		}
  3548 	else
  3549 		{
  3550 		//Reserve memory from free pool to this client
  3551 		iRequestPoolCount = (TUint16)(iRequestPoolCount - aRequest.RequestCount());
  3552 		pC->iReservedRm = (TUint8)(pC->iReservedRm + aRequest.RequestCount());
  3553 		}
  3554 	UnLock();
  3555 #ifdef PRM_INSTRUMENTATION_MACRO
  3556     TUint size =0;
  3557     if(pCL)
  3558 		size = (iClientLevelPoolGrowBy+aRequest.ClientLevelCount())*sizeof(SPowerResourceClientLevel);
  3559     if(pR)
  3560 		size += (iRequestPoolGrowBy+aRequest.RequestCount())*sizeof(SPowerRequest);
  3561     if(size)
  3562         PRM_MEMORY_USAGE_TRACE
  3563 #endif
  3564 	return(KErrNone);
  3565 	}
  3566 
  3567 /*  Register the proxy client to resource controller.
  3568 	This is called as the result of new user side client opening a channel.*/
  3569 TInt DPowerResourceController::RegisterProxyClient(TUint& aClientId, const TDesC8& aName)
  3570 	{
  3571 	GET_CRITICAL_SECTION_COUNT
  3572 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterProxyClient"));
  3573 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("Proxy client name %S", &aName));
  3574 
  3575 	DThread& t = Kern::CurrentThread();	
  3576 	CHECK_CONTEXT(t)
  3577 	//If number of expected user side clients is set to 0 during initial configuration
  3578 	//then dont allow to configure user side clients.
  3579 	if(!iUserSideClientList.GrowBy())
  3580 		return KErrNotSupported;
  3581 	//Maximum allowable length of a client's name is 32 characters.
  3582 	if (aName.Length() > KMaxClientNameLength) return KErrTooBig;
  3583 
  3584 	SPowerResourceClient *pC = NULL;
  3585     Lock();
  3586 #ifdef DEBUG_VERSION
  3587     if(!iUserSideClientList.Find(pC, (TDesC8&)aName))
  3588 		{
  3589 		UnLock();
  3590 		LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
  3591 		return KErrAlreadyExists;
  3592 		}
  3593 #endif
  3594 	TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
  3595 	req->ReqType() = TPowerRequest::ERegisterUsersideClient;
  3596 	UnLock();
  3597 	req->SendReceive(iMsgQ);
  3598 	if(req->ReturnCode() == KErrNone)
  3599 		{
  3600 		pC = iUserSideClientList[(TUint16)(req->ClientId() & ID_INDEX_BIT_MASK)];
  3601 		pC->iName=&aName;
  3602 		//Store the current thread Id;
  3603 		pC->iThreadId = t.iId;
  3604 		aClientId = pC->iClientId;
  3605 		}
  3606 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterProxyClient, clientId = 0x%x", aClientId));
  3607     PRM_CLIENT_REGISTER_TRACE
  3608 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
  3609 	return KErrNone;
  3610 	}
  3611 
  3612 /*  Deregister the specified user side client from resource controller.
  3613 	This is called as the result of client closing the channel. */
  3614 TInt DPowerResourceController::DeregisterProxyClient(TUint aClientId)
  3615 	{
  3616 	GET_CRITICAL_SECTION_COUNT
  3617 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::DeregisterProxyClient"));
  3618 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x", aClientId));
  3619 	DThread& t = Kern::CurrentThread();	
  3620 	CHECK_CONTEXT(t)
  3621 	//Get the index from client ID
  3622 	if(!(aClientId & USER_SIDE_CLIENT_BIT_MASK))
  3623 		return KErrArgument;
  3624 	Lock();
  3625 	SPowerResourceClient* pC = iUserSideClientList[(TUint16)(aClientId & ID_INDEX_BIT_MASK)];
  3626 	if(!pC)
  3627 		{
  3628 		UnLock();
  3629 		LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
  3630 		return KErrNotFound;
  3631 		}
  3632 	if(pC->iClientId != aClientId)
  3633 		{
  3634         __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client ID does not match"));
  3635 	     UNLOCK_RETURN(KErrNotFound);
  3636 		}
  3637 	if(pC->iClientId & CLIENT_THREAD_RELATIVE_BIT_MASK)
  3638 		{
  3639 		if(pC->iThreadId != t.iId)
  3640 			{
  3641 			UnLock();
  3642 			LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
  3643 			return KErrAccessDenied;
  3644 			}
  3645 		}
  3646 	//Check for any pending request
  3647 	if(pC->iPendingReqCount)
  3648 		{
  3649 		UnLock();
  3650 		LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
  3651 		Panic(EClientHasPendingAsyncRequest);
  3652 		}
  3653 	//Check for notification request
  3654 	if(pC->iNotificationList)
  3655 		{
  3656 		UnLock();
  3657 		LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
  3658 		Panic(EClientHasNotificationObject);
  3659 		}
  3660 #ifdef PRM_ENABLE_EXTENDED_VERSION
  3661 	if(pC->iDynamicResCount)
  3662 		{
  3663 		UnLock();
  3664 		LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
  3665 		Panic(DPowerResourceController::EClientHasDynamicResourceRegistered);
  3666 		}
  3667 #endif
  3668 	ResourceStateChangeOfClientLevels(pC);
  3669 	//Add reserved request to pool
  3670 	iRequestPoolCount = (TUint16)(iRequestPoolCount + pC->iReservedRm);
  3671 	PRM_CLIENT_DEREGISTER_TRACE
  3672 	//Increment the free pool count for client level and request level.
  3673 	iUserSideClientList.Remove(pC, (TUint16)(pC->iClientId & ID_INDEX_BIT_MASK));
  3674 	pC->iName = NULL;
  3675 	iUserSideClientCount--; //Decrement client count
  3676 	LIST_PUSH(iClientPool, pC, iNextInList);
  3677 	UnLock();
  3678 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
  3679 	return KErrNone;
  3680 	}
  3681 
  3682 /* This is called from power controller to cache the state of resource whose
  3683    state information it is interested in for accessing from null thread. This
  3684    list needs to be accessed from the Idle thread using direct access. */
  3685 TInt DPowerResourceController::RegisterResourcesForIdle(TInt aPowerControllerId, TUint aNumResources, TPtr* aBuf)
  3686 	{
  3687 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterResourceForIdle"));
  3688 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("PowerControllerId = 0x%x, NumResources = %d", aPowerControllerId, aNumResources));
  3689 #ifdef DEBUG_VERSION //Surrounding with macro to avoid warnings.
  3690 	DThread& t = Kern::CurrentThread();	
  3691 	CHECK_CONTEXT(t)
  3692 #endif
  3693 	if(!aBuf)
  3694 		return KErrArgument;
  3695 	if((TUint)aPowerControllerId != iPowerControllerId)
  3696 		return KErrAccessDenied;
  3697 	if(iListForIdle) //Only one list is allowed.
  3698 		return KErrInUse;
  3699 	if((TUint)(aBuf->MaxLength() - aBuf->Length()) < (sizeof(SIdleResourceInfo) * aNumResources))
  3700 		return KErrArgument;
  3701 	GET_CRITICAL_SECTION_COUNT
  3702 	Lock();
  3703 	SIdleResourceInfo* pS=(SIdleResourceInfo*)aBuf->Ptr();
  3704 	DStaticPowerResource* pR=NULL;
  3705 	TUint count=0;
  3706 	TUint id=0;
  3707 	for(count=0;count<aNumResources;count++) //Check for valid resource ID.
  3708 		{
  3709 #ifndef PRM_ENABLE_EXTENDED_VERSION
  3710 		if((!pS->iResourceId) || (pS->iResourceId > iStaticResourceArrayEntries) || (!iStaticResourceArray[pS->iResourceId-1]))
  3711 			{
  3712 			UnLock();
  3713 			LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
  3714 			return KErrNotFound;
  3715 			}
  3716 #else
  3717 		if(pS->iResourceId & KIdMaskDynamic)
  3718 			{
  3719 			UnLock();
  3720 			LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
  3721 			return KErrNotSupported;
  3722 			}
  3723 		if((!pS->iResourceId) || ((pS->iResourceId & KIdMaskResourceWithDependencies) && 
  3724 			     (pS->iResourceId > iStaticResDependencyCount)) || (!(pS->iResourceId & KIdMaskResourceWithDependencies) && 
  3725 					((pS->iResourceId > iStaticResourceArrayEntries) || (!iStaticResourceArray[pS->iResourceId-1]))))
  3726 			{
  3727 			UnLock();
  3728 			LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
  3729 			return KErrNotFound;
  3730 			}
  3731 #endif
  3732 		pS++;
  3733 		}
  3734 	pS = (SIdleResourceInfo*)aBuf->Ptr();
  3735 	for(count=0;count<aNumResources;count++)
  3736 		{
  3737 		id=pS->iResourceId;
  3738 #ifdef PRM_ENABLE_EXTENDED_VERSION
  3739 		if(id & KIdMaskResourceWithDependencies) //Dependency resource
  3740 			pR = iStaticResDependencyArray[(id & ID_INDEX_BIT_MASK)-1];
  3741 		else
  3742 #endif
  3743 		pR=iStaticResourceArray[id-1];
  3744 		pS->iLevelOwnerId = pR->iLevelOwnerId;
  3745 		pS->iCurrentLevel = pR->iCachedLevel;
  3746 		pR->iIdleListEntry=pS;
  3747 		pS++;
  3748 		}
  3749 	iListForIdle=(SIdleResourceInfo*)aBuf->Ptr();
  3750 	pS = (SIdleResourceInfo*)aBuf->Ptr();
  3751 	UnLock();
  3752 	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
  3753 	return KErrNone;
  3754 	}
  3755 	
  3756 /**
  3757 @publishedPartner
  3758 @prototype 9.6
  3759 
  3760 Request to deregister client level from the specified resource for the specified client. 
  3761 
  3762 @param aClientId	ID of the client which is requesting the deregistration of client level.
  3763 @param aResourceId	ID of the resource from which to remove the specified client's level.
  3764 
  3765 @return KErrNone			if successful
  3766 		KErrAccessDenied	if the client ID could not be found in the list of registered clients or
  3767 							if the client was registered to be thread relative and this API is not 
  3768 							called from the same thread.
  3769 		KErrNotFound		if the resource ID could not be found in the current list of controllable 
  3770 							resources or if the client is not holding any level with the specified 
  3771 							resource (no client level found for the specified client).
  3772 
  3773 @pre Interrupts must be enabled
  3774 @pre Kernel must be unlocked
  3775 @pre No fast mutex can be held
  3776 @pre Call in a thread context but not from null thread or DFC thread1
  3777 @pre Can be used in a device driver.
  3778 */
  3779 TInt DPowerResourceController::DeRegisterClientLevelFromResource(TUint aClientId, TUint aResourceId)
  3780 	{
  3781 	TInt r = KErrNone;
  3782 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::DeRegisterClientLevelFromResource\n"));
  3783 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("aClientId = 0x%x, aResourceId = 0x%x\n", aClientId, aResourceId));
  3784 	DThread& thread = Kern::CurrentThread();	
  3785 	CHECK_CONTEXT(thread)
  3786 	SPowerResourceClient* pC = NULL;
  3787 	Lock();
  3788 	VALIDATE_CLIENT(thread);
  3789 	//Validate resource
  3790 	if((!aResourceId))
  3791 		{
  3792 		UNLOCK_RETURN(KErrNotFound);
  3793 		}
  3794 	DStaticPowerResource *pR = NULL;
  3795 #ifdef PRM_ENABLE_EXTENDED_VERSION
  3796 	GET_RESOURCE_FROM_LIST(aResourceId, pR)
  3797 	if(aResourceId & KIdMaskDynamic)
  3798 		((DDynamicPowerResource*)pR)->Lock();
  3799 #else
  3800 	if(aResourceId > iStaticResourceArrayEntries)
  3801 		{
  3802 		UNLOCK_RETURN(KErrNotFound);
  3803 		}
  3804 	pR = iStaticResourceArray[aResourceId - 1];
  3805 	if(!pR)
  3806 		UNLOCK_RETURN(KErrNotFound);
  3807 #endif
  3808 	//Need to change the state of the resource if the client is holding the current resource.
  3809 	if((pR->iLevelOwnerId == (TInt)aClientId) || (pR->Sense() == DStaticPowerResource::ECustom)) 
  3810 		{
  3811 		//If Longlatency resource then process it in the resource controller thread
  3812 		TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
  3813 		req->ResourceId() = aResourceId;
  3814 		req->ReqType() = TPowerRequest::ESetDefaultLevel;
  3815 		req->ClientId() = aClientId;
  3816 		req->Resource() = pR;
  3817 		req->ResourceCb() = NULL;
  3818 #ifdef PRM_INSTRUMENTATION_MACRO
  3819 		//Setting to current state as exact state will be known only before calling the PSL.
  3820 		TInt aNewState = pR->iCachedLevel; 
  3821 		PRM_CLIENT_CHANGE_STATE_START_TRACE
  3822 #endif
  3823 		if(pR->LatencySet())
  3824 			{
  3825 			UnLock();
  3826 #ifdef PRM_ENABLE_EXTENDED_VERSION
  3827 			if(pR->iResourceId & KIdMaskResourceWithDependencies) //Dependency resource
  3828 				{
  3829 				r = req->SendReceive(iMsgQDependency); // Send the request to DFC thread.
  3830 				}
  3831 			else
  3832 #endif
  3833 				{
  3834 				r = req->SendReceive(iMsgQ); //Long latency resource request are processed in controller thread.
  3835 				}
  3836 			Lock();
  3837 			}
  3838 		else if(pR->Usage())
  3839 			{
  3840 			//Shared resource
  3841 			//Not checking the return value here because there is no allocation of client levels. 
  3842 			CheckLevelAndAddClient(pC, req); 
  3843 			}
  3844 		else
  3845 			{
  3846 			//Single user set it to default
  3847 			req->ClientId() = -1;
  3848 			req->ReqType() = TPowerRequest::ESetDefaultLevel;
  3849 			}
  3850 		//Change the state of resource for instantaneous resource.
  3851 		if((!pR->LatencySet()) && ((!pR->Usage()) || (pR->Usage() && req->RequiresChange())))
  3852 			{
  3853 			UnLock();
  3854 			r = pR->DoRequest(*req);
  3855 			Lock();
  3856 			if(r == KErrNone)
  3857 				{
  3858 				//Complete notifications
  3859 				CompleteNotifications(req->ClientId(), pR, req->Level(), KErrNone, req->ClientId(), EFalse);
  3860 				//Update the cache
  3861 				pR->iLevelOwnerId = req->ClientId();
  3862 				pR->iCachedLevel = req->Level();
  3863 				if(pR->iIdleListEntry)
  3864 					{
  3865 					pR->iIdleListEntry->iLevelOwnerId = req->ClientId();
  3866 					pR->iIdleListEntry->iCurrentLevel = req->Level();
  3867 					}
  3868 				}
  3869 			}
  3870 #ifdef PRM_INSTRUMENTATION_MACRO
  3871 		if(!pR->LatencySet())
  3872 			{
  3873 			aNewState = req->Level();
  3874 			PRM_CLIENT_CHANGE_STATE_END_TRACE
  3875 			}
  3876 #endif
  3877 		}
  3878 	//Remove clientLevel from client
  3879 	r = KErrNotFound;
  3880 	for(SPowerResourceClientLevel* pCL = pC->iLevelList; pCL != NULL; pCL= pCL->iNextInList)
  3881 		{
  3882 		if(pCL->iResourceId == aResourceId)
  3883 			{
  3884 			LIST_REMOVE(pC->iLevelList, pCL, iNextInList, SPowerResourceClientLevel);
  3885 			//Remove from Resource
  3886 			pCL->Deque();
  3887 			LIST_PUSH(iClientLevelPool,pCL,iNextInList); // back to free pool
  3888 			if(pC->iUnderFlowClCount > 0)
  3889 				{
  3890 				pC->iUnderFlowClCount--;
  3891 				iClientLevelPoolCount++;
  3892 				}
  3893 			else
  3894 				pC->iReservedCl++;
  3895 			r = KErrNone;
  3896 			break;
  3897 			}
  3898 		}
  3899 #ifdef PRM_ENABLE_EXTENDED_VERSION
  3900 	if(aResourceId & KIdMaskDynamic)
  3901 		((DDynamicPowerResource*)pR)->UnLock();
  3902 #endif
  3903 	UNLOCK_RETURN(r);
  3904 	}
  3905 
  3906 /**
  3907 @publishedPartner
  3908 @prototype 9.5
  3909 
  3910 Interface to provide extended functionality.This provides support
  3911 to register and deregister dynamic resources and handling of resource dependency, registering
  3912 and deregistering resource dependency.
  3913 This is not supported in basic version
  3914 
  3915 @pre Interrupts must be enabled
  3916 @pre Kernel must be unlocked
  3917 @pre No fast mutex can be held
  3918 @pre Call in a thread context but not from null thread or DFC thread1
  3919 @pre Can be used in a device driver.
  3920 */
  3921 TInt DPowerResourceController::GetInterface(TUint aClientId, TUint aInterfaceId, TAny* aParam1, TAny* aParam2, 
  3922 											                                             TAny* aParam3)
  3923 	{
  3924 	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetInterface"));
  3925 	DThread& thread = Kern::CurrentThread();	
  3926 	CHECK_CONTEXT(thread)
  3927 	if((iInitialised != EResConStartupCompleted) && (aInterfaceId != KResManControlIoGetVersion))
  3928 		return KErrNotSupported;
  3929 	TInt r = KErrNone;
  3930 	Lock();
  3931 	SPowerResourceClient* pC = NULL;
  3932 	VALIDATE_CLIENT(thread);
  3933 #ifndef PRM_ENABLE_EXTENDED_VERSION
  3934 	if(aInterfaceId == KResManControlIoGetVersion)
  3935 		{
  3936 		if(!aParam1)
  3937 			r = KErrArgument;
  3938 		else
  3939 			*(TUint*)aParam1  = KResControllerBasicVersion;
  3940 		}
  3941 	else
  3942 		r = KErrNotSupported;
  3943 	(void) aParam2;
  3944 	(void) aParam3;
  3945 #else
  3946 	//User side client is not allowed to register/deregister dynamic resource and dependencies
  3947 	if((aClientId & USER_SIDE_CLIENT_BIT_MASK) && (aInterfaceId >= KResManControlIoRegisterDynamicResource) && 
  3948 		                                                 (aInterfaceId <= KResManControlIoDeregisterDependency))
  3949 		return KErrAccessDenied;
  3950 	switch (aInterfaceId)
  3951 		{
  3952 		case KResManControlIoGetVersion:
  3953 			{
  3954 			if(!aParam1)
  3955 				r = KErrArgument;
  3956 			else
  3957 				*(TUint*)aParam1 = KResControllerExtendedVersion;
  3958 			break;
  3959 			}
  3960 		case KResManControlIoRegisterDynamicResource:
  3961 			{
  3962 			r = RegisterDynamicResource(pC, (DDynamicPowerResource *)aParam1, (TUint*)aParam2);
  3963 			break;
  3964 			}
  3965 		case KResManControlIoDeregisterDynamicResource:
  3966 			{
  3967 			r = DeregisterDynamicResource(pC, (TUint)aParam1, (TInt*)aParam2);
  3968 			break;
  3969 			}
  3970 		case KResManControlIoRegisterDependency:
  3971 			{
  3972 
  3973 			r = RegisterResourceDependency(pC, (SResourceDependencyInfo*)aParam1, (SResourceDependencyInfo*)aParam2);
  3974 			break;
  3975 			}
  3976 		case KResManControlIoDeregisterDependency:
  3977 			{
  3978 			r = DeregisterResourceDependency(pC, (TUint)aParam1, (TUint)aParam2);
  3979 			__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetInterface"));
  3980 			return(r);
  3981 			}
  3982 		case KResManControlIoGetNumDependents:
  3983 			{
  3984 			r = GetNumDependentsForResource((TUint)aParam1, (TUint*)aParam2);
  3985 			break;
  3986 			}
  3987 		case KResManControlIoGetDependentsId:
  3988 			{
  3989 			r = GetDependentsIdForResource((TUint)aParam1, (TAny*)aParam2, (TUint*)aParam3);
  3990 			break;
  3991 			}
  3992 		default:
  3993 			{
  3994 			r = KErrNotSupported;
  3995 			break;
  3996 			}
  3997 		}
  3998 #endif
  3999 	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetInterface"));
  4000 	UNLOCK_RETURN(r);
  4001 	}
  4002