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