Update contrib.
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\drivers\resourceman\resourcecontrol.cpp
18 #include <drivers/resourcecontrol.h>
19 #include <drivers/resourcecontrol_trace.h>
21 #define GET_CRITICAL_SECTION_COUNT \
22 DThread& thread = Kern::CurrentThread(); \
23 TInt CsCount = thread.iNThread.iCsCount;
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__);
31 #define GET_CRITICAL_SECTION_COUNT
32 #define LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
35 /** Allow interface class to call this. */
36 DPowerResourceController* PowerResourceController = NULL;
38 /** Resource Controller factory class implementation */
39 #ifdef RESOURCE_MANAGER_SIMULATED_PSL
40 #ifndef PRM_ENABLE_EXTENDED_VERSION
41 _LIT(KPddName,"resourcecontroller.pdd");
43 _LIT(KPddName, "resourcecontrollerextended.pdd");
46 #ifndef PRM_ENABLE_EXTENDED_VERSION
47 _LIT(KPddName, "resman.pdd");
49 _LIT(KPddName, "resmanextended.pdd");
53 /** Factory class constructor */
54 DResConPddFactory::DResConPddFactory()
57 iVersion = DResConPddFactory::VersionRequired();
60 TInt DResConPddFactory::Install()
62 // Set a Name for Resource Controller Factory class object.
63 return(SetName(&KPddName));
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*/)
69 //Create new interface for each channel.
70 DUserSideProxyInterface *pI = new (DUserSideProxyInterface);
73 pI->iController = PowerResourceController; //Store the resource controller.
74 aChannel = (DBase*)pI;
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)
81 if (!Kern::QueryVersionSupported(DResConPddFactory::VersionRequired(),aVer))
82 return(KErrNotSupported);
86 /** Return the driver capabilities */
87 void DResConPddFactory::GetCaps(TDes8& aDes) const
89 // Create a capabilities object
91 caps.iVersion = iVersion;
93 TInt maxLen = aDes.MaxLength();
96 TInt size=sizeof(caps);
99 aDes.Copy((TUint8*)&caps,size);
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()
106 return new DResConPddFactory;
110 /** Interface class implementation */
111 TInt TInterface::RegisterClient(TUint& aClientId, const TDesC8& aName, TOwnerType aType)
113 GET_CRITICAL_SECTION_COUNT
115 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::RegisterClient"));
116 r = PowerResourceController->RegisterClient(aClientId, aName, aType);
117 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
121 TInt TInterface::DeRegisterClient(TUint aClientId)
123 GET_CRITICAL_SECTION_COUNT
125 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::DeRegisterClient"));
126 r = PowerResourceController->DeRegisterClient(aClientId);
127 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
131 TInt TInterface::GetClientName(TUint aClientId, TUint aTargetClientId, TDes8& aName)
133 GET_CRITICAL_SECTION_COUNT
135 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetClientName"));
136 r = PowerResourceController->GetClientName(aClientId, aTargetClientId, aName);
137 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
141 TInt TInterface::GetClientId(TUint aClientId, TDesC8& aClientName, TUint& aTargetClientId)
143 GET_CRITICAL_SECTION_COUNT
145 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetClientId"));
146 r = PowerResourceController->GetClientId(aClientId, aClientName, aTargetClientId);
147 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
151 TInt TInterface::GetResourceId(TUint aClientId, TDesC8& aResourceName, TUint& aResourceId)
153 GET_CRITICAL_SECTION_COUNT
155 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetResourceId"));
156 r = PowerResourceController->GetResourceId(aClientId, aResourceName, aResourceId);
157 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
161 TInt TInterface::GetResourceInfo(TUint aClientId, TUint aResourceId, TAny* aInfo)
163 GET_CRITICAL_SECTION_COUNT
165 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetResourceInfo"));
166 r = PowerResourceController->GetResourceInfo(aClientId, aResourceId, aInfo);
167 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
171 TInt TInterface::GetNumResourcesInUseByClient(TUint aClientId, TUint aTargetClientId, TUint& aNumResource)
173 GET_CRITICAL_SECTION_COUNT
175 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetNumResourcesInUseByClient"));
176 r = PowerResourceController->GetNumResourcesInUseByClient(aClientId, aTargetClientId, aNumResource);
177 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
181 TInt TInterface::GetInfoOnResourcesInUseByClient(TUint aClientId, TUint aTargetClientId, TUint& aNumResources, TAny* aInfo)
183 GET_CRITICAL_SECTION_COUNT
185 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetInfoOnResourcesInUseByClient"));
186 r = PowerResourceController->GetInfoOnResourcesInUseByClient(aClientId, aTargetClientId, aNumResources, aInfo);
187 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
191 TInt TInterface::GetNumClientsUsingResource(TUint aClientId, TUint aResourceId, TUint& aNumClients)
193 GET_CRITICAL_SECTION_COUNT
195 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetNumClientsUsingResource"));
196 r = PowerResourceController->GetNumClientsUsingResource(aClientId, aResourceId, aNumClients);
197 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
201 TInt TInterface::GetInfoOnClientsUsingResource(TUint aClientId, TUint aResourceId, TUint& aNumClients, TAny* aInfo)
203 GET_CRITICAL_SECTION_COUNT
205 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetInfoOnClientsUsingResource"));
206 r = PowerResourceController->GetInfoOnClientsUsingResource(aClientId, aResourceId, aNumClients, aInfo);
207 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
211 TInt TInterface::ChangeResourceState(TUint aClientId, TUint aResourceId, TInt aNewState, TPowerResourceCb* aCb)
213 GET_CRITICAL_SECTION_COUNT
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.
219 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
224 TInt TInterface::GetResourceState(TUint aClientId, TUint aResourceId, TBool aCached, TInt& aState, TInt& aLevelOwnerId)
226 GET_CRITICAL_SECTION_COUNT
228 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetResourceState"));
229 r = PowerResourceController->GetResourceState(aClientId, aResourceId, aCached, aState, aLevelOwnerId);
230 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
234 TInt TInterface::GetResourceState(TUint aClientId, TUint aResourceId, TBool aCached, TPowerResourceCb& aCb)
237 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetResourceState"));
238 r = PowerResourceController->GetResourceState(aClientId, aResourceId, aCached, aCb);
242 TInt TInterface::CancelAsyncRequestCallBack(TUint aClientId, TUint aResourceId, TPowerResourceCb& aCb)
244 GET_CRITICAL_SECTION_COUNT
246 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::CancelAsyncRequestCallback"));
247 r = PowerResourceController->CancelAsyncRequestCallBack(aClientId, aResourceId, aCb);
248 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
252 TInt TInterface::RequestNotification(TUint aClientId, TUint aResourceId, DPowerResourceNotification& aN)
254 GET_CRITICAL_SECTION_COUNT
256 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::RequestNotification"));
257 r = PowerResourceController->RequestNotification(aClientId, aResourceId, aN);
258 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
262 TInt TInterface::RequestNotification(TUint aClientId, TUint aResourceId, DPowerResourceNotification& aN, TInt aThreshold,
265 GET_CRITICAL_SECTION_COUNT
267 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::RequestNotification"));
268 r = PowerResourceController->RequestNotification(aClientId, aResourceId, aN, aThreshold, aDirection);
269 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
273 TInt TInterface::CancelNotification(TUint aClientId, TUint aResourceId, DPowerResourceNotification& aN)
275 GET_CRITICAL_SECTION_COUNT
277 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::CancelNotification"));
278 r = PowerResourceController->CancelNotification(aClientId, aResourceId, aN);
279 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
283 TInt TInterface::DeRegisterClientLevelFromResource(TUint aClientId, TUint aResourceId)
285 GET_CRITICAL_SECTION_COUNT
287 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::DeRegisterClientLevelFromResource"));
288 r = PowerResourceController->DeRegisterClientLevelFromResource(aClientId, aResourceId);
289 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
293 TInt TInterface::AllocReserve(TUint aClientId, TUint8 aNumCl, TUint8 aNumRm)
295 GET_CRITICAL_SECTION_COUNT
297 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::AllocReserve"));
298 r = PowerResourceController->AllocReserve(aClientId, aNumCl, aNumRm);
299 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
303 /** This function is used by export functions of Resource contoller defined in seperate file */
304 DPowerResourceController* TInterface::GetPowerResourceController(void)
306 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetPowerResourceController"));
307 return PowerResourceController;
310 TInt TInterface::ControlIO(TUint aClientId, TUint aFunction, TAny* aParam1, TAny* aParam2, TAny* aParam3)
312 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::ControlIO"));
313 return PowerResourceController->GetInterface(aClientId, aFunction, aParam1, aParam2, aParam3);
316 /** Resouce controller panic */
317 void DPowerResourceController::Panic(TUint8 aPanic)
319 Kern::Fault("Power Resource Controller", aPanic);
322 /** Constructor for power controller. Creates message queue and generates ID for power controller to use. */
323 DPowerResourceController::DPowerResourceController()
325 __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::DPowerResouceController()"));
326 //Constructor is expected to invoke multiple times (during creation, variant init 0 and extension init 1)
327 if(PowerResourceController)
329 PowerResourceController = this;
330 iClientList.Initialise(0);
331 iUserSideClientList.Initialise(0);
332 iInitialised = EResConCreated;
333 #ifdef PRM_ENABLE_EXTENDED_VERSION
334 iDynamicResourceList.Initialise(0);
335 iDynamicResDependencyList.Initialise(0);
339 /** Destructor for power controller. Frees the memory allocated in kernel heap. */
340 DPowerResourceController::~DPowerResourceController()
342 __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::~DPowerResourceController()"));
343 #ifdef RESOURCE_MANAGER_SIMULATED_PSL
344 iCleanList.ResetAndDestroy();
346 iClientList.Delete();
347 iUserSideClientList.Delete();
351 #ifdef PRM_ENABLE_EXTENDED_VERSION
352 iDynamicResourceList.Delete();
353 iDynamicResDependencyList.Delete();
356 SPowerResourceClientLevel *pCL = iClientLevelPool;
357 while(iClientLevelPool) //Find the starting position of array to delete
359 if(iClientLevelPool < pCL)
360 pCL = iClientLevelPool;
361 iClientLevelPool = iClientLevelPool->iNextInList;
365 SPowerRequest *pReq = iRequestPool;
366 while(iRequestPool) //Find the starting position of array to delete
368 if(iRequestPool < pReq)
370 iRequestPool = iRequestPool->iNext;
374 #ifdef PRM_ENABLE_EXTENDED_VERSION
375 pCL = iResourceLevelPool;
376 while(iResourceLevelPool)
378 if(iResourceLevelPool < pCL)
379 pCL = iResourceLevelPool;
380 iResourceLevelPool = iResourceLevelPool->iNextInList;
382 //delete resource pool
384 //delete Message Queue dependency
385 delete iMsgQDependency;
387 //delete Message Queue
391 /** Send notificatins to clients registered for it for the specified resource. */
392 void DPowerResourceController::CompleteNotifications(TInt aClientId, DStaticPowerResource* aResource, TInt aState,
393 TInt aReturnCode, TInt aLevelOwnerId, TBool aLock)
395 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::CompleteNotifications"));
398 DPowerResourceNotification*pN=NULL;
399 for(SDblQueLink* pNL=aResource->iNotificationList.First();pNL!=&aResource->iNotificationList.iA; pNL=pNL->iNext)
401 pN = _LOFF(pNL, DPowerResourceNotification, iNotificationLink);
402 #ifdef PRM_ENABLE_EXTENDED_VERSION
403 //If dyanmic resource is deregistering, send notification to all clients requested for it
404 if((pN->iCallback.iResourceId & KIdMaskDynamic) && (aClientId == KDynamicResourceDeRegistering))
406 pN->iCallback.iResult = aReturnCode;
407 pN->iCallback.iLevel = aState;
408 pN->iCallback.iClientId = aClientId;
409 pN->iCallback.iLevelOwnerId = aLevelOwnerId;
410 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Notification ClientId = 0x%x, ResourceId = %d, state = %d, Result = %d",
411 pN->iCallback.iClientId, pN->iCallback.iResourceId, aState, aReturnCode));
412 PRM_POSTNOTIFICATION_SENT_TRACE
413 pN->iCallback.Enque();
417 if((pN->iType==DPowerResourceNotification::EUnconditional) ||
418 (pN->iDirection && ((pN->iPreviousLevel < pN->iThreshold) && (aState >= pN->iThreshold))) ||
419 (!pN->iDirection && ((pN->iPreviousLevel > pN->iThreshold) && (aState <= pN->iThreshold))))
421 pN->iCallback.iResult=aReturnCode;
422 pN->iCallback.iLevel=aState;
423 pN->iCallback.iClientId = aClientId;
424 pN->iCallback.iLevelOwnerId = aLevelOwnerId;
425 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Notifications ClientId = 0x%x, ResourceId = %d, State = %d, Result = %d",
426 pN->iCallback.iClientId, pN->iCallback.iResourceId, aState, aReturnCode));
427 PRM_POSTNOTIFICATION_SENT_TRACE
428 pN->iCallback.Enque();
430 pN->iPreviousLevel = aState; //Update the state
432 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::CompleteNotifications"));
438 /** Complete the asynchronous request. */
439 void DPowerResourceController::CompleteRequest(TPowerRequest& aRequest)
441 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::CompleteRequest"));
442 // Complete notification for state change operation
443 DStaticPowerResource* pR=aRequest.Resource();
444 //If request in EChange or ESetDefaultValue and no error and if shared resources and if change is done then
445 //issue notification.
446 if(((aRequest.ReqType() == TPowerRequest::EChange) || (aRequest.ReqType() == TPowerRequest::ESetDefaultLevel))
447 && (aRequest.ReturnCode() == KErrNone) && ((!pR->Usage()) || (pR->Usage() && aRequest.RequiresChange())))
449 CompleteNotifications(aRequest.ClientId(), aRequest.Resource(), aRequest.Level(),
450 aRequest.ReturnCode(), aRequest.ClientId());
452 //Do not update the level if the resource is shared and change is not required or any error.
453 if(aRequest.ReturnCode()==KErrNone && ((aRequest.ReqType() ==TPowerRequest::EGet) ||
454 (((aRequest.ReqType()==TPowerRequest::EChange) || (aRequest.ReqType()==TPowerRequest::ESetDefaultLevel))
455 && ((!pR->Usage()) || (pR->Usage() && aRequest.RequiresChange())))))
458 // Cache the latest value
459 pR->iCachedLevel=aRequest.Level();
460 //Need to update client ID only during state change.
461 if(aRequest.ReqType() != TPowerRequest::EGet)
462 pR->iLevelOwnerId=aRequest.ClientId();
463 // Cache Idle list entry for this reosurce if requested.
464 if(pR->iIdleListEntry)
466 SIdleResourceInfo* pI=pR->iIdleListEntry;
467 if(aRequest.ReqType() != TPowerRequest::EGet)
468 pI->iLevelOwnerId= aRequest.ClientId();
469 pI->iCurrentLevel=aRequest.Level();
474 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::CompleteRequest"));
477 /** Handle/process the asynchronous request sent to resource controller.
478 The request can be one of the following
479 1) State change of long latency reosurce
480 2) Get the state of long latency resource
481 3) Set the default value of long latency resource */
482 void DPowerResourceController::HandleMsg(TPowerRequest& aRequest)
484 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::HandleMsg"));
485 DStaticPowerResource* pR=aRequest.Resource();
486 //Get client using client ID
487 TUint aClientId = aRequest.ClientId();
488 SPowerResourceClient* pC = NULL;
489 #ifdef PRM_ENABLE_EXTENDED_VERSION
490 if((TInt)aClientId != KDynamicResourceDeRegistering)
492 if(aClientId & USER_SIDE_CLIENT_BIT_MASK)
493 pC = iUserSideClientList[TUint16(aClientId & ID_INDEX_BIT_MASK)];
495 pC = iClientList[TUint16(aClientId & ID_INDEX_BIT_MASK)];
498 if(aClientId & USER_SIDE_CLIENT_BIT_MASK)
499 pC = iUserSideClientList[TUint16(aClientId & ID_INDEX_BIT_MASK)];
501 pC = iClientList[TUint16(aClientId & ID_INDEX_BIT_MASK)];
503 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Request Type = %d, ClientId = 0x%x, ResourceId = %d",
504 aRequest.ReqType(), aRequest.ClientId(), aRequest.ResourceId()));
505 if(aRequest.ReqType()==TPowerRequest::EChange)
507 if(pR->Usage()) //Handling shared resource
509 Lock(); //To avoid race condition between deregister resource level.
510 aRequest.ReturnCode() = CheckLevelAndAddClient(pC, &aRequest);
512 if((aRequest.ReturnCode()!= KErrNone) || (!aRequest.RequiresChange()))
514 aRequest.Level() = pR->iCachedLevel; //If no change then send the current level back.
515 CompleteRequest(aRequest);
519 else if(pR->iLevelOwnerId ==-1) //No existing client.
522 if(pC->iReservedCl==0 && !iClientLevelPoolCount)
524 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Reserved Client Level exhausted and its free pool empty"));
525 aRequest.ReturnCode() = KErrUnderflow;
526 CompleteRequest(aRequest);
529 SPowerResourceClientLevel* pSCL=NULL;
530 LIST_POP(iClientLevelPool, pSCL, iNextInList);
531 pSCL->iClientId=aClientId;
532 pSCL->iResourceId=aRequest.ResourceId();
533 pSCL->iLevel=aRequest.Level();
534 LIST_PUSH(pC->iLevelList, pSCL, iNextInList); //Add to client
535 pR->iClientList.Add(pSCL); //Add in resource
536 if(pC->iReservedCl==0)
538 iClientLevelPoolCount--;
539 pC->iUnderFlowClCount++;
546 //Update the level in the client list.
547 SPowerResourceClientLevel* pSCL = (SPowerResourceClientLevel*)pR->iClientList.First();
548 pSCL->iLevel = aRequest.Level();
551 else if(aRequest.ReqType()==TPowerRequest::ESetDefaultLevel)
553 #ifdef PRM_ENABLE_EXTENDED_VERSION
554 if((aRequest.ResourceId() & KIdMaskDynamic) && ((TInt)aClientId == KDynamicResourceDeRegistering))
556 //Try to change the resource to requested level and if that fails try to change it to default level
557 if(pR->iDefaultLevel != aRequest.Level())
559 aRequest.ReqType() = TPowerRequest::EChange;
560 aRequest.ReturnCode() = pR->DoRequest(aRequest);
561 if(aRequest.ReturnCode() != KErrNone)
563 aRequest.ReqType() = TPowerRequest::ESetDefaultLevel;
564 aRequest.Level() = pR->iDefaultLevel;
565 pR->DoRequest(aRequest);
569 pR->DoRequest(aRequest);
570 aRequest.ReturnCode() = KErrNone;
571 aRequest.RequiresChange() = ETrue;
572 CompleteRequest(aRequest);
578 aRequest.ReturnCode() = CheckLevelAndAddClient(pC, &aRequest);
579 if((aRequest.ReturnCode()!= KErrNone) || (!aRequest.RequiresChange()))
581 aRequest.Level() = pR->iCachedLevel; //If no change then send the current level back.
582 CompleteRequest(aRequest);
588 aRequest.ClientId() = -1;
589 aRequest.Level() = pR->iDefaultLevel;
592 if((aRequest.ReqType() == TPowerRequest::EGet) || (pR->iCachedLevel != aRequest.Level()))
593 aRequest.ReturnCode() = pR->DoRequest(aRequest);
594 CompleteRequest(aRequest);
595 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::HandleMsg"));
598 #ifdef PRM_ENABLE_EXTENDED_VERSION
599 /** Handle/process the dependency resource.
600 The request can be one of the following
601 1) State change of a dependency resource
602 2) Get the state of a dependency resource
603 3) Set the default value of a dependency resource */
604 void DPowerResourceController::HandleDependencyMsg(TPowerRequest& aRequest)
606 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::HandleDependencyMsg"));
607 DStaticPowerResource* pR=aRequest.Resource();
608 //Get client using client ID
609 TUint aClientId = aRequest.ClientId();
610 SPowerResourceClient* pC = NULL;
612 if((TInt)aClientId != KDynamicResourceDeRegistering)
614 if(aClientId & USER_SIDE_CLIENT_BIT_MASK)
615 pC = iUserSideClientList[TUint16(aClientId & ID_INDEX_BIT_MASK)];
617 pC = iClientList[TUint16(aClientId & ID_INDEX_BIT_MASK)];
619 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Request Type = %d, ClientId = 0x%x, ResourceId = %d",
620 aRequest.ReqType(), aRequest.ClientId(), aRequest.ResourceId()));
621 if((aRequest.ResourceId() & KIdMaskResourceWithDependencies) && (aRequest.ReqType() != TPowerRequest::EGet))
624 iDfcQDependencyLock = ETrue;
626 PowerResourceController->HandleDependencyResourceStateChange(pC, aRequest);
628 iDfcQDependencyLock = EFalse;
632 //Get the resource current level.
633 aRequest.ReturnCode() = pR->DoRequest(aRequest);
634 CompleteRequest(aRequest);
635 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::HandleDependencyMsg"));
639 /** Function called whenever there is a message in resource controller message queue. */
640 void DPowerResourceController::MsgQFunc(TAny* aPtr)
642 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::MsgQFunc"));
643 DPowerResourceController* pRC=(DPowerResourceController*)aPtr;
644 TPowerRequest* aReq=(TPowerRequest*)pRC->iMsgQ->iMessage;
645 DStaticPowerResource *pR = aReq->Resource();
646 if(aReq->ReqType() == TPowerRequest::EAllocReserve)
648 aReq->ReturnCode() = pRC->HandleReservationOfObjects(*aReq);
649 aReq->Complete(aReq->ReturnCode(),ETrue);
652 if((aReq->ReqType() == TPowerRequest::ERegisterKernelClient) || (aReq->ReqType() == TPowerRequest::ERegisterUsersideClient))
654 aReq->ReturnCode() = pRC->HandleClientRegistration(*aReq);
655 aReq->Complete(aReq->ReturnCode(), ETrue);
658 #ifdef PRM_ENABLE_EXTENDED_VERSION
659 if(aReq->ReqType() == TPowerRequest::ERegisterDynamicResource)
661 aReq->ReturnCode() = pRC->HandleResourceRegistration(*aReq);
662 aReq->Complete(aReq->ReturnCode(), ETrue);
666 pRC->HandleMsg(*aReq);
667 #ifdef PRM_ENABLE_EXTENDED_VERSION
668 if((aReq->ResourceId() & KIdMaskDynamic) && (aReq->ResourceCb()))
671 ((DDynamicPowerResource*)aReq->Resource())->UnLock();
675 //Below code is for Btrace
676 #ifdef PRM_INSTRUMENTATION_MACRO
677 SPowerResourceClient* pC = NULL;
678 SPowerResourceClient tRes;
679 #ifdef PRM_ENABLE_EXTENDED_VERSION
680 if((aReq->ClientId() == -1) || (aReq->ClientId() == KDynamicResourceDeRegistering))
682 if(aReq->ClientId() == -1)
686 pC->iClientId = (TUint)-1;
687 pC->iName = &KNoClient;
689 else if(aReq->ClientId() & USER_SIDE_CLIENT_BIT_MASK)
690 pC = pRC->iUserSideClientList[TUint16(aReq->ClientId() & ID_INDEX_BIT_MASK)];
692 pC = pRC->iClientList[TUint16(aReq->ClientId() & ID_INDEX_BIT_MASK)];
694 TUint aResourceId = aReq->ResourceId();
695 TInt r = aReq->ReturnCode();
696 if(aReq->ReqType()==TPowerRequest::EGet)
698 TInt aState = aReq->Level();
699 PRM_RESOURCE_GET_STATE_END_TRACE
703 TInt aNewState = aReq->Level();
704 PRM_CLIENT_CHANGE_STATE_END_TRACE
707 //Check whether callback is cancelled and if not queue the DFC.
708 TPowerResourceCb* pCb = aReq->ResourceCb();
711 pCb->iResult=aReq->ReturnCode();
712 pCb->iLevel=aReq->Level();
713 pCb->iResourceId=aReq->ResourceId();
714 pCb->iClientId=aReq->ClientId();
715 pCb->iLevelOwnerId = pR->iLevelOwnerId;
718 aReq->Complete(aReq->ReturnCode(),ETrue);
719 if(aReq->ResourceCb())
720 pRC->MoveRequestToFreePool(aReq);
721 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::MsgQFunc"));
725 #ifdef PRM_ENABLE_EXTENDED_VERSION
726 /** Function called whenever there is a message in resource controller Dependency message queue. */
727 void DPowerResourceController::MsgQDependencyFunc(TAny* aPtr)
729 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::MsgQDependencyFunc"));
730 DPowerResourceController* pRC=(DPowerResourceController*)aPtr;
731 TPowerRequest* aReq=(TPowerRequest*)pRC->iMsgQDependency->iMessage;
732 DStaticPowerResource *pR = aReq->Resource();
733 pRC->HandleDependencyMsg(*aReq);
734 if((aReq->ResourceId() & KIdMaskDynamic) && (aReq->ResourceCb()))
737 ((DDynamicPowerResource*)aReq->Resource())->UnLock();
740 //Below code is for Btrace
741 #ifdef PRM_INSTRUMENTATION_MACRO
742 SPowerResourceClient* pC = NULL;
743 SPowerResourceClient tRes;
744 if((aReq->ClientId() != -1) && (aReq->ClientId() != KDynamicResourceDeRegistering) &&
745 (aReq->ClientId() & KIdMaskResourceWithDependencies))
748 pC->iClientId = aReq->ClientId();
749 DDynamicPowerResourceD* pDRes;
750 if(aReq->ClientId() & KIdMaskDynamic)
751 pDRes = pRC->iDynamicResDependencyList[(TUint16)(aReq->ClientId() & ID_INDEX_BIT_MASK)];
753 pDRes = (DDynamicPowerResourceD*)pRC->iStaticResDependencyArray[(aReq->ClientId() & ID_INDEX_BIT_MASK) - 1];
754 pC->iName = pDRes->iName;
756 else if((aReq->ClientId() == -1) || (aReq->ClientId() == KDynamicResourceDeRegistering))
759 pC->iClientId = (TUint)-1;
760 pC->iName = &KNoClient;
762 else if(aReq->ClientId() & USER_SIDE_CLIENT_BIT_MASK)
763 pC = pRC->iUserSideClientList[TUint16(aReq->ClientId() & ID_INDEX_BIT_MASK)];
765 pC = pRC->iClientList[TUint16(aReq->ClientId() & ID_INDEX_BIT_MASK)];
767 TUint aResourceId = aReq->ResourceId();
768 TInt r = aReq->ReturnCode();
769 if(aReq->ReqType()==TPowerRequest::EGet)
771 TInt aState = aReq->Level();
772 PRM_RESOURCE_GET_STATE_END_TRACE
776 TInt aNewState = aReq->Level();
777 PRM_CLIENT_CHANGE_STATE_END_TRACE
780 //Check whether callback is cancelled and if not queue the DFC.
781 TPowerResourceCb* pCb = aReq->ResourceCb();
784 pCb->iResult=aReq->ReturnCode();
785 pCb->iLevel=aReq->Level();
786 pCb->iResourceId=aReq->ResourceId();
787 pCb->iClientId=aReq->ClientId();
788 pCb->iLevelOwnerId = pR->iLevelOwnerId;
791 aReq->Complete(aReq->ReturnCode(),ETrue);
792 if(aReq->ResourceCb())
793 pRC->MoveRequestToFreePool(aReq);
794 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::MsgQDependencyFunc"));
798 /** Function to move the request object to free pool and update client request count accordingly. */
799 void DPowerResourceController::MoveRequestToFreePool(TPowerRequest *aReq)
801 //Return request to free pool
802 SPowerRequest* pS=_LOFF(aReq, SPowerRequest, iRequest);
804 LIST_PUSH(iRequestPool, pS, iNext);
805 SPowerResourceClient* pC = NULL;
806 if(aReq->ClientId() & USER_SIDE_CLIENT_BIT_MASK)
807 pC = iUserSideClientList[TUint16(aReq->ClientId() & ID_INDEX_BIT_MASK)];
809 pC = iClientList[TUint16(aReq->ClientId() & ID_INDEX_BIT_MASK)];
810 pC->iPendingReqCount--;
811 if(pC->iUnderFlowRmCount > 0)
814 pC->iUnderFlowRmCount--;
822 /** This function is called by PSL to set the DFC queue created */
823 void DPowerResourceController::SetDfcQ(TDfcQue* aDfcQ)
825 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::SetDfcQ"));
827 iMsgQ->SetDfcQ(iDfcQ);
830 #ifdef PRM_ENABLE_EXTENDED_VERSION
831 /** This function is called by PSL to set the DFC Dependency queue created */
832 void DPowerResourceController::SetDfcQDependency(TDfcQue* aDfcQDependency)
834 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::SetDfcQDependency"));
835 iDfcQDependency=aDfcQDependency;
836 iMsgQDependency->SetDfcQ(iDfcQDependency);
839 /**This is called as a result of DFC queued in supervisor thread to complete the initialisation
840 of resource controller.It registers the resource controller with the power controller. It also
841 calls PSL (DoInitResources()) to initialise all static resources to their post-reboot state.
842 Finally mark resource controller as fully initialised (ready to accept state change and get request)
843 and start the message queue if exists. */
844 TInt DPowerResourceController::InitResources()
846 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::InitResources()"));
848 //Create a Kernel client object for Power Controller
850 SPowerResourceClient * pC = NULL;
851 // By now client pool should be created
852 LIST_POP(iClientPool, pC, iNextInList);
853 TUint16 growBy = iClientList.GrowBy();
857 // coverity[alloc_fn]
858 SPowerResourceClient *pCL = new SPowerResourceClient[growBy];
861 __KTRACE_OPT(KRESMANAGER, Kern::Printf("No memory to grow client pool"));
862 Panic(ENoMemToCreatePowerControllerClient);
864 #ifdef RESOURCE_MANAGER_SIMULATED_PSL
865 iCleanList.Append(pCL);
868 for(count = 0; count < growBy-1; count++)
869 LIST_PUSH(iClientPool, &pCL[count], iNextInList);
871 #ifdef PRM_INSTRUMENTATION_MACRO
872 TUint size = growBy *sizeof(SPowerResourceClient);
873 PRM_MEMORY_USAGE_TRACE
876 pC->iName = (const TDesC8*)&KPowerController;
878 if(iClientList.Allocd()==iClientList.Count())
880 if(iClientList.ReSize(growBy))
882 Panic(ENoMemToCreatePowerControllerClient);
886 iClientList.Add(pC, iPowerControllerId);
887 pC->iClientId = iPowerControllerId | CLIENT_POWER_CONTROLLER_BIT_MASK;
888 iPowerControllerId = pC->iClientId;
890 if(TPowerController::PowerController())
891 TPowerController::PowerController()->RegisterResourceController(this, iPowerControllerId);
892 iInitialised =EResConStartupCompleted;
894 //Check the resource for postboot level and send notifications to clients registered for it.
895 DStaticPowerResource *pR = NULL;
897 TPowerRequest req = TPowerRequest::Get();
898 //For Static resource with no dependencies
899 for(count = 0; count< iStaticResourceArrayEntries; count++)
901 pR = iStaticResourceArray[count];
902 if(pR && (pR->iFlags & SET_VALID_POST_BOOT_LEVEL))
904 //Form the request message
905 req.ReqType() = TPowerRequest::EChange;
906 req.ResourceId() = count+1;
908 req.Level() = pR->iPostBootLevel;
910 req.ResourceCb() = NULL;
911 req.RequiresChange() = ETrue;
912 r = pR->DoRequest(req);
915 CompleteNotifications(-1, pR, req.Level(), r, -1, ETrue);
916 pR->iCachedLevel = req.Level(); //Update the cached level.
920 #ifdef PRM_ENABLE_EXTENDED_VERSION
921 //For Static resource with dependencies
922 for(count = 0; count < iStaticResDependencyCount; count++)
924 pR = iStaticResDependencyArray[count];
925 if(pR->iFlags & SET_VALID_POST_BOOT_LEVEL)
927 req.ReqType() = TPowerRequest::EChange;
928 req.ResourceId() = ((DStaticPowerResourceD*)pR)->iResourceId;
930 req.Level() = pR->iPostBootLevel;
932 req.ResourceCb() = NULL;
933 req.RequiresChange() = ETrue;
934 //Form the request message
935 ((DStaticPowerResourceD*)pR)->HandleChangePropagation(req, EChangeStart, req.ClientId(), KNoClient);
939 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::InitResources()"));
943 /** @internalComponent
944 This function is called for shared resources to determine level for the shared resource.
945 This takes care of updating the resource level for each client.
947 TInt DPowerResourceController::CheckLevelAndAddClient(SPowerResourceClient* pC, TPowerRequest* aReq)
949 //Client level addition in state change needs to be taken care.
950 __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient, ClientId = 0x%x, ResourceId = %d, ReqType = %d",
951 pC->iClientId, aReq->ResourceId(), aReq->ReqType()));
953 SPowerResourceClientLevel* pSCL=NULL; //Place to hold the current client
954 SPowerResourceClientLevel* pMCL=NULL; //Place to hold the prevailing client.
955 DStaticPowerResource* aResource = aReq->Resource();
956 aReq->RequiresChange() = EFalse;
957 TInt maxLevel=KMinTInt;
960 //Get the nextmaximum, current client information.If the change is requested by client holding the prevailing
961 //level of the resource then maxlevel will be next highest level with respect to sense. Otherwise will contain
963 SPowerResourceClientLevel* pL = NULL;
964 for(SDblQueLink* pCL=aResource->iClientList.First();pCL!=&aResource->iClientList.iA;pCL=pCL->iNext,count++)
966 pL=(SPowerResourceClientLevel*)pCL;
967 if(pL->iClientId == pC->iClientId)
970 if(aResource->Sense() == DStaticPowerResource::ECustom)
975 if((count == 0) || ((pSCL != NULL) && (maxLevel == KMinTInt)))
977 maxLevel = pL->iLevel;
981 if(((aResource->Sense() == DStaticPowerResource::ENegative) && (pL->iLevel < maxLevel)) ||
982 ((aResource->Sense() == DStaticPowerResource::EPositive) && (pL->iLevel > maxLevel)))
988 //Get the current level.
989 if(((TInt)pC->iClientId == aResource->iLevelOwnerId))
990 // coverity[var_deref_op]
991 CurrentLevel = pSCL->iLevel;
993 CurrentLevel = maxLevel;
995 #ifdef PRM_ENABLE_EXTENDED_VERSION
996 if(aResource->iLevelOwnerId & KIdMaskResourceWithDependencies)
998 CurrentLevel = aResource->iCachedLevel;
1001 TBool newClient = EFalse;
1004 // If the client is new, get free client level from pool and populate with client information
1005 // and add it to the client list and in resource list.
1006 if((pC->iReservedCl ==0) && !iClientLevelPoolCount)
1008 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client level quota exhausted and its free pool empty, iReservedCl = %d, iClientLevelPoolCount = %d",
1009 pC->iReservedCl, iClientLevelPoolCount));
1010 return KErrUnderflow;
1012 LIST_POP(iClientLevelPool, pSCL, iNextInList);
1013 pSCL->iClientId=pC->iClientId;
1014 pSCL->iResourceId=aReq->ResourceId();
1015 pSCL->iLevel = aReq->Level();
1016 //Add to the resource list
1017 aResource->iClientList.Add(pSCL);
1018 //Add to the client List
1019 LIST_PUSH(pC->iLevelList, pSCL, iNextInList);
1020 if(pC->iReservedCl == 0)
1022 iClientLevelPoolCount--;
1023 pC->iUnderFlowClCount++;
1027 //If no client is holding the resource already and is not custom sense resource, then change is allowed
1028 if((aResource->iLevelOwnerId == -1) && (aResource->Sense() != DStaticPowerResource::ECustom))
1030 aReq->RequiresChange() = ETrue;
1031 __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
1034 if(aResource->Sense() == DStaticPowerResource::ECustom)
1038 // Capture the new level requested by the client.
1039 pSCL->iLevel=aReq->Level();
1041 if(aResource->Sense() == DStaticPowerResource::ECustom)
1044 if(!aResource->iCustomFunction)
1045 Panic(ECustomFunctionNotSet);
1046 // coverity[var_deref_op]
1047 if(aReq->ReqType() == TPowerRequest::EChange)
1049 aReq->RequiresChange() = aResource->iCustomFunction(aReq->ClientId(), *(pC->iName), aReq->ResourceId(),
1050 newClient ? EClientRequestLevel : EClientChangeLevel,
1051 aReq->Level(), (TAny*)&aResource->iClientList, NULL);
1055 aReq->RequiresChange() = aResource->iCustomFunction(aReq->ClientId(), *(pC->iName), aReq->ResourceId(),
1056 EClientRelinquishLevel,
1057 aReq->Level(), (TAny*)&aResource->iClientList, NULL);
1059 if((aReq->ClientId() != -1) && (aReq->ClientId() != (TInt)pC->iClientId) )
1061 //Check whether the updated client Id (by custom function) is in the client level list.
1062 for(SDblQueLink* pCL=aResource->iClientList.First();pCL!=&aResource->iClientList.iA;pCL=pCL->iNext)
1064 pL = (SPowerResourceClientLevel*)pCL;
1065 if((TInt)pL->iClientId == aReq->ClientId())
1068 #ifdef PRM_ENABLE_EXTENDED_VERSION
1069 if(aReq->ClientId() & (1 << RESOURCE_BIT_IN_ID_CHECK))
1071 if(aResource->iResourceId & KIdMaskDynamic)
1072 pL = ((DDynamicPowerResourceD*)aResource)->iResourceClientList;
1074 pL = ((DStaticPowerResourceD*)aResource)->iResourceClientList;
1077 if((TInt)pL->iClientId == aReq->ClientId())
1082 // coverity[var_deref_op]
1083 if((TInt)pL->iClientId != aReq->ClientId())
1084 Panic(EClientIdNotInClientLevelList);
1086 if(!aReq->RequiresChange() && (aReq->ClientId() != (TInt)pC->iClientId))
1088 aResource->iLevelOwnerId=aReq->ClientId();
1089 //Update resource details for Idle
1090 if(aResource->iIdleListEntry)
1091 aResource->iIdleListEntry->iLevelOwnerId=aReq->ClientId();
1093 __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
1096 //Handle client deregistration
1097 if(aReq->ReqType() == TPowerRequest::ESetDefaultLevel)
1099 aReq->RequiresChange() = ETrue;
1100 // If the client is the only ask PSL to set to default level.
1103 aReq->ReqType() = TPowerRequest::ESetDefaultLevel;
1104 aReq->Level() = aResource->iDefaultLevel;
1105 aReq->ClientId() = -1;
1109 //Change the state to next maximum level with respect to sense.
1110 aReq->ReqType() = TPowerRequest::EChange;
1111 // coverity[var_deref_op]
1112 aReq->ClientId() = pMCL->iClientId;
1113 aReq->Level() = pMCL->iLevel;
1114 if(pSCL->iLevel == pMCL->iLevel)
1116 //Change the client alone and level remains the same.
1117 aResource->iLevelOwnerId = pMCL->iClientId;
1118 if(aResource->iIdleListEntry)
1119 aResource->iIdleListEntry->iLevelOwnerId = pMCL->iClientId;
1120 aReq->RequiresChange() = EFalse;
1123 __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
1127 //If the level is in increasing order with respect to sense the change is allowed.
1128 if(((aResource->Sense() == DStaticPowerResource::ENegative) && aReq->Level()<CurrentLevel) ||
1129 ((aResource->Sense() == DStaticPowerResource::EPositive) && aReq->Level()>CurrentLevel))
1131 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Resource is in increasing order with respect to sense and level is %d",
1133 aReq->RequiresChange()=ETrue;
1136 if((TInt)pC->iClientId == aResource->iLevelOwnerId)
1138 if(aReq->Level() == CurrentLevel)
1140 __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
1145 aReq->RequiresChange() = ETrue;
1146 __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
1149 // If the client requesting is the client holding current level, then chnage it to the nextmaximum level.
1150 // Next maximum level is the max of requesting level or next maximum level.
1151 if(((aResource->Sense()==DStaticPowerResource::ENegative) && maxLevel < aReq->Level()) ||
1152 ((aResource->Sense()==DStaticPowerResource::EPositive) && maxLevel > aReq->Level()))
1154 aReq->Level() = maxLevel;
1155 aReq->ClientId() = pMCL->iClientId;
1156 if(maxLevel == CurrentLevel)
1158 aResource->iLevelOwnerId=pMCL->iClientId;
1159 //Update resource details for Idle
1160 if(aResource->iIdleListEntry)
1161 aResource->iIdleListEntry->iLevelOwnerId=pMCL->iClientId;
1162 aReq->RequiresChange() = EFalse;
1163 __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
1167 aReq->RequiresChange() = ETrue;
1169 __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
1174 Initialise pools of request structures, client strutures and client power level structures.
1175 By preallocating sufficiently large structures we remove any allocations whilst the resource manager mutex is held.
1176 The function basically ensures that sufficient memory is preallocated to the resource manager to ensure that none is
1177 required at run time.
1178 @param aKClients number of kernel side clients expected in the resource manager
1179 @param aUClients number of user side clients expected in the resource manager
1180 @param aNClientLevels number of client levels the RM should preallocate. This is roughly the number of clients
1181 that are expected to use shared resources multiplied by the number of shared resources.
1182 @param aNRequest number of simultaneous asynchronous requests the resource manager is likely to handle
1183 @return KErrNone if preallocations succeed
1184 @return KErrNoMemory if one the prealocations fails
1186 TInt DPowerResourceController::InitPools(TUint16 aKClients, TUint16 aUClients, TUint16 aNClientLevels, TUint16 aNRequests)
1188 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::InitPools"));
1189 __KTRACE_OPT(KRESMANAGER, Kern::Printf("aKClients = %d, aUClients = %d, aNClientLevels = %d, aNRequests = %d",
1190 aKClients, aUClients, aNClientLevels, aNRequests));
1191 __ASSERT_ALWAYS((iInitialised == EResConCreated) && !(iClientPool || iRequestPool || iClientLevelPool), Kern::Fault("Already initialized"
1192 __FILE__, __LINE__));
1194 // Create client pool
1195 SPowerResourceClient* pC = NULL;
1196 SPowerResourceClientLevel* pCL = NULL;
1197 SPowerRequest* pR = NULL;
1198 aKClients++; //Add one default for PowerController
1199 if(aKClients + aUClients)
1201 // coverity[alloc_fn]
1202 pC = new SPowerResourceClient[aKClients+aUClients];
1205 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client Pool Allocation Failed"));
1206 return KErrNoMemory;
1209 // Create Client level pool
1212 // coverity[alloc_fn]
1213 pCL = new SPowerResourceClientLevel[aNClientLevels];
1216 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client Level Pool Allocation Failed"));
1218 return KErrNoMemory;
1221 // Create Request pool
1224 // coverity[alloc_fn]
1225 pR = new SPowerRequest[aNRequests];
1228 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Request Pool Allocation Failed"));
1231 return KErrNoMemory;
1234 //Create the client Array for kernel and user side clients.
1235 if(iClientList.Initialise(aKClients))
1240 return KErrNoMemory;
1242 if(iUserSideClientList.Initialise(aUClients))
1247 iClientList.Delete();
1248 return KErrNoMemory;
1250 #ifdef PRM_ENABLE_EXTENDED_VERSION
1251 SPowerResourceClientLevel* pRL = NULL;
1252 if(iStaticResDependencyCount)
1254 pRL = new SPowerResourceClientLevel[iStaticResDependencyCount];
1257 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Resource level Pool Allocation Failed"));
1261 iClientList.Delete();
1262 iUserSideClientList.Delete();
1263 return KErrNoMemory;
1266 #ifdef RESOURCE_MANAGER_SIMULATED_PSL
1267 iCleanList.Append(pC);
1271 for(c = 0; c < iStaticResDependencyCount; c++)
1273 LIST_PUSH(iResourceLevelPool, &pRL[c], iNextInList);
1275 iResourceLevelPoolCount = iStaticResDependencyCount;
1277 #ifdef RESOURCE_MANAGER_SIMULATED_PSL
1278 iCleanList.Append(pC);
1283 // Create Client pool list
1284 for(c = 0; c< (aKClients + aUClients); c++)
1286 LIST_PUSH(iClientPool, &pC[c], iNextInList);
1288 // Create client level pool list
1289 for(c = 0; c < aNClientLevels; c++)
1291 LIST_PUSH(iClientLevelPool, &pCL[c], iNextInList);
1293 // Create request pool list
1294 for(c = 0; c < aNRequests; c++)
1296 LIST_PUSH(iRequestPool, &pR[c], iNext);
1298 // When the pool is exhausted they are increased by half of initial size. */
1299 iClientLevelPoolGrowBy=(TUint16)(aNClientLevels/2);
1300 iRequestPoolGrowBy=(TUint16)(aNRequests/2);
1301 // Initialise the free pool size
1302 iClientLevelPoolCount=aNClientLevels;
1303 iRequestPoolCount=aNRequests;
1304 #ifdef PRM_INSTRUMENTATION_MACRO
1305 TUint size = (((aKClients + aUClients)*sizeof(SPowerResourceClient)) +
1306 (aNClientLevels * sizeof(SPowerResourceClientLevel)) + (aNRequests * sizeof(SPowerRequest)));
1307 PRM_MEMORY_USAGE_TRACE
1309 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::InitPools"));
1310 UNLOCK_RETURN(KErrNone);
1317 Register a client with the Resource Manager.
1319 @param aClientId A reference to a client ID: returns a unique handle if registration was
1320 successful, 0 otherwise.
1321 @param aName Descriptor with name for client. The descriptor is created by the client
1322 in kernel data space or its user address space.
1323 NOTE: Name should ideally relate to component name and should take care
1324 of name uniqueness as it is checked only if DEBUG_VERSION macro is enabled.
1325 @param aType Defines ownership
1326 EOwnerProcess - The client ID can be used by all thread in the process to
1327 call the resource manager API's
1328 EOwnerThread - The client ID can only be used by the thread that registered
1329 the client to resource manager to call the PRM API's
1330 By default this is set to EOwnerProcess.
1332 @return KErrNone if the operation was successful,
1333 KErrNoMemory if a new client link was needed but could not be created and
1334 added to the client list,
1335 KErrTooBig if the length of the descriptor passed is greater than 32.
1336 KErrAlreadyExists if the specified name already exists. This is valid only if
1337 DEBUG_VERSION macro is enabled.
1338 KErrNotSupported if number of expected kernel side clients is set to zero by
1341 @pre Interrupts must be enabled.
1342 @pre Kernel must be unlocked.
1343 @pre No fast mutex can be held.
1344 @pre Call in a thread context, but not from null thread or DFC thread1.
1345 @pre Can be used in a device driver
1347 TInt DPowerResourceController::RegisterClient(TUint& aClientId, const TDesC8& aName, TOwnerType aType)
1349 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterClient, Name = %S, Type = %d", &aName, aType));
1350 DThread& thread = Kern::CurrentThread();
1351 CHECK_CONTEXT(thread)
1352 //If number of expected kernel side clients is set to 0 during initial configuration
1353 //then dont allow to configure kernel side clients.
1354 if(!iClientList.GrowBy())
1355 return KErrNotSupported;
1356 if (aName.Length() > KMaxClientNameLength) return KErrTooBig;
1357 SPowerResourceClient *pC = NULL;
1359 #ifdef DEBUG_VERSION
1360 if(!iClientList.Find(pC, (TDesC8&)aName))
1361 UNLOCK_RETURN(KErrAlreadyExists);
1363 //Call from thread Id.
1364 TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
1365 req->ReqType() = TPowerRequest::ERegisterKernelClient;
1367 req->SendReceive(iMsgQ);
1368 if(req->ReturnCode() == KErrNone)
1370 pC = iClientList[(TUint16)(req->ClientId() & ID_INDEX_BIT_MASK)];
1371 if(aType == EOwnerThread)
1373 pC->iClientId |= CLIENT_THREAD_RELATIVE_BIT_MASK; //Set 31st bit;
1374 //Store the current thread Id;
1375 pC->iThreadId = thread.iId;
1378 aClientId = pC->iClientId;
1380 PRM_CLIENT_REGISTER_TRACE
1381 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterClient, clientId = 0x%x", aClientId));
1382 return(req->ReturnCode());
1385 #ifdef PRM_ENABLE_EXTENDED_VERSION
1386 TInt DPowerResourceController::HandleResourceRegistration(TPowerRequest& aReq)
1388 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::HandleResourceRegistration"));
1389 DDynamicPowerResource* pDRes = (DDynamicPowerResource*)aReq.Resource();
1390 //Add to appropriate container
1391 if(pDRes->iResourceId & KIdMaskResourceWithDependencies)
1392 ADD_TO_RESOURCE_CONTAINER(iDynamicResDependencyList, ((DDynamicPowerResourceD*)pDRes), aReq.ResourceId(),
1393 iDynamicResDependencyCount)
1395 ADD_TO_RESOURCE_CONTAINER(iDynamicResourceList, pDRes, aReq.ResourceId(), iDynamicResourceCount)
1397 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::HandleResourceRegistration"));
1406 This function runs in the context of the RC thread and
1407 handles registration of client (kernel and user side).
1409 TInt DPowerResourceController::HandleClientRegistration(TPowerRequest& aRequest)
1411 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterClient"));
1412 SPowerResourceClient* pC = NULL;
1414 if(aRequest.ReqType() == TPowerRequest::ERegisterKernelClient)
1416 //Get Next client from FreePool
1417 LIST_POP(iClientPool, pC, iNextInList);
1419 TUint16 growBy = iClientList.GrowBy();
1422 //Free Pool is empty, so try to grow the pool.
1423 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client pool exhausted so growing client Pool by %d", growBy));
1424 // coverity[alloc_fn]
1425 SPowerResourceClient *pCL = (SPowerResourceClient*)Kern::Alloc(sizeof(SPowerResourceClient) * growBy);
1428 __KTRACE_OPT(KRESMANAGER, Kern::Printf("No memory to grow client pool"));
1429 return(KErrNoMemory);
1431 #ifdef RESOURCE_MANAGER_SIMULATED_PSL
1432 iCleanList.Append(pCL);
1436 for(count = 0; count < growBy-1; count++)
1437 LIST_PUSH(iClientPool, &pCL[count], iNextInList);
1439 #ifdef PRM_INSTRUMENTATION_MACRO
1440 TUint size = growBy *sizeof(SPowerResourceClient);
1441 PRM_MEMORY_USAGE_TRACE
1446 if(iClientList.Allocd()==iClientList.Count())
1448 //Resize the container for holding client list
1449 if(iClientList.ReSize(growBy)!=KErrNone)
1451 __KTRACE_OPT(KRESMANAGER, Kern::Printf("No memory for client container allocation"));
1452 return(KErrNoMemory);
1456 iClientList.Add(pC, clientId);
1460 else // Request is registration of user side client
1462 //Get Next client from FreePool
1463 LIST_POP(iClientPool, pC, iNextInList);
1464 TUint16 growBy = iUserSideClientList.GrowBy();
1467 //Free Pool is empty, so try to grow the pool.
1468 SPowerResourceClient *pCL = (SPowerResourceClient*)Kern::Alloc(sizeof(SPowerResourceClient) * growBy);
1471 return KErrNoMemory;
1473 #ifdef RESOURCE_MANAGER_SIMULATED_PSL
1474 iCleanList.Append(pCL);
1478 for(count = 0; count < growBy - 1; count++)
1479 LIST_PUSH(iClientPool, &pCL[count], iNextInList);
1481 #ifdef PRM_INSTRUMENTATION_MACRO
1482 TUint size = growBy * sizeof(SPowerResourceClient);
1483 PRM_MEMORY_USAGE_TRACE
1488 //User side clients are always thread relative as they execute in the context of proxy driver.
1489 pC->iClientId = CLIENT_THREAD_RELATIVE_BIT_MASK; //Set 31st bit;
1490 pC->iClientId|=USER_SIDE_CLIENT_BIT_MASK;
1491 if(iUserSideClientList.Allocd()==iUserSideClientList.Count())
1493 //Resize the container for holding client list
1494 if(iUserSideClientList.ReSize(growBy)!=KErrNone)
1496 __KTRACE_OPT(KRESMANAGER, Kern::Printf("No memory for container class allocation"));
1497 return KErrNoMemory;
1501 iUserSideClientList.Add(pC, clientId);
1502 ++iUserSideClientCount;
1505 //Create the unique handle for each client
1506 //Client Handle format
1507 // 31 30 18 16 15 14 13 0
1508 // ¦----¦-----------------------------------¦----¦-----¦-----¦-----------------------------------¦
1509 // ¦ T/P¦ Container's instance count(15 bits¦C/R ¦ PC ¦ K/U ¦ Index into Client array container ¦
1510 // ¦----¦-----------------------------------¦----¦-----¦-----¦-----------------------------------¦
1511 // T/P -> Thread / process relative
1512 // PC -> Power Controller reserved ID.
1513 // K/U -> Kernel / User side clients
1514 // C/R -> Client / Resource Id. This bit will be set for dependency resource Id, zero for clientId.
1515 pC->iLevelList = NULL;
1516 pC->iNotificationList = NULL;
1517 pC->iDynamicResCount = 0;
1518 pC->iReservedCl = 0;
1519 pC->iReservedRm = 0;
1520 pC->iPendingReqCount = 0;
1521 pC->iUnderFlowRmCount = 0;
1522 pC->iUnderFlowClCount = 0;
1523 pC->iClientId |= clientId;
1524 aRequest.ClientId() = pC->iClientId;
1528 /** @internalComponent
1530 This is called as the result of client deregistration and takes care of resource state changes
1531 (to appropriate levels) of all the resources the client is holding active requirement. */
1532 void DPowerResourceController::ResourceStateChangeOfClientLevels(SPowerResourceClient* pC)
1534 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::ResourceStateChangeOfClientLevels"));
1535 TPowerRequest* pReq = (TPowerRequest*)&TPowerRequest::Get();
1536 DStaticPowerResource* pR = NULL;
1537 SPowerResourceClientLevel* pCL = pC->iLevelList;
1538 SPowerResourceClientLevel* pCLL = NULL;
1541 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client 0x%x has requirement on resource %d", pCL->iClientId, pCL->iResourceId));
1542 #ifdef PRM_ENABLE_EXTENDED_VERSION
1543 switch((pCL->iResourceId >>RESOURCE_BIT_IN_ID_CHECK) & 0x3)
1545 case PRM_STATIC_RESOURCE:
1546 pR = iStaticResourceArray[pCL->iResourceId - 1];
1548 case PRM_DYNAMIC_RESOURCE:
1549 pR = (iDynamicResourceList[(TUint16)(pCL->iResourceId & ID_INDEX_BIT_MASK)]);
1551 case PRM_STATIC_DEPENDENCY_RESOURCE:
1552 pR = (iStaticResDependencyArray[(TUint16)(pCL->iResourceId & ID_INDEX_BIT_MASK) - 1]);
1554 case PRM_DYNAMIC_DEPENDENCY_RESOURCE:
1555 pR = (iDynamicResDependencyList[(TUint16)(pCL->iResourceId & ID_INDEX_BIT_MASK)]);
1559 pR = iStaticResourceArray[pCL->iResourceId -1];
1561 #ifdef PRM_ENABLE_EXTENDED_VERSION
1562 if(((pR->Sense() == DStaticPowerResource::ECustom) || ((TInt)pCL->iClientId == pR->iLevelOwnerId)) && (!(pCL->iResourceId & KIdMaskDynamic) ||
1563 ((pCL->iResourceId & KIdMaskDynamic) && (((DDynamicPowerResource*)pR)->LockCount() != 0))))
1565 if((pR->Sense() == DStaticPowerResource::ECustom) || ((TInt)pCL->iClientId == pR->iLevelOwnerId))
1568 pReq->ReqType() = TPowerRequest::ESetDefaultLevel;
1569 pReq->ResourceId() = pCL->iResourceId;
1570 pReq->ClientId() = pCL->iClientId;
1571 pReq->Resource() = pR;
1572 pReq->Level() = pR->iCachedLevel;
1573 pReq->ResourceCb() = NULL;
1574 pReq->ReturnCode() = KErrNone;
1575 #ifdef PRM_INSTRUMENTATION_MACRO
1576 //Setting level to current level as correct level will be known only at the end,
1577 TInt aNewState = pR->iCachedLevel;
1578 TUint aResourceId = pReq->ResourceId();
1579 PRM_CLIENT_CHANGE_STATE_START_TRACE
1582 if(pR->LatencySet())
1584 #ifdef PRM_ENABLE_EXTENDED_VERSION
1585 if(pCL->iResourceId & KIdMaskDynamic)
1586 ((DDynamicPowerResource*)pR)->Lock();
1589 #ifdef PRM_ENABLE_EXTENDED_VERSION
1590 if(pR->iResourceId & KIdMaskResourceWithDependencies) //Dependency resource
1591 r = pReq->SendReceive(iMsgQDependency);
1594 r = pReq->SendReceive(iMsgQ);
1596 #ifdef PRM_ENABLE_EXTENDED_VERSION
1597 if(pCL->iResourceId & KIdMaskDynamic)
1598 ((DDynamicPowerResource*)pR)->UnLock();
1605 //Not checking return value as there is no memory allocation at this point
1606 CheckLevelAndAddClient(pC, pReq);
1610 pReq->ClientId() = -1;
1611 pReq->Level() = pR->iDefaultLevel;
1614 if((!pR->Usage()) || (pR->Usage() && pReq->RequiresChange()))
1616 // NOTE:Not checking error here as no action can be taken based on error.
1617 if(pR->iCachedLevel != pReq->Level())
1620 r = pR->DoRequest(*pReq);
1623 CompleteNotifications(pReq->ClientId(), pReq->Resource(), pReq->Level(),
1624 pReq->ReturnCode(), pReq->ClientId(), EFalse);
1625 #ifdef PRM_INSTRUMENTATION_MACRO
1626 PRM_CLIENT_CHANGE_STATE_END_TRACE
1628 pR->iLevelOwnerId = pReq->ClientId();
1629 pR->iCachedLevel = pReq->Level();
1630 if(pR->iIdleListEntry)
1632 SIdleResourceInfo* pI = (SIdleResourceInfo*)pR->iIdleListEntry;
1633 pI->iLevelOwnerId = pReq->ClientId();
1634 pI->iCurrentLevel = pReq->Level();
1640 /* Deque from resource */
1642 pCL = pCL->iNextInList;
1644 iClientLevelPoolCount++;
1645 LIST_PUSH(iClientLevelPool,pCLL,iNextInList); // back to free pool
1647 pC->iLevelList = NULL;
1648 //Add reserved client level to free pool
1649 iClientLevelPoolCount = (TUint16)(iClientLevelPoolCount + (TUint16)pC->iReservedCl);
1650 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::ResourceStateChangeOfClientLevels"));
1657 Deregister a client with the resource manager
1659 @param aClientId The ID of the client which is being deregistered
1661 @return KErrNone if the operation was successful
1662 KErrNotFound if this client ID could not be found in the current
1664 KErrArgument if user side client Id is specified or client ID to be used
1665 by Power Controller is specified.
1666 KErrAccessDenied if client was registered to be thread relative and this
1667 API is not called from the same thread.
1669 @pre Interrupts must be enabled
1670 @pre Kernel must be unlocked
1671 @pre No fast mutex can be held
1672 @pre Call in a thread context but not from null thread or DFC thread1
1673 @pre Can be used in a device driver
1675 TInt DPowerResourceController::DeRegisterClient(TUint aClientId)
1677 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::DeRegisterClient, ClientId = 0x%x", aClientId));
1678 DThread& thread = Kern::CurrentThread();
1679 CHECK_CONTEXT(thread)
1680 if((aClientId & USER_SIDE_CLIENT_BIT_MASK) || (aClientId == iPowerControllerId))
1681 return KErrArgument;
1682 //Get the index from client ID
1684 SPowerResourceClient* pC = iClientList[(TUint16)(aClientId & ID_INDEX_BIT_MASK)];
1687 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client ID not Found"));
1688 UNLOCK_RETURN(KErrNotFound);
1690 if(pC->iClientId != aClientId)
1692 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client ID does not match"));
1693 UNLOCK_RETURN(KErrNotFound);
1695 if(pC->iClientId & CLIENT_THREAD_RELATIVE_BIT_MASK)
1697 if(pC->iThreadId != thread.iId)
1699 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client not called from thread context(Thread Relative)"));
1700 UNLOCK_RETURN(KErrAccessDenied);
1703 //Check for any pending request
1704 if(pC->iPendingReqCount)
1707 Panic(EClientHasPendingAsyncRequest);
1709 //Check for notification request
1710 if(pC->iNotificationList)
1713 Panic(EClientHasNotificationObject);
1715 #ifdef PRM_ENABLE_EXTENDED_VERSION
1716 if(pC->iDynamicResCount)
1719 Panic(DPowerResourceController::EClientHasDynamicResourceRegistered);
1722 //Check for registration of dynamic resource
1723 ResourceStateChangeOfClientLevels(pC);
1724 // Add reserved request to pool
1725 iRequestPoolCount = (TUint16)(iRequestPoolCount + (TUint16)pC->iReservedRm);
1726 PRM_CLIENT_DEREGISTER_TRACE
1727 //Increment the free pool count for client level and request level.
1728 iClientList.Remove(pC, (TUint16)(pC->iClientId & ID_INDEX_BIT_MASK));
1730 iClientCount--; //Decrement client count
1731 LIST_PUSH(iClientPool, pC, iNextInList);
1732 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::DeRegisterClient"));
1733 UNLOCK_RETURN(KErrNone);
1740 Obtain the name of a registered client of the resource manager
1742 @param aClientId The ID of the client which is requesting the name of
1743 another client whose ID is specified in aTargetClientId.
1744 @param aTargetClientId The ID of the client whose name is being requested.
1745 @param aName Descriptor to be filled with the name of the client. The descriptor
1746 is created by the client in kernel stack or heap.
1748 @return KErrNone if the operation was successful
1749 KErrNotFound if this client ID (aTargetClientId) could not be
1750 found in the current list of registered clients.
1751 KErrAccessDenied if the client ID (aClientId) could not be found
1752 in the current list of registered clients or if client was registered
1753 to be thread relative and this API is not called from the same thread.
1754 KErrArgument if size of aName is less than 32.
1756 @pre Interrupts must be enabled
1757 @pre Kernel must be unlocked
1758 @pre No fast mutex can be held
1759 @pre Call in a thread context but not from null thread or DFC thread1
1760 @pre Can be used in a device driver
1762 TInt DPowerResourceController::GetClientName(TUint aClientId, TUint aTargetClientId, TDes8& aName)
1764 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetClientName, CallingClientId = 0x%x, TargetClientId = 0x%x", aClientId, aTargetClientId));
1765 DThread& thread = Kern::CurrentThread();
1766 CHECK_CONTEXT(thread)
1767 if((aName.MaxLength() - aName.Length()) < KMaxClientNameLength)
1768 return KErrArgument;
1769 SPowerResourceClient* pC = NULL;
1771 VALIDATE_CLIENT(thread);
1772 GET_TARGET_CLIENT();
1773 aName.Append(*pC->iName);
1774 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetClientName, ClientName = %S", &aName));
1775 UNLOCK_RETURN(KErrNone);
1782 Obtain the Id of registered client of the resource manager
1784 @param aClientId ID of the client which is requesting the ID of the another
1785 client whose name is specified in aClientName
1786 @param aClientName Descriptor containing the name of the client whose ID is being
1787 requested. The client must create the descriptor in kernel stack
1789 NOTE: Resource manager does not check for uniqueness of client
1790 name during registration, so if there are multiple clients registered
1791 to PRM with same name it will return the ID of the first client it encounters.
1792 @param aTargetClientId Updates with ID of the requested client on success
1794 @return KErrNone if the operation was successful
1795 KErrNotFound if this client name could not be found in the current list of registered
1797 KErrAccessDenied if the client ID (aClientId) could not be found in the current
1798 list of registered client or if the client was registered to be
1799 thread relative and this API is not called from the same thread.
1800 KErrTooBig if the length of the descriptor passed is greater than 32.
1802 @pre Interrupts must be enabled
1803 @pre Kernel must be unlocked
1804 @pre No fast mutex can be held
1805 @pre Call in a thread context but not from null thread or DFC thread1
1806 @pre Can be used in a device driver
1808 TInt DPowerResourceController::GetClientId(TUint aClientId, TDesC8& aClientName, TUint& aTargetClientId)
1810 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetClientId CallingClientId = 0x%x, ClientName = %S", aClientId, &aClientName));
1811 DThread& thread = Kern::CurrentThread();
1812 CHECK_CONTEXT(thread)
1813 if(aClientName.Length() > KMaxClientNameLength)
1815 SPowerResourceClient* pC = NULL;
1817 VALIDATE_CLIENT(thread);
1818 //Find the client ID with the specified name first from kernel client list & then user side.
1819 if(iClientList.Find(pC, aClientName) && iUserSideClientList.Find(pC, aClientName))
1820 UNLOCK_RETURN(KErrNotFound);
1821 aTargetClientId = pC->iClientId;
1822 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetClientId TargetClientId = 0x%x", aTargetClientId));
1823 UNLOCK_RETURN(KErrNone);
1830 Obtain the ID of registered resource of the resource manager.
1831 NOTE: ID of the first matching name found in the resource list will be returned
1833 @param aClientId ID of the client which is requesting the ID of the
1834 resource, by specifying its name.
1835 @param aResourceName Descriptor containing the name of the resource whose
1836 ID is being requested.
1837 @param aResourceId Updates with ID of the requested resource on success
1839 @return KErrNone if the operation was successful
1840 KErrAccessDenied if the ID of the client could not be found in the
1841 current list of registered clients or if the client was
1842 registered to be thread relative and this API is not called
1843 from the same thread.
1844 KErrNotFound if this resource name could not be found in the current
1845 list of registered resources.
1846 KErrTooBig if the length of the descriptor passed is greater than maximum
1847 allowable resource name length (32).
1848 @pre Interrupts must be enabled
1849 @pre Kernel must be unlocked
1850 @pre No fast mutex can be held
1851 @pre Call in a thread context but not from null thread or DFC thread1
1852 @pre Can be used in a device driver
1854 TInt DPowerResourceController::GetResourceId(TUint aClientId, TDesC8& aResourceName, TUint& aResourceId)
1856 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetResourceId"));
1857 __KTRACE_OPT(KRESMANAGER, Kern::Printf("CallingClientId = 0x%x, ResourceName = %S", aClientId, &aResourceName));
1858 DThread& thread = Kern::CurrentThread();
1859 CHECK_CONTEXT(thread)
1860 SPowerResourceClient* pC;
1861 if(aResourceName.Length() > KMaxResourceNameLength)
1864 VALIDATE_CLIENT(thread);
1866 //Search in static resource with no dependencies array for specified resource name.
1867 for(count = 0; count < iStaticResourceArrayEntries; count++)
1869 if((iStaticResourceArray[count]) && (!(aResourceName.Compare(*(const TDesC8*)iStaticResourceArray[count]->iName))))
1871 aResourceId = ++count;
1872 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetResourceId, ResourceId = 0x%x", aResourceId));
1873 UNLOCK_RETURN(KErrNone);
1876 #ifdef PRM_ENABLE_EXTENDED_VERSION
1877 //Search in dynamic resource with no dependencies array for specified resource name.
1878 DDynamicPowerResource* pDR = NULL;
1879 if(PowerResourceController->iDynamicResourceCount &&
1880 !PowerResourceController->iDynamicResourceList.Find(pDR, aResourceName))
1882 aResourceId = pDR->iResourceId;
1883 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetResourceId, ResourceId = 0x%x", aResourceId));
1884 UNLOCK_RETURN(KErrNone);
1886 //Search in static resource with dependencies (if exists) for specified resource name
1887 for(count = 0; count < iStaticResDependencyCount; count++)
1889 if(!(aResourceName.Compare(*(const TDesC8*)iStaticResDependencyArray[count]->iName)))
1891 aResourceId = iStaticResDependencyArray[count]->iResourceId;
1892 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetResourceId, ResourceId = 0x%x", aResourceId));
1893 UNLOCK_RETURN(KErrNone);
1896 //Search in dynamic resource with dependencies (if exists) for specified resource name
1897 DDynamicPowerResourceD* pDRD;
1898 if(iDynamicResDependencyCount && !iDynamicResDependencyList.Find(pDRD, aResourceName))
1900 aResourceId = pDRD->iResourceId;
1901 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetResourceId, ResourceId = 0x%x", aResourceId));
1902 UNLOCK_RETURN(KErrNone);
1905 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetResourceId, ResourceID not found"));
1906 UNLOCK_RETURN(KErrNotFound);
1913 Request a structure containing information on a resource.
1915 @param aClientId ID of the client which is requesting the resource information
1916 @param aResourceId ID of the resource whose information is being requested.
1917 @param aInfo A pointer to descriptor containing resource information
1918 structure (TPowerResourceInfoV01) to be filled in
1919 with the requested resource information. The client must
1920 create the descriptor in kernel stack or heap.
1922 @return KErrNone if the operation was successful
1923 KErrAccessDenied if the client ID could not be found in the current list
1924 of registered clients or if the client was registered to be
1925 thread relative and this API is not called from the same thread.
1926 KErrNotFound if this resource ID could not be found in the current list
1927 of controllable resource.
1928 KErrArgument if aInfo is NULL or size of descriptor passed is less than size of
1929 TPowerResourceInfoV01.
1930 @pre Interrupts must be enabled
1931 @pre Kernel must be unlocked
1932 @pre No fast mutex can be held
1933 @pre Call in a thread context but not from null thread or DFC thread1
1934 @pre Can be used in a device driver
1936 TInt DPowerResourceController::GetResourceInfo(TUint aClientId, TUint aResourceId, TAny* aInfo)
1938 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetResourceInfo"));
1939 __KTRACE_OPT(KRESMANAGER, Kern::Printf("CallingClientId = 0x%x, ResourceId = %d", aClientId, aResourceId));
1940 DThread& thread = Kern::CurrentThread();
1941 CHECK_CONTEXT(thread)
1943 return KErrArgument;
1944 SPowerResourceClient* pC = NULL;
1946 VALIDATE_CLIENT(thread);
1947 TDes8* buf = (TDes8*)aInfo;
1949 DStaticPowerResource *pR = NULL;
1951 //Validate buffer size
1952 if((TUint)(buf->MaxLength() - buf->Length()) < sizeof(TPowerResourceInfoV01))
1953 UNLOCK_RETURN(KErrArgument);
1955 #ifndef PRM_ENABLE_EXTENDED_VERSION
1956 if((!aResourceId) || (aResourceId > iStaticResourceArrayEntries))
1957 UNLOCK_RETURN(KErrNotFound);
1958 //Get resource from static resource array. 0(1) operation.
1959 pR = iStaticResourceArray[aResourceId-1];
1962 UNLOCK_RETURN(KErrNotFound);
1967 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetResourceInfo, return value = %d", KErrNotFound));
1968 UNLOCK_RETURN(KErrNotFound);
1970 //Get resource from corresponding container
1971 GET_RESOURCE_FROM_LIST(aResourceId, pR)
1973 //Update resource info
1974 TPowerResourceInfoBuf01 infoBuf;
1975 r = pR->GetInfo((TDes8*)infoBuf.Ptr());
1977 ((TPowerResourceInfoV01*)infoBuf.Ptr())->iResourceId = aResourceId;
1979 buf->Append(infoBuf);
1987 Request number of resources the specified client (aTargetClientId) has
1988 requirement on resource level. Client ID starts from 1, so if 0 is specified in
1989 aTargetClientId, returns the number of controllable resources registered with PRM.
1991 @param aClientId ID of the client which is requesting the number of resources
1992 the specified client (aTargetClientId) holds requirement on
1993 resource level change.
1994 @param aTargetClientId ID of the client. The number of resources on which it
1995 has requirement on resource level change is requested.
1996 @param aNumResource Updated with the number of resources the specified client
1997 has requirement on resource level change, if valid client
1998 ID is passed. If client ID is 0, updates the total number
1999 of resources registered with resource manager.
2001 @return KErrNone if the operation was successful.
2002 KErrAccessDenied if the client ID (aClientId) could not be found in the
2003 current list of registered clients or if the client was registered
2004 to be thread relative and this API is not called from the same thread.
2005 KErrNotFound if the client ID (aTargetClientId) could not be found in the
2006 current list of registered clients and is not 0.
2008 @pre Interrupts must be enabled
2009 @pre Kernel must be unlocked
2010 @pre No fast mutex can be held
2011 @pre Call in a thread context but not from null thread or DFC thread1
2012 @pre Can be used in a device driver
2014 TInt DPowerResourceController::GetNumResourcesInUseByClient(TUint aClientId, TUint aTargetClientId, TUint& aNumResource)
2016 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetNumResourcesInUseByClient"));
2017 __KTRACE_OPT(KRESMANAGER, Kern::Printf("CallingClientId = 0x%x, TargetClientId = 0x%x", aClientId, aTargetClientId));
2018 DThread& thread = Kern::CurrentThread();
2019 CHECK_CONTEXT(thread)
2020 SPowerResourceClient* pC = NULL;
2022 VALIDATE_CLIENT(thread);
2023 //Special case, return number of resources registered resource controller.
2024 if(!aTargetClientId)
2026 #ifdef PRM_ENABLE_EXTENDED_VERSION
2027 aNumResource = iStaticResourceCount + iDynamicResourceCount + iStaticResDependencyCount +
2028 iDynamicResDependencyCount;
2030 aNumResource = iStaticResourceCount;
2032 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetNumResourcesInUseByClient, numResources = %d", aNumResource));
2033 UNLOCK_RETURN(KErrNone);
2035 GET_TARGET_CLIENT();
2036 SPowerResourceClientLevel* pCL = pC->iLevelList;
2041 pCL = pCL->iNextInList;
2043 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetNumResourcesInUseByClient, numResources = %d", aNumResource));
2044 UNLOCK_RETURN(KErrNone);
2051 Request information on resources.
2052 If client ID (aTargetClientId) is valid, aInfo is updated with the information of the resources
2053 this client hold requirement on the resource level.
2054 If client ID (aTargetClientId) is 0, aInfo is updated with the information of the resources
2055 registered with resource controller.
2056 Number of resource information updated will be equal or less than the number specified in aNumResources.
2058 @param aClientId ID of the client which is requesting the resource information.
2059 @param aTargetClientId ID of the client. The information of all the resources on
2060 which it has requirement on resource level change is requested.
2061 Client ID starts from 1, so calling this API with client ID 0 will
2062 fill the details of all the controllable resource registered with
2064 @param aNumResources Number of resource whose information needs to be filled in aInfo i.e,
2065 it specifies the size of aInfo array.
2066 @param aInfo A pointer to an array of descriptor containing an information structure
2067 (TPowerResourceInfoV01) to be filled in with the information
2068 on the resources. It will be assumed that array allocated will be equal
2069 to the number passed in aNumResources. The client must create the array
2070 in Kernel stack or heap.
2072 @return KErrNone if the operation was successful
2073 KErrAccessDenied if client ID (aClientId) could not be found in the registered
2074 client list or if the client was registered to be thread relative
2075 and this API is not called from the same thread.
2076 KErrNotFound if client ID (aTargetClientId) could not be found in the current list
2077 of registered client and is also not 0.
2078 KErrArgument if aNumResources is 0 or aInfo is NULL or if size of aInfo is not sufficient
2079 to hold the resource information of number of resources specified in aNumResources.
2081 @pre Interrupts must be enabled
2082 @pre Kernel must be unlocked
2083 @pre No fast mutex can be held
2084 @pre Call in a thread context but not from null thread or DFC thread1
2085 @pre Can be used in a device driver
2087 TInt DPowerResourceController::GetInfoOnResourcesInUseByClient(TUint aClientId, TUint aTargetClientId,
2088 TUint& aNumResources, TAny* anInfo)
2090 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetInfoOnResourcesInUseByClient"));
2091 __KTRACE_OPT(KRESMANAGER, Kern::Printf("CallingClientId = 0x%x, TargetClientId = 0x%x, NumResources = %d", \
2092 aClientId, aTargetClientId, aNumResources));
2093 DThread& thread = Kern::CurrentThread();
2094 CHECK_CONTEXT(thread)
2095 if(!anInfo || !aNumResources)
2096 return KErrArgument;
2097 SPowerResourceClient* pC = NULL;
2099 VALIDATE_CLIENT(thread);
2100 DStaticPowerResource* pR = NULL;
2101 TDes8 *pInfo = (TDes8*)anInfo;
2102 if((TUint)(pInfo->MaxLength() - pInfo->Length()) < (sizeof(TPowerResourceInfoV01) * aNumResources))
2103 UNLOCK_RETURN(KErrArgument);
2104 TPowerResourceInfoBuf01 buf;
2108 //Special case, if aTargetClientId is 0 fill with all the resource
2109 if(!aTargetClientId)
2111 TUint numResources = aNumResources;
2112 #ifndef PRM_ENABLE_EXTENDED_VERSION
2113 aNumResources = iStaticResourceCount;
2115 aNumResources = iStaticResourceCount + iDynamicResourceCount + iStaticResDependencyCount +
2116 iDynamicResDependencyCount;
2119 while(count < iStaticResourceArrayEntries)
2121 if(numResources <=0)
2123 pR = iStaticResourceArray[count++];
2126 r = pR->GetInfo((TDes8*)buf.Ptr());
2129 //Update Resource Id.
2130 ((TPowerResourceInfoV01*)buf.Ptr())->iResourceId = count;
2134 #ifdef PRM_ENABLE_EXTENDED_VERSION
2136 while(count < iStaticResDependencyCount)
2138 if(count >= numResources)
2140 pR = iStaticResDependencyArray[count++];
2141 r = pR->GetInfo((TDes8*)buf.Ptr());
2142 //Update Resource Id.
2143 ((TPowerResourceInfoV01*)buf.Ptr())->iResourceId = ((DStaticPowerResourceD*)pR)->iResourceId;
2148 numResources -= iStaticResDependencyCount;
2149 if((!numResources) || (!iDynamicResourceCount && !iDynamicResDependencyCount))
2153 for(count = 0; count < iDynamicResourceList.Allocd(); count++)
2155 pR = iDynamicResourceList[count];
2158 if((resCount >= iDynamicResourceCount) || (resCount >= numResources))
2159 UNLOCK_RETURN(KErrNone);
2160 r = pR->GetInfo((TDes8*)buf.Ptr());
2163 ((TPowerResourceInfoV01*)buf.Ptr())->iResourceId = ((DDynamicPowerResource*)pR)->iResourceId;
2167 numResources -= resCount;
2169 for(count = 0; count < iDynamicResDependencyList.Allocd(); count++)
2171 pR = iDynamicResDependencyList[count];
2174 if((resCount >= iDynamicResDependencyCount) || (resCount >= numResources))
2175 UNLOCK_RETURN(KErrNone);
2176 r = pR->GetInfo((TDes8*)buf.Ptr());
2179 ((TPowerResourceInfoV01*)buf.Ptr())->iResourceId = ((DDynamicPowerResourceD*)pR)->iResourceId;
2187 GET_TARGET_CLIENT();
2188 SPowerResourceClientLevel* pCL = pC->iLevelList;
2189 for (count= 0; pCL; count++, pCL = pCL->iNextInList)
2191 if(count >= aNumResources)
2193 #ifndef PRM_ENABLE_EXTENDED_VERSION
2194 pR = iStaticResourceArray[pCL->iResourceId-1];
2196 GET_RESOURCE_FROM_LIST(pCL->iResourceId, pR);
2198 r = pR->GetInfo((TDes8*)buf.Ptr());
2199 //Update Resource Id.
2200 ((TPowerResourceInfoV01*)buf.Ptr())->iResourceId = pCL->iResourceId;
2205 aNumResources = count;
2206 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetInfoOnResourcesInUseByClient, AcutalNoOfResources = %d", aNumResources));
2207 UNLOCK_RETURN(KErrNone);
2214 Request number of clients which has requirements on the resource level of the specified
2215 resource. Resource ID starts from 1, so 0 can be used to get the number of clients
2216 registered with resource manager.
2218 @param aClientId ID of the client which is requesting number of clients
2219 holding requirement on specified resource.
2220 @param aResourceId ID of the resource.
2221 @param aNumClient This is updated with number of clients having a requirement
2222 on resource level if valid resource ID is specified.
2223 If resource ID is 0, then it is updated with number of clients
2224 registered with PRM.
2226 @return KErrNone if the operation was successful
2227 KErrAccessDenied if the client ID could not found in the current list of
2228 registered clients or if the client was registered to be thread
2229 relative and this API is not called from the same thread.
2230 KErrNotFound If this resource ID could not be found in the current list
2231 of registered resource and is also not 0.
2233 @pre Interrupts must be enabled
2234 @pre Kernel must be unlocked
2235 @pre No fast mutex can be held
2236 @pre Call in a thread context but not from null thread or DFC thread1
2237 @pre Can be used in a device driver
2239 TInt DPowerResourceController::GetNumClientsUsingResource(TUint aClientId, TUint aResourceId, TUint& aNumClients)
2241 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetNumClientsUsingResource"));
2242 __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d", aClientId, aResourceId));
2243 DThread& thread = Kern::CurrentThread();
2244 CHECK_CONTEXT(thread)
2245 SPowerResourceClient* pC = NULL;
2247 VALIDATE_CLIENT(thread);
2250 //Special case return the number of clients registered with resource controller.
2251 aNumClients = iClientCount + iUserSideClientCount;
2252 UNLOCK_RETURN(KErrNone);
2254 #ifdef PRM_ENABLE_EXTENDED_VERSION
2255 DStaticPowerResource* pR = NULL;
2256 GET_RESOURCE_FROM_LIST(aResourceId, pR)
2258 if(aResourceId > iStaticResourceArrayEntries)
2259 UNLOCK_RETURN(KErrNotFound);
2260 DStaticPowerResource* pR = iStaticResourceArray[aResourceId-1];
2262 UNLOCK_RETURN(KErrNotFound);
2265 for(SDblQueLink*pCL = pR->iClientList.First(); pCL != &pR->iClientList.iA; pCL=pCL->iNext)
2267 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetNumClientsUsingResource, NumClients = %d", aNumClients));
2268 UNLOCK_RETURN(KErrNone);
2275 Request information on clients
2276 If resource ID is valid, aInfo is updated with the information of the clients
2277 which have a requirement on the resource level for the specified resource
2278 If resource ID is 0, aInfo is updated with the information of the clients registered
2279 with resource manager, starting from client ID 1.
2280 The number of clients for which information will be provided will be equal to or less
2281 than the number specified in aNumClients.
2282 @param aClientId ID of the client which is requesting the information on
2283 the clients which holds requirement on specified
2284 resource's level change.
2285 @param aResourceId Id of the resource.
2286 @param aNumClients Number of clients whose information needs to be filled in aInfo
2287 i.e., it specifies the size of aInfo array.
2288 @param aInfo A pointer to an array of descriptor containing an information
2289 structure (TPowerClientInfoV01) to be filled in with
2290 the information on the client. It will be assumed that array
2291 allocated will be equal to the number passed in aNumClients.
2292 The Client must create the array of descriptors in kernel stack
2295 @return KErrNone if the operation was successful.
2296 KErrNotFound if resource ID could not be found in the registered resource list and is not 0.
2297 KErrAccessDenied if client ID (aClientId) could not be found in the registered client
2298 list or if the client was registered to be thread relative and this API is not
2299 called from the same thread.
2300 KErrArgument if aNumClients is 0 or aInfo is NULL or if size of aInfo is not sufficient to hold
2301 client information of specified client number in aNumClients.
2303 @pre Interrupts must be enabled
2304 @pre Kernel must be unlocked
2305 @pre No fast mutex can be held
2306 @pre Call in a thread context but not from null thread or DFC thread1
2307 @pre Can be used in a device driver
2309 TInt DPowerResourceController::GetInfoOnClientsUsingResource(TUint aClientId, TUint aResourceId,
2310 TUint& aNumClients, TAny* anInfo)
2312 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetInfoOnClientsUsingResource"));
2313 __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d, NumClients = %d", \
2314 aClientId, aResourceId, aNumClients));
2315 DThread& thread = Kern::CurrentThread();
2316 CHECK_CONTEXT(thread)
2317 if(!anInfo || !aNumClients)
2318 return KErrArgument;
2319 SPowerResourceClient* pC = NULL;
2321 VALIDATE_CLIENT(thread);
2322 TDes8 *pInfo = (TDes8*)anInfo;
2323 if((TUint)(pInfo->MaxLength() - pInfo->Length()) < (sizeof(TPowerClientInfoV01) * aNumClients))
2324 UNLOCK_RETURN(KErrArgument);
2325 TPowerClientInfoV01 info;
2326 if(aResourceId == 0)
2328 TUint16 count = 0, resCount = 0;
2329 for(count = 0; count < iClientList.Allocd(); count++)
2331 if((resCount >= iClientCount) || (resCount >= aNumClients))
2333 pC = iClientList[count];
2337 info.iClientId = pC->iClientId;
2338 info.iClientName = (TDesC8*)pC->iName;
2339 pInfo->Append(TPckgC<TPowerClientInfoV01>(info));
2341 aNumClients -= resCount;
2343 for(count = 0; count < iUserSideClientList.Allocd(); count++)
2345 if((resCount >= iUserSideClientCount) || (resCount >= aNumClients))
2347 pC = iUserSideClientList[count];
2351 info.iClientId = pC->iClientId;
2352 info.iClientName = (TDesC8*)pC->iName;
2353 pInfo->Append(TPckgC<TPowerClientInfoV01>(info));
2355 aNumClients = iClientCount + iUserSideClientCount;
2356 UNLOCK_RETURN(KErrNone);
2358 #ifdef PRM_ENABLE_EXTENDED_VERSION
2359 DStaticPowerResource* pR = NULL;
2360 GET_RESOURCE_FROM_LIST(aResourceId, pR)
2362 if(aResourceId > iStaticResourceArrayEntries)
2363 UNLOCK_RETURN(KErrNotFound);
2364 DStaticPowerResource* pR = iStaticResourceArray[aResourceId-1];
2366 UNLOCK_RETURN(KErrNotFound);
2368 SPowerResourceClientLevel* pCL = NULL;
2370 for(SDblQueLink* pRC = pR->iClientList.First(); pRC != &pR->iClientList.iA; pRC = pRC->iNext, c++)
2372 if(c >= aNumClients)
2374 pCL = (SPowerResourceClientLevel*)pRC;
2375 if(pCL->iClientId & USER_SIDE_CLIENT_BIT_MASK)
2376 pC = iUserSideClientList[(TUint16)(pCL->iClientId & ID_INDEX_BIT_MASK)];
2378 pC = iClientList[(TUint16)(pCL->iClientId & ID_INDEX_BIT_MASK)];
2379 info.iClientId = pC->iClientId;
2380 info.iClientName = (TDesC8*)pC->iName;
2381 pInfo->Append(TPckgC<TPowerClientInfoV01>(info));
2384 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetInfoOnClientsUsingResource, NumClients = %d", aNumClients));
2385 UNLOCK_RETURN(KErrNone);
2392 Request changing the state of a resource
2393 NOTE: If a resource callback is specified for instantaneous resource, then callback
2394 will be called after resource change and will be executed in the context of the
2396 If a resource callback is specified for long latency reosurces, then it will be
2397 executed asynchronously.When the request is accepted the API returns immediately
2398 and the calling thread is unblocked: the callback (called in the client's context)
2399 will be invoked when the resource change finally takes place.
2400 If aCb is not specified (NULL by default) the API executes synchronously and will
2401 only return when the resource change has taken place for long latency resource.
2402 The client thread is blocked throughout
2403 When state change for a shared resource is requested, only minimum state that
2404 satisfy the requirement is guaranteed and it is not guaranteed for the absolute
2407 @param aClientId ID of the client which is requesting the resource change.
2408 @param aResourceId ID of the resource whose state is to be changed.
2409 @param aNewState The new state of the resource. This could be a binary value for a
2410 binary resource, an integer level for a multilevel resource or some
2411 platform specific token for a multi-property resource.
2412 @param aCb For Long latency resource
2413 A pointer to a resource callback object which encapsulates a
2414 callback function to be called whenever the resource state change
2415 happens (if left NULL the API will execute synchrounously).
2416 For Instantaneous resource
2417 A pointer to a resource callback object which encapsulates a callback
2418 function to be called after resource change. This executes in the
2419 context of the client thread.
2421 @return KErrNone If the API is to be executed synchronously it indicates the change was
2422 successful, if the API is to be executed asynchronously it indicates
2423 the request to change the resource state has been accepted.
2424 KErrNotFound if the resource ID could not be found in the current list of
2425 controllable resources.
2426 KErrAccessDenied if the client ID could not be found in the list of
2427 registered clients or if the client was registered to be thread
2428 relative and this API is not called from the same thread or if the
2429 resource is single user resource and another client is already holding
2431 KErrNotReady if the request is issued before the resource controller completes its
2432 internal initialisation.
2433 KErrUnderflow if the client has exceeded the reserved number of
2434 SPowerResourceClientLevel and the free pool is empty or if it is
2435 an asynchronous operation on a long latency resource and the client has
2436 exceeded the reserved number of TPowerRequest and the free pool is empty.
2437 KErrArgument if requested level is out of range (outside of min and max levels).
2438 KErrCorrupt if internal data structure is corrupted.
2439 KErrPermissionDenied if the requested state of the resource is not accepted by its dependents.
2440 This error is valid only for dependent resource state change in extended version
2443 @pre Interrupts must be enabled
2444 @pre Kernel must be unlocked
2445 @pre No fast mutex can be held
2446 @pre Call in a thread context but not from null thread or DFC thread1
2447 @pre Can be used in a device driver
2448 @pre Do not call synchronous version from DFC thread 0 for long latency resource
2450 TInt DPowerResourceController::ChangeResourceState(TUint aClientId, TUint aResourceId, TInt aNewState,
2451 TPowerResourceCb* aCb)
2453 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::ChangeResourceState"));
2454 __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d, NewState = %d", aClientId, \
2455 aResourceId, aNewState));
2456 DThread& thread = Kern::CurrentThread();
2457 CHECK_CONTEXT(thread)
2458 if(iInitialised <= EResConCreated)
2459 return KErrNotReady;
2461 return KErrNotFound;
2462 SPowerResourceClient* pC = NULL;
2465 VALIDATE_CLIENT(thread);
2466 #ifdef PRM_ENABLE_EXTENDED_VERSION
2467 DStaticPowerResource *pR = NULL;
2468 GET_RESOURCE_FROM_LIST(aResourceId, pR)
2470 if(aResourceId > iStaticResourceArrayEntries)
2471 UNLOCK_RETURN(KErrNotFound);
2472 DStaticPowerResource* pR = iStaticResourceArray[aResourceId-1];
2474 UNLOCK_RETURN(KErrNotFound);
2476 //Return if the resource is already in that state and client is also the same.
2477 if((aNewState == pR->iCachedLevel) && ((TInt)aClientId == pR->iLevelOwnerId))
2478 UNLOCK_RETURN(KErrNone);
2481 PRM_CLIENT_CHANGE_STATE_START_TRACE
2482 //If long latency resource requested synchronously from DFC thread 0 Panic
2484 const TDesC8* pDfc0 = &KDfcThread0Name;
2485 if((pR->LatencySet() && !aCb) && !(pDfc0->Compare(*(TDesC8*)thread.iName)))
2488 Panic(ECalledFromDfcThread0);
2490 if(!pR->Usage() && !pR->iClientList.IsEmpty())
2492 SPowerResourceClientLevel* pCL = (SPowerResourceClientLevel*)pR->iClientList.First();
2493 if((pCL != NULL) && (pCL->iClientId != pC->iClientId))
2495 r = KErrAccessDenied;
2496 PRM_CLIENT_CHANGE_STATE_END_TRACE
2500 #ifdef PRM_ENABLE_EXTENDED_VERSION
2501 if(aResourceId & KIdMaskDynamic)
2503 //Resource in the process of deregistration
2504 if(((DDynamicPowerResource*)pR)->LockCount() == 0)
2507 PRM_CLIENT_CHANGE_STATE_END_TRACE
2512 //Validate requested level
2513 TPowerResourceInfoBuf01 buf;
2514 r = pR->GetInfo((TDes8*)buf.Ptr());
2517 PRM_CLIENT_CHANGE_STATE_END_TRACE
2520 TPowerResourceInfoV01 *pBuf = (TPowerResourceInfoV01*)buf.Ptr();
2521 if(((pBuf->iMinLevel > pBuf->iMaxLevel) && ((aNewState > pBuf->iMinLevel) || (aNewState < pBuf->iMaxLevel)))
2522 || ((pBuf->iMaxLevel > pBuf->iMinLevel) && ((aNewState > pBuf->iMaxLevel) || (aNewState < pBuf->iMinLevel))))
2525 PRM_CLIENT_CHANGE_STATE_END_TRACE
2530 SPowerRequest* pS=NULL;
2531 if(pR->LatencySet() && aCb)
2533 // Get request object from free pool, as it is long latency reosurce as client
2534 // will be unblocked once message is sent to controller, so cant use thread message.
2535 if(pC->iReservedRm ==0 && !iRequestPoolCount)
2538 PRM_CLIENT_CHANGE_STATE_END_TRACE
2542 LIST_POP(iRequestPool, pS, iNext);
2544 UNLOCK_RETURN(KErrCorrupt); //This should not happen
2545 if(pC->iReservedRm==0)
2547 iRequestPoolCount--;
2548 pC->iUnderFlowRmCount++;
2553 pC->iPendingReqCount++;
2556 req=(TPowerRequest*)&TPowerRequest::Get();
2557 #ifdef PRM_ENABLE_EXTENDED_VERSION
2558 if(aResourceId & KIdMaskDynamic)
2559 ((DDynamicPowerResource*)pR)->Lock();
2561 req->Level() = aNewState;
2562 req->ResourceId() = aResourceId;
2563 req->ClientId() = aClientId;
2564 req->ReqType() = TPowerRequest::EChange;
2565 req->Resource() = pR;
2568 aCb->iResult = KErrNone;
2569 aCb->iResourceId = aResourceId;
2570 aCb->iClientId = aClientId;
2572 req->ResourceCb() = aCb;
2573 if(pR->LatencySet())
2578 #ifdef PRM_ENABLE_EXTENDED_VERSION
2579 if (aCb->iResourceId & KIdMaskResourceWithDependencies) //Dependency resource
2581 req->Send(iMsgQDependency); // Send the request to DFC thread.
2587 req->Send(iMsgQ); // Send the request to Resource Controler thread.
2591 #ifdef PRM_ENABLE_EXTENDED_VERSION
2592 if(aResourceId & KIdMaskResourceWithDependencies) //Dependency resource
2594 r = req->SendReceive(iMsgQDependency); // Send the request to DFC thread.
2599 r = req->SendReceive(iMsgQ); // Block till the controller completes with the request.
2601 #ifdef PRM_ENABLE_EXTENDED_VERSION
2603 if(aResourceId & KIdMaskDynamic)
2604 ((DDynamicPowerResource*)pR)->UnLock();
2611 r = CheckLevelAndAddClient(pC, req);
2612 if((r != KErrNone)|| !req->RequiresChange())
2614 req->Level() = pR->iCachedLevel;
2615 #ifdef PRM_ENABLE_EXTENDED_VERSION
2616 if(aResourceId & KIdMaskDynamic)
2617 ((DDynamicPowerResource*)pR)->UnLock();
2622 //Invoke callback function
2623 aCb->iCallback(req->ClientId(), aResourceId, req->Level(), pR->iLevelOwnerId, r, aCb->iParam);
2624 //Mark the callback object to act properly during cancellation of this request.
2625 aCb->iResult = KErrCompletion;
2627 PRM_CLIENT_CHANGE_STATE_END_TRACE
2631 else if(pR->iLevelOwnerId == -1)
2633 /* Add client Level */
2634 if(pC->iReservedCl<=0 && !iClientLevelPoolCount)
2637 PRM_CLIENT_CHANGE_STATE_END_TRACE
2638 #ifdef PRM_ENABLE_EXTENDED_VERSION
2639 if(aResourceId & KIdMaskDynamic)
2640 ((DDynamicPowerResource*)pR)->UnLock();
2645 SPowerResourceClientLevel* pSCL=NULL;
2646 LIST_POP(iClientLevelPool, pSCL, iNextInList);
2647 pSCL->iClientId=aClientId;
2648 pSCL->iResourceId=aResourceId;
2649 pSCL->iLevel=aNewState;
2650 LIST_PUSH(pC->iLevelList, pSCL, iNextInList);
2651 pR->iClientList.Add(pSCL);
2652 if(pC->iReservedCl==0)
2654 iClientLevelPoolCount--;
2655 pC->iUnderFlowClCount++;
2662 //Update the level in the client list.
2663 SPowerResourceClientLevel* pSCL = (SPowerResourceClientLevel*)pR->iClientList.First();
2664 pSCL->iLevel = aNewState;
2667 r = pR->DoRequest(*req);
2671 //Notification to clients
2672 CompleteNotifications(req->ClientId(), pR, req->Level(), r, aClientId, EFalse);
2674 pR->iCachedLevel=req->Level();
2675 pR->iLevelOwnerId=req->ClientId();
2676 //Update resource details for Idle
2677 if(pR->iIdleListEntry)
2679 pR->iIdleListEntry->iLevelOwnerId=req->ClientId();
2680 pR->iIdleListEntry->iCurrentLevel=req->Level();
2683 #ifdef PRM_ENABLE_EXTENDED_VERSION
2684 if(aResourceId & KIdMaskDynamic)
2685 ((DDynamicPowerResource*)pR)->UnLock();
2690 //Invoke callback function
2691 aCb->iCallback(req->ClientId(), aResourceId, req->Level(), pR->iLevelOwnerId, r, aCb->iParam);
2692 aCb->iResult = KErrCompletion; //Mark the callback object to act properly during cancellation of this request.
2694 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::ChangeResourceState, Level = %d", req->Level()));
2695 PRM_CLIENT_CHANGE_STATE_END_TRACE
2703 Request the state of the resource synchronously
2705 @param aClientId ID of the client which is requesting the resource state.
2706 @param aResourceId ID of the resource whose state is being requested.
2707 @param aCached If ETrue, cached value will be updated in aState.
2708 If EFalse, aState will be updated after the resource
2709 state is read from resource.
2710 @param aState Returns the resource state if operation was successful. This
2711 could be a binary value for a binary resource, an integer level
2712 for a multilevel resource or some platform specific tolen for a
2713 multi-property resource.
2714 @param aLevelOwnerId Returns the Id of the client that is currently holding the resource.
2715 -1 is returned when no client is holding the resource.
2717 @return KErrNone if operation was successful
2718 KErrAccessDenied if the client ID could not be found in the current list
2719 of registered clients or if the client was registered to be thread
2720 relative and this API is not called from the same thread.
2721 KErrNotFound if this resource ID could not be found in the current list
2722 of controllable resources.
2723 KErrNotReady if the request is issued before the resource controller completes
2724 its internal initialization.
2727 @pre Interrupts must be enabled
2728 @pre Kernel must be unlocked
2729 @pre No fast mutex can be held
2730 @pre Call in a thread context but not from null thread or DFC thread1
2731 @pre Can be used in a device driver
2732 @pre Do not call from DFC thread 0 for long latency resource with caching disabled.
2734 TInt DPowerResourceController::GetResourceState(TUint aClientId, TUint aResourceId, TBool aCached, TInt& aState,
2735 TInt& aLevelOwnerId)
2737 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetResourceState(synchronous)"));
2738 __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d, Cached = %d", aClientId, aResourceId, aCached));
2740 DThread& thread = Kern::CurrentThread();
2741 CHECK_CONTEXT(thread)
2742 if(iInitialised <= EResConCreated)
2743 return KErrNotReady;
2744 SPowerResourceClient* pC = NULL;
2747 VALIDATE_CLIENT(thread);
2749 UNLOCK_RETURN(KErrNotFound);
2750 #ifdef PRM_ENABLE_EXTENDED_VERSION
2751 DStaticPowerResource *pR = NULL;
2752 GET_RESOURCE_FROM_LIST(aResourceId, pR)
2753 if(aResourceId & KIdMaskDynamic)
2755 if(((DDynamicPowerResource*)pR)->LockCount() == 0)
2756 UNLOCK_RETURN(KErrNotFound);
2759 if(aResourceId > iStaticResourceArrayEntries)
2760 UNLOCK_RETURN(KErrNotFound);
2761 DStaticPowerResource *pR = iStaticResourceArray[aResourceId-1];
2763 UNLOCK_RETURN(KErrNotFound);
2765 PRM_RESOURCE_GET_STATE_START_TRACE
2766 //Panic if long latency resource called to execute synchronously from DFC thread0
2767 const TDesC8* pDfc0 = &KDfcThread0Name;
2768 if((!aCached && pR->LatencyGet()) && !(pDfc0->Compare(*(TDesC*)thread.iName)))
2771 Panic(ECalledFromDfcThread0);
2775 //Return the cached value.
2776 aState = pR->iCachedLevel;
2777 aLevelOwnerId = pR->iLevelOwnerId;
2778 PRM_RESOURCE_GET_STATE_END_TRACE
2779 UNLOCK_RETURN(KErrNone);
2781 #ifdef PRM_ENABLE_EXTENDED_VERSION
2782 if(aResourceId & KIdMaskDynamic)
2783 ((DDynamicPowerResource*)pR)->Lock();
2785 //Call from thread Id.
2786 TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
2787 req->ResourceId() = aResourceId;
2788 req->ReqType() = TPowerRequest::EGet;
2789 req->ClientId() = aClientId;
2790 req->Resource() = pR;
2791 req->ResourceCb() = NULL;
2792 if(pR->LatencyGet())
2794 #ifdef PRM_ENABLE_EXTENDED_VERSION
2795 if( req->ResourceId() & KIdMaskResourceWithDependencies ) // Dependency Resource
2798 req->SendReceive(iMsgQDependency); //Send the request to DFC Thread
2801 else // Plain resource
2805 req->SendReceive(iMsgQ);
2812 r = pR->DoRequest(*req); // Call PSL to get the state of resource.
2816 //Update the cache value and cache for idle thread usage if requested for this resource.
2817 pR->iCachedLevel=req->Level();
2818 if(pR->iIdleListEntry)
2820 SIdleResourceInfo* pI=pR->iIdleListEntry;
2821 pI->iCurrentLevel=req->Level();
2825 aState = req->Level();
2826 aLevelOwnerId = pR->iLevelOwnerId;
2827 #ifdef PRM_ENABLE_EXTENDED_VERSION
2828 if(aResourceId & KIdMaskDynamic)
2829 ((DDynamicPowerResource*)pR)->UnLock();
2832 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetResourceState(synchronous), Level = %d", aState));
2833 if(pR->LatencyGet()) //For long latency resource btrace is done in controller thread.
2835 PRM_RESOURCE_GET_STATE_END_TRACE
2843 Request the state of the resource asynchrounously for long latency resource and
2844 synchronously for instantaneous resource
2846 @param aClientId ID of the client which is requesting the resource state.
2847 @param aResourceId ID of the resource whose state is being requested.
2848 @param aCached If ETrue, cached value will be updated in aState
2849 If EFalse, will be updated after the resource state is read from resource
2850 @param aCb For long latency resource:
2851 A pointer to a resource callback object which encapsulates a callback function
2852 to be called whenever the state of the resource is available for the long
2853 latency resource (executes in the context of resource manager)
2854 For instantaneous resource:
2855 A pointer to a resource callback object which encapsulates a callback
2856 function to be called after the resource state is read. This is executed
2857 synchronously in the context of the calling thread.
2858 NOTE: The client must create the callback object in kernel heap or
2861 @return KErrNone if the operation was successful
2862 KErrArgument if callback object is NULL
2863 KErrAccessDenied if the client ID could not be found in the current list
2864 of registered clients or if the client was registered to be thread
2865 relative and this API is not called from the same thread.
2866 KErrNotFound if this resource ID could not be found in the current list
2867 of controllable resources.
2868 KErrNotReady if the request is issued before the resource controller completes
2869 its internal initialisation
2870 KErrUnderflow if the client has exceeded the reserved number of TPowerRequest
2871 and the TPowerRequest free pool is empty for long latency resource.
2872 KErrCorrupt if internal data structure is corrupt.
2874 @pre Interrupts must be enabled
2875 @pre Kernel must be unlocked
2876 @pre No fast mutex can be held
2877 @pre Call in a thread context but not from null thread or DFC thread1
2878 @pre Can be used in a device driver
2880 TInt DPowerResourceController::GetResourceState(TUint aClientId, TUint aResourceId, TBool aCached, TPowerResourceCb& aCb)
2882 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetResourceState(asynchronous)"));
2883 __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d, Cached = %d", aClientId, aResourceId, aCached));
2885 DThread& thread = Kern::CurrentThread();
2886 CHECK_CONTEXT(thread)
2887 if(iInitialised <= EResConCreated)
2888 return KErrNotReady;
2889 SPowerResourceClient* pC = NULL;
2892 VALIDATE_CLIENT(thread);
2894 UNLOCK_RETURN(KErrNotFound);
2895 #ifdef PRM_ENABLE_EXTENDED_VERSION
2896 DStaticPowerResource *pR = NULL;
2897 GET_RESOURCE_FROM_LIST(aResourceId, pR)
2898 if(aResourceId & KIdMaskDynamic)
2900 //Dynamic resource in process of deregistration
2901 if(((DDynamicPowerResource*)pR)->LockCount() == 0)
2902 UNLOCK_RETURN(KErrNotFound);
2905 if(aResourceId > iStaticResourceArrayEntries)
2906 UNLOCK_RETURN(KErrNotFound);
2907 DStaticPowerResource *pR = iStaticResourceArray[aResourceId-1];
2909 UNLOCK_RETURN(KErrNotFound);
2911 aCb.iResult = KErrNone;
2912 aCb.iResourceId = aResourceId;
2913 aCb.iClientId = aClientId;
2915 PRM_RESOURCE_GET_STATE_START_TRACE
2916 if(aCached) //Call the callback directly
2919 aCb.iCallback(aClientId, aResourceId, pR->iCachedLevel, pR->iLevelOwnerId, KErrNone, aCb.iParam);
2920 aCb.iResult = KErrCompletion; //Mark the callback object to act properly during cancellation of this request.
2921 #ifdef PRM_INSTRUMENTATION_MACRO
2922 TInt aState = pR->iCachedLevel;
2923 PRM_RESOURCE_GET_STATE_END_TRACE
2927 TPowerRequest* req=NULL;
2928 if(pR->LatencyGet())
2930 //Check the client quota of requests
2931 if(pC->iReservedRm==0 && !iRequestPoolCount)
2932 UNLOCK_RETURN(KErrUnderflow);
2933 if(pC->iReservedRm ==0)
2935 iRequestPoolCount--;
2936 pC->iUnderFlowRmCount++;
2940 //Get the request from pool
2942 LIST_POP(iRequestPool, pS, iNext);
2944 UNLOCK_RETURN(KErrCorrupt); //This should not be called
2945 req = &pS->iRequest;
2946 //Increment pending request count of the client
2947 pC->iPendingReqCount++;
2950 //Asynchronous instantaneous resource execute in the context of client thread.
2951 req = (TPowerRequest*)&TPowerRequest::Get();
2952 #ifdef PRM_ENABLE_EXTENDED_VERSION
2953 if(aResourceId & KIdMaskDynamic)
2954 ((DDynamicPowerResource*)pR)->Lock();
2957 req->ReqType() = TPowerRequest::EGet;
2958 req->ResourceId() = aResourceId;
2959 req->ClientId() = aClientId;
2960 req->Resource() = pR;
2961 req->ResourceCb() = &aCb;
2962 if(pR->LatencyGet())
2964 #ifdef PRM_ENABLE_EXTENDED_VERSION
2965 if( req->ResourceId() & KIdMaskResourceWithDependencies ) // Dependency Resource
2967 req->Send(iMsgQDependency); // Send the request to DFC thread.
2969 else // Plain resource
2977 r = pR->DoRequest(*req);
2981 //Update the cache value and cache for idle thread usage if requested for this resource.
2982 pR->iCachedLevel = req->Level();
2983 if(pR->iIdleListEntry)
2984 pR->iIdleListEntry->iCurrentLevel=req->Level();
2986 #ifdef PRM_ENABLE_EXTENDED_VERSION
2987 if(aResourceId & KIdMaskDynamic)
2988 ((DDynamicPowerResource*)pR)->UnLock();
2991 // Call the client callback function directly as it is already executing in the context of client thread.
2992 aCb.iCallback(aClientId, aResourceId, req->Level(), pR->iLevelOwnerId, r, aCb.iParam);
2993 aCb.iResult = KErrCompletion; //Mark the callback object to act properly during cancellation of this request.
2995 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetResourceState(asynchronous), Level = %d", req->Level()));
2996 if(pR->LatencyGet())
2998 #ifdef PRM_INSTRUMENTATION_MACRO
2999 TInt aState = req->Level();
3000 PRM_RESOURCE_GET_STATE_END_TRACE
3010 Cancel an asynchronous request(or its callback).
3012 @param aClientId ID of the client which is requesting the cancellation of the request.
3013 @param aResourceId ID for the resource which the request that is being cancelled operates
3015 @param aCb A reference to the resource callback object specified with the request
3016 that is being cancelled.
3018 @return KErrCancel if the request was cancelled.
3019 KErrNotFound if this resource ID could not be found in the current list of controllable
3021 KErrCompletion if request is no longer pending.
3022 KErrAccessDenied if the client ID could not be found in the current list of registered
3023 clients or if the client was registered to be thread relative and this API is not called
3024 from the same thread or if client is not the same that requested the resource state change.
3025 KErrInUse if the request cannot be cancelled as processing of the request already started
3026 and will run to completion.
3028 @pre Interrupts must be enabled
3029 @pre Kernel must be unlocked
3030 @pre No fast mutex can be held
3031 @pre Call in a thread context but not from null thread or DFC thread1
3032 @pre Can be used in a device driver
3034 TInt DPowerResourceController::CancelAsyncRequestCallBack(TUint aClientId, TUint aResourceId, TPowerResourceCb& aCb)
3037 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::CancelAsyncRequestCallBack"));
3038 __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d", aClientId, aResourceId));
3039 DThread& thread = Kern::CurrentThread();
3040 CHECK_CONTEXT(thread)
3041 SPowerResourceClient* pC = NULL;
3043 VALIDATE_CLIENT(thread);
3044 if((!aResourceId) || (aCb.iResourceId != aResourceId))
3045 UNLOCK_RETURN(KErrNotFound);
3046 #ifdef PRM_INSTRUMENTATION_MACRO
3047 #ifdef PRM_ENABLE_EXTENDED_VERSION
3048 DStaticPowerResource *pR = NULL;
3049 GET_RESOURCE_FROM_LIST(aResourceId, pR)
3051 DStaticPowerResource *pR = iStaticResourceArray[aResourceId-1];
3053 UNLOCK_RETURN(KErrNotFound);
3056 if(aCb.iClientId != aClientId)
3058 __KTRACE_OPT(KRESMANAGER, Kern::Printf("aCb.iClientId = 0x%x, aClientId = 0x%x", aCb.iClientId, aClientId));
3059 r = KErrAccessDenied;
3060 #ifdef PRM_INSTRUMENTATION_MACRO
3061 PRM_RESOURCE_CANCEL_LONGLATENCY_OPERATION_TRACE
3065 if(aCb.iResult == KErrCompletion)
3068 #ifdef PRM_INSTRUMENTATION_MACRO
3069 PRM_RESOURCE_CANCEL_LONGLATENCY_OPERATION_TRACE
3073 //Search in the controller message queue for this message
3074 #ifdef PRM_ENABLE_EXTENDED_VERSION
3075 if(aResourceId & KIdMaskResourceWithDependencies) //long latency resource with dependency and will be processed in dependency thread.
3077 //Search in the controller message queue for this message
3078 for(SDblQueLink* pRM = iMsgQDependency->iQ.First(); pRM != &(iMsgQDependency->iQ.iA); pRM = pRM->iNext)
3080 TMessageBase* pMsgQ = (TMessageBase*)pRM;
3081 TPowerRequest* pReq=(TPowerRequest*)pMsgQ;
3082 if(pReq->ResourceCb() == &aCb)
3086 pMsgQ->iState = TMessageBase::EFree; //Reset the state
3087 MoveRequestToFreePool(pReq);
3088 #ifdef PRM_INSTRUMENTATION_MACRO
3089 PRM_RESOURCE_CANCEL_LONGLATENCY_OPERATION_TRACE
3095 else // long latency resource without dependency and will be processed in RC thread.
3098 for(SDblQueLink* pRM = iMsgQ->iQ.First(); pRM != &(iMsgQ->iQ.iA); pRM = pRM->iNext)
3100 TMessageBase* pMsgQ = (TMessageBase*)pRM;
3101 TPowerRequest* pReq=(TPowerRequest*)pMsgQ;
3102 if(pReq->ResourceCb() == &aCb)
3106 pMsgQ->iState = TMessageBase::EFree; //Reset the state
3107 MoveRequestToFreePool(pReq);
3108 #ifdef PRM_INSTRUMENTATION_MACRO
3109 PRM_RESOURCE_CANCEL_LONGLATENCY_OPERATION_TRACE
3115 #ifdef PRM_INSTRUMENTATION_MACRO
3116 PRM_RESOURCE_CANCEL_LONGLATENCY_OPERATION_TRACE
3125 Request notification of changes to the state of a resource.
3127 @param aClientId ID of the client which is requesting the notification.
3128 @param aResourceId ID of the resource for which notification of state changes
3130 @param aN A reference to a notification object which encapsulates a callback
3131 function to be called whenever a resource state change takes place.
3132 NOTE: The client must create the notification object in kernel heap
3135 @return KErrNone if the operation of requesting a notification was successful.
3136 KErrNotFound if this resource ID could not be found in the current list
3137 of controllable resources.
3138 KErrAccessDenied if the client ID could not be found in the current
3139 list of registered clients or if the client was registered to be
3140 thread relative and this API is not called from the same thread.
3141 KErrInUse if the passed notification object is used already.
3142 NOTE: This API should return immediately; however the notification will
3143 only happen when a resource change occurs.Notification request is idempotent,
3144 if the same notification has already been requested for this resource ID,
3145 the API returns with no further action.Notifications remain queued until they are cancelled.
3147 @pre Interrupts must be enabled
3148 @pre Kernel must be unlocked
3149 @pre No fast mutex can be held
3150 @pre Call in a thread context but not from null thread or DFC thread1
3151 @pre Can be used in a device driver
3153 TInt DPowerResourceController::RequestNotification(TUint aClientId, TUint aResourceId, DPowerResourceNotification& aN)
3156 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RequestNotification(unconditional)"));
3157 __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d", aClientId, aResourceId));
3158 DThread& thread = Kern::CurrentThread();
3159 CHECK_CONTEXT(thread)
3160 SPowerResourceClient* pC = NULL;
3162 VALIDATE_CLIENT(thread);
3166 PRM_POSTNOTIFICATION_REGISTER_TRACE
3169 #ifdef PRM_ENABLE_EXTENDED_VERSION
3170 DStaticPowerResource *pR = NULL;
3171 GET_RESOURCE_FROM_LIST(aResourceId, pR)
3173 if(aResourceId > iStaticResourceArrayEntries)
3176 PRM_POSTNOTIFICATION_REGISTER_TRACE
3180 DStaticPowerResource *pR = iStaticResourceArray[aResourceId-1];
3184 PRM_POSTNOTIFICATION_REGISTER_TRACE
3188 if(aN.iRegistered) //Check if the same notification object is used already
3191 PRM_POSTNOTIFICATION_REGISTER_TRACE
3195 aN.iType = DPowerResourceNotification::EUnconditional;
3196 aN.iOwnerId=(TUint16)aClientId;
3197 aN.iCallback.iClientId= aClientId;
3198 aN.iCallback.iResourceId=aResourceId;
3199 //Add to resource notification list
3200 pR->iNotificationList.Add(&(aN.iNotificationLink));
3201 //Add to client notification list
3202 LIST_PUSH(pC->iNotificationList, &aN, iNextInClient);
3203 PRM_POSTNOTIFICATION_REGISTER_TRACE
3204 UNLOCK_RETURN(KErrNone);
3211 Request notification when the state of a resource reaches a specified threshold or
3212 goes above or below that threshold (for multilevel resource only) based on direction.
3213 In other words it is issued when a threshold on the specified resource state is crossed
3214 in the direction specified.
3216 @param aClientId ID of the client which is requesting the notification.
3217 @param aResourceId ID for the resource whose notification of state changes is
3219 @param aN A reference to a notification object which encapsulates a callback
3220 function to be called whenever the conditions to issue the notification
3221 (specified in the API) are met.
3222 NOTE: The client must create the notification object in kernel heap
3224 @param aThreshold The level of the resource state that will trigger the notification
3226 @param aDirection Specifies the direction of change of the resource state that will
3227 trigger a notification. EFalse means the notification will be issued
3228 when the resource state change to a specified threshold value or below
3229 the specified threshold, ETrue means the notification will be issued
3230 when the resource state change to a specified threshold value or above
3231 the specified threshold.
3235 @return KErrNone if the operation of requesting a notification was successful.
3236 KErrNotFound if this resource ID could not be found in the current list
3237 of controllable reosurces.
3238 KErrAccessDenied if the client ID could not be found in the list of
3239 registered clients or if the client was registered to be thread
3240 relative and this API is not called from the same thread.
3241 KErrInUse if the passed notification object is used already.
3242 KErrArgument if the specified threshold is out of range.
3243 NOTE: This API should return immediately; however the notification will only
3244 happen when a resource change occurs. Notification request is idempotent,
3245 if the same notification has already been requested for this resource ID,
3246 the API returns with no further action. Notification remain queued until they are cancelled.
3248 @pre Interrupts must be enabled
3249 @pre Kernel must be unlocked
3250 @pre No fast mutex can be held
3251 @pre Call in a thread context but not from null thread or DFC thread1
3252 @pre Can be used in a device driver
3254 TInt DPowerResourceController::RequestNotification(TUint aClientId, TUint aResourceId, DPowerResourceNotification& aN,
3255 TInt aThreshold, TBool aDirection)
3258 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RequestNotification(conditional)"));
3259 __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d, Threshold = %d, Direction = %d", \
3260 aClientId, aResourceId, aThreshold, aDirection));
3261 DThread& thread = Kern::CurrentThread();
3262 CHECK_CONTEXT(thread)
3264 SPowerResourceClient* pC = NULL;
3265 VALIDATE_CLIENT(thread);
3269 PRM_POSTNOTIFICATION_REGISTER_TRACE
3272 #ifdef PRM_ENABLE_EXTENDED_VERSION
3273 DStaticPowerResource *pR = NULL;
3274 GET_RESOURCE_FROM_LIST(aResourceId, pR)
3276 if(aResourceId > iStaticResourceArrayEntries)
3279 PRM_POSTNOTIFICATION_REGISTER_TRACE
3283 DStaticPowerResource *pR = iStaticResourceArray[aResourceId-1];
3287 PRM_POSTNOTIFICATION_REGISTER_TRACE
3291 if(aN.iRegistered) //Check if the same notification object is used already
3294 PRM_POSTNOTIFICATION_REGISTER_TRACE
3298 //Validate threshold for correctness
3299 TPowerResourceInfoBuf01 buf;
3300 r = pR->GetInfo((TDes8*)buf.Ptr());
3303 PRM_POSTNOTIFICATION_REGISTER_TRACE
3306 TPowerResourceInfoV01 *pBuf = (TPowerResourceInfoV01*)buf.Ptr();
3307 if(((pBuf->iMinLevel > pBuf->iMaxLevel) && ((aThreshold > pBuf->iMinLevel) || (aThreshold < pBuf->iMaxLevel))) ||
3308 ((pBuf->iMaxLevel > pBuf->iMinLevel) && ((aThreshold > pBuf->iMaxLevel) || (aThreshold < pBuf->iMinLevel))))
3311 PRM_POSTNOTIFICATION_REGISTER_TRACE
3315 aN.iType = DPowerResourceNotification::EConditional;
3316 aN.iThreshold = aThreshold;
3317 aN.iDirection = aDirection;
3318 aN.iOwnerId = (TUint16)aClientId;
3319 aN.iCallback.iClientId = aClientId;
3320 aN.iCallback.iResourceId = aResourceId;
3321 //Store the current level of the resource as will be used for issuing notification
3322 aN.iPreviousLevel = pR->iCachedLevel;
3323 //Add to resource notification list
3324 pR->iNotificationList.Add(&(aN.iNotificationLink));
3325 //Add to client notification list
3326 LIST_PUSH(pC->iNotificationList, &aN, iNextInClient);
3327 PRM_POSTNOTIFICATION_REGISTER_TRACE
3328 UNLOCK_RETURN(KErrNone);
3335 Cancel and remove from queue a previously issued request for notification on a
3336 resource state change.
3338 @param aClientId ID of the client which is requesting to cancel the notification
3339 @param aResourceId for the resource whose pending notification of state changes
3341 @param aN A reference to the notification object that was associated with
3342 the notification request that is being cancelled. This will be
3343 used to identify the notification that is being cancelled.
3345 @return KErrCancel if the notification request was successfully cancelled.
3346 KErrNotFound if the specified notification object is
3347 not found in the current list of notification objects for the
3349 KErrAccessDenied if the client requesting the cancellation is not the same
3350 which registered the notification or if the resource id does not match or
3351 if the client ID could not be found in the list of registered clients or
3352 if the client was registered to be thread relative and this API is
3353 not called from the same thread.
3355 @pre Interrupts must be enabled
3356 @pre Kernel must be unlocked
3357 @pre No fast mutex can be held
3358 @pre Call in a thread context but not from null thread or DFC thread1
3359 @pre Can be used in a device driver
3361 TInt DPowerResourceController::CancelNotification(TUint aClientId, TUint aResourceId, DPowerResourceNotification& aN)
3363 TInt r = KErrCancel;
3364 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::CancelNotification"));
3365 __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d", aClientId, aResourceId));
3366 DThread& thread = Kern::CurrentThread();
3367 CHECK_CONTEXT(thread)
3368 SPowerResourceClient* pC = NULL;
3370 VALIDATE_CLIENT(thread);
3375 PRM_POSTNOTIFICATION_DEREGISTER_TRACE
3378 //Remove from the client list
3379 TBool found = EFalse;
3380 DPowerResourceNotification* pCNL = pC->iNotificationList;
3381 DPowerResourceNotification* pCNLNext = pCNL;
3384 if(pCNL->iOwnerId != (TUint16)aClientId)
3386 r = KErrAccessDenied;
3387 PRM_POSTNOTIFICATION_DEREGISTER_TRACE
3398 if(pCNL->iOwnerId != (TUint16)aClientId)
3400 r = KErrAccessDenied;
3401 PRM_POSTNOTIFICATION_DEREGISTER_TRACE
3404 pCNL->iNextInClient = pCNLNext->iNextInClient;
3410 pCNLNext = pCNLNext->iNextInClient;
3416 PRM_POSTNOTIFICATION_DEREGISTER_TRACE
3419 if(pCNL->iCallback.iResourceId != aResourceId)
3421 r = KErrAccessDenied;
3422 PRM_POSTNOTIFICATION_DEREGISTER_TRACE
3425 //Remove from resource list
3426 pCNL->iNotificationLink.Deque();
3427 pCNL->iCallback.Cancel();
3428 //Remove from client list
3429 LIST_REMOVE(pC->iNotificationList, pCNL, iNextInClient, DPowerResourceNotification);
3430 pCNL->iRegistered--;
3431 PRM_POSTNOTIFICATION_DEREGISTER_TRACE
3432 UNLOCK_RETURN(KErrCancel);
3439 Request pre-allocation of specified number of client level and request message objects.
3441 @param aClientId ID of the client which is requesting the pre-allocation.
3442 @param aNumCl Number of client level objects that needs to be pre-allocated
3444 @param aNumRm Number of request message objects that needs to be pre-allocated
3447 @return KErrNone if the allocation was successful
3448 KErrAccessDenied if the client ID could not be found in the list of
3449 registered clients or if the client was registered to be thread
3450 relative and this API is not called from the same thread.
3451 KErrNoMemory if there is no sufficient memory for allocation of requested
3454 @pre Interrupts must be enabled
3455 @pre Kernel must be unlocked
3456 @pre No fast mutex can be held
3457 @pre Call in a thread context but not from null thread or DFC thread1
3458 @pre Can be used in a device driver
3460 TInt DPowerResourceController::AllocReserve(TUint aClientId, TUint8 aNumCl, TUint8 aNumRm)
3462 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::AllocReserve"));
3463 __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, Numclients = %d, NumResource = %d", aClientId, aNumCl, aNumRm));
3464 DThread& thread = Kern::CurrentThread();
3465 CHECK_CONTEXT(thread)
3466 SPowerResourceClient* pC = NULL;
3468 VALIDATE_CLIENT(thread);
3469 //Call from thread Id.
3470 TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
3471 req->ReqType() = TPowerRequest::EAllocReserve;
3472 req->ClientId() = aClientId;
3473 req->RequestCount() = aNumRm;
3474 req->ClientLevelCount() = aNumCl;
3477 req->SendReceive(iMsgQ);
3478 return (req->ReturnCode());
3484 This function runs in the context of the RC thread and
3485 handles creation of memory pools.
3487 TInt DPowerResourceController::HandleReservationOfObjects(TPowerRequest& aRequest)
3489 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::AllocReserve"));
3491 SPowerResourceClientLevel* pCL = NULL;
3492 SPowerRequest* pR = NULL;
3495 TInt clientPoolCount = iClientLevelPoolCount;
3496 TInt requestPoolCount = iRequestPoolCount;
3497 SPowerResourceClient* pC;
3498 if(aRequest.ClientId() & USER_SIDE_CLIENT_BIT_MASK)
3499 pC = iUserSideClientList[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)];
3501 pC = iClientList[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)];
3504 if(clientPoolCount < aRequest.ClientLevelCount())
3506 //Grow the client level pool
3507 // coverity[alloc_fn]
3508 pCL = new SPowerResourceClientLevel[iClientLevelPoolGrowBy + aRequest.ClientLevelCount()];
3510 return(KErrNoMemory);
3512 if(requestPoolCount < aRequest.RequestCount())
3514 //Grow the request pool
3515 // coverity[alloc_fn]
3516 pR = new SPowerRequest[iRequestPoolGrowBy + aRequest.RequestCount()];
3519 if(pCL) //If client level is allocated delete the same.
3521 return(KErrNoMemory);
3524 //Push the memory to list and adjust the counter.
3529 for(count = 0;count<(TUint)(iClientLevelPoolGrowBy+aRequest.ClientLevelCount());count++)
3530 LIST_PUSH(iClientLevelPool, &pCL[count], iNextInList);
3531 iClientLevelPoolCount= (TUint16)(iClientLevelPoolCount + iClientLevelPoolGrowBy);
3532 pC->iReservedCl= (TUint8)(pC->iReservedCl + aRequest.ClientLevelCount());
3536 //Reserve memory from free pool to this client
3537 iClientLevelPoolCount = (TUint16)(iClientLevelPoolCount - aRequest.ClientLevelCount());
3538 pC->iReservedCl = (TUint8)(pC->iReservedCl + aRequest.ClientLevelCount());
3543 for(count=0;count<(TUint)(iRequestPoolGrowBy+aRequest.RequestCount());count++)
3544 LIST_PUSH(iRequestPool, &pR[count], iNext);
3545 iRequestPoolCount = (TUint16)(iRequestPoolCount + iRequestPoolGrowBy);
3546 pC->iReservedRm =(TUint8)(pC->iReservedRm + aRequest.RequestCount());
3550 //Reserve memory from free pool to this client
3551 iRequestPoolCount = (TUint16)(iRequestPoolCount - aRequest.RequestCount());
3552 pC->iReservedRm = (TUint8)(pC->iReservedRm + aRequest.RequestCount());
3555 #ifdef PRM_INSTRUMENTATION_MACRO
3558 size = (iClientLevelPoolGrowBy+aRequest.ClientLevelCount())*sizeof(SPowerResourceClientLevel);
3560 size += (iRequestPoolGrowBy+aRequest.RequestCount())*sizeof(SPowerRequest);
3562 PRM_MEMORY_USAGE_TRACE
3567 /* Register the proxy client to resource controller.
3568 This is called as the result of new user side client opening a channel.*/
3569 TInt DPowerResourceController::RegisterProxyClient(TUint& aClientId, const TDesC8& aName)
3571 GET_CRITICAL_SECTION_COUNT
3572 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterProxyClient"));
3573 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Proxy client name %S", &aName));
3575 DThread& t = Kern::CurrentThread();
3577 //If number of expected user side clients is set to 0 during initial configuration
3578 //then dont allow to configure user side clients.
3579 if(!iUserSideClientList.GrowBy())
3580 return KErrNotSupported;
3581 //Maximum allowable length of a client's name is 32 characters.
3582 if (aName.Length() > KMaxClientNameLength) return KErrTooBig;
3584 SPowerResourceClient *pC = NULL;
3586 #ifdef DEBUG_VERSION
3587 if(!iUserSideClientList.Find(pC, (TDesC8&)aName))
3590 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
3591 return KErrAlreadyExists;
3594 TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
3595 req->ReqType() = TPowerRequest::ERegisterUsersideClient;
3597 req->SendReceive(iMsgQ);
3598 if(req->ReturnCode() == KErrNone)
3600 pC = iUserSideClientList[(TUint16)(req->ClientId() & ID_INDEX_BIT_MASK)];
3602 //Store the current thread Id;
3603 pC->iThreadId = t.iId;
3604 aClientId = pC->iClientId;
3606 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterProxyClient, clientId = 0x%x", aClientId));
3607 PRM_CLIENT_REGISTER_TRACE
3608 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
3612 /* Deregister the specified user side client from resource controller.
3613 This is called as the result of client closing the channel. */
3614 TInt DPowerResourceController::DeregisterProxyClient(TUint aClientId)
3616 GET_CRITICAL_SECTION_COUNT
3617 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::DeregisterProxyClient"));
3618 __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x", aClientId));
3619 DThread& t = Kern::CurrentThread();
3621 //Get the index from client ID
3622 if(!(aClientId & USER_SIDE_CLIENT_BIT_MASK))
3623 return KErrArgument;
3625 SPowerResourceClient* pC = iUserSideClientList[(TUint16)(aClientId & ID_INDEX_BIT_MASK)];
3629 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
3630 return KErrNotFound;
3632 if(pC->iClientId != aClientId)
3634 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client ID does not match"));
3635 UNLOCK_RETURN(KErrNotFound);
3637 if(pC->iClientId & CLIENT_THREAD_RELATIVE_BIT_MASK)
3639 if(pC->iThreadId != t.iId)
3642 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
3643 return KErrAccessDenied;
3646 //Check for any pending request
3647 if(pC->iPendingReqCount)
3650 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
3651 Panic(EClientHasPendingAsyncRequest);
3653 //Check for notification request
3654 if(pC->iNotificationList)
3657 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
3658 Panic(EClientHasNotificationObject);
3660 #ifdef PRM_ENABLE_EXTENDED_VERSION
3661 if(pC->iDynamicResCount)
3664 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
3665 Panic(DPowerResourceController::EClientHasDynamicResourceRegistered);
3668 ResourceStateChangeOfClientLevels(pC);
3669 //Add reserved request to pool
3670 iRequestPoolCount = (TUint16)(iRequestPoolCount + pC->iReservedRm);
3671 PRM_CLIENT_DEREGISTER_TRACE
3672 //Increment the free pool count for client level and request level.
3673 iUserSideClientList.Remove(pC, (TUint16)(pC->iClientId & ID_INDEX_BIT_MASK));
3675 iUserSideClientCount--; //Decrement client count
3676 LIST_PUSH(iClientPool, pC, iNextInList);
3678 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
3682 /* This is called from power controller to cache the state of resource whose
3683 state information it is interested in for accessing from null thread. This
3684 list needs to be accessed from the Idle thread using direct access. */
3685 TInt DPowerResourceController::RegisterResourcesForIdle(TInt aPowerControllerId, TUint aNumResources, TPtr* aBuf)
3687 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterResourceForIdle"));
3688 __KTRACE_OPT(KRESMANAGER, Kern::Printf("PowerControllerId = 0x%x, NumResources = %d", aPowerControllerId, aNumResources));
3689 #ifdef DEBUG_VERSION //Surrounding with macro to avoid warnings.
3690 DThread& t = Kern::CurrentThread();
3694 return KErrArgument;
3695 if((TUint)aPowerControllerId != iPowerControllerId)
3696 return KErrAccessDenied;
3697 if(iListForIdle) //Only one list is allowed.
3699 if((TUint)(aBuf->MaxLength() - aBuf->Length()) < (sizeof(SIdleResourceInfo) * aNumResources))
3700 return KErrArgument;
3701 GET_CRITICAL_SECTION_COUNT
3703 SIdleResourceInfo* pS=(SIdleResourceInfo*)aBuf->Ptr();
3704 DStaticPowerResource* pR=NULL;
3707 for(count=0;count<aNumResources;count++) //Check for valid resource ID.
3709 #ifndef PRM_ENABLE_EXTENDED_VERSION
3710 if((!pS->iResourceId) || (pS->iResourceId > iStaticResourceArrayEntries) || (!iStaticResourceArray[pS->iResourceId-1]))
3713 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
3714 return KErrNotFound;
3717 if(pS->iResourceId & KIdMaskDynamic)
3720 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
3721 return KErrNotSupported;
3723 if((!pS->iResourceId) || ((pS->iResourceId & KIdMaskResourceWithDependencies) &&
3724 (pS->iResourceId > iStaticResDependencyCount)) || (!(pS->iResourceId & KIdMaskResourceWithDependencies) &&
3725 ((pS->iResourceId > iStaticResourceArrayEntries) || (!iStaticResourceArray[pS->iResourceId-1]))))
3728 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
3729 return KErrNotFound;
3734 pS = (SIdleResourceInfo*)aBuf->Ptr();
3735 for(count=0;count<aNumResources;count++)
3738 #ifdef PRM_ENABLE_EXTENDED_VERSION
3739 if(id & KIdMaskResourceWithDependencies) //Dependency resource
3740 pR = iStaticResDependencyArray[(id & ID_INDEX_BIT_MASK)-1];
3743 pR=iStaticResourceArray[id-1];
3744 pS->iLevelOwnerId = pR->iLevelOwnerId;
3745 pS->iCurrentLevel = pR->iCachedLevel;
3746 pR->iIdleListEntry=pS;
3749 iListForIdle=(SIdleResourceInfo*)aBuf->Ptr();
3750 pS = (SIdleResourceInfo*)aBuf->Ptr();
3752 LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
3760 Request to deregister client level from the specified resource for the specified client.
3762 @param aClientId ID of the client which is requesting the deregistration of client level.
3763 @param aResourceId ID of the resource from which to remove the specified client's level.
3765 @return KErrNone if successful
3766 KErrAccessDenied if the client ID could not be found in the list of registered clients or
3767 if the client was registered to be thread relative and this API is not
3768 called from the same thread.
3769 KErrNotFound if the resource ID could not be found in the current list of controllable
3770 resources or if the client is not holding any level with the specified
3771 resource (no client level found for the specified client).
3773 @pre Interrupts must be enabled
3774 @pre Kernel must be unlocked
3775 @pre No fast mutex can be held
3776 @pre Call in a thread context but not from null thread or DFC thread1
3777 @pre Can be used in a device driver.
3779 TInt DPowerResourceController::DeRegisterClientLevelFromResource(TUint aClientId, TUint aResourceId)
3782 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::DeRegisterClientLevelFromResource\n"));
3783 __KTRACE_OPT(KRESMANAGER, Kern::Printf("aClientId = 0x%x, aResourceId = 0x%x\n", aClientId, aResourceId));
3784 DThread& thread = Kern::CurrentThread();
3785 CHECK_CONTEXT(thread)
3786 SPowerResourceClient* pC = NULL;
3788 VALIDATE_CLIENT(thread);
3792 UNLOCK_RETURN(KErrNotFound);
3794 DStaticPowerResource *pR = NULL;
3795 #ifdef PRM_ENABLE_EXTENDED_VERSION
3796 GET_RESOURCE_FROM_LIST(aResourceId, pR)
3797 if(aResourceId & KIdMaskDynamic)
3798 ((DDynamicPowerResource*)pR)->Lock();
3800 if(aResourceId > iStaticResourceArrayEntries)
3802 UNLOCK_RETURN(KErrNotFound);
3804 pR = iStaticResourceArray[aResourceId - 1];
3806 UNLOCK_RETURN(KErrNotFound);
3808 //Need to change the state of the resource if the client is holding the current resource.
3809 if((pR->iLevelOwnerId == (TInt)aClientId) || (pR->Sense() == DStaticPowerResource::ECustom))
3811 //If Longlatency resource then process it in the resource controller thread
3812 TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
3813 req->ResourceId() = aResourceId;
3814 req->ReqType() = TPowerRequest::ESetDefaultLevel;
3815 req->ClientId() = aClientId;
3816 req->Resource() = pR;
3817 req->ResourceCb() = NULL;
3818 #ifdef PRM_INSTRUMENTATION_MACRO
3819 //Setting to current state as exact state will be known only before calling the PSL.
3820 TInt aNewState = pR->iCachedLevel;
3821 PRM_CLIENT_CHANGE_STATE_START_TRACE
3823 if(pR->LatencySet())
3826 #ifdef PRM_ENABLE_EXTENDED_VERSION
3827 if(pR->iResourceId & KIdMaskResourceWithDependencies) //Dependency resource
3829 r = req->SendReceive(iMsgQDependency); // Send the request to DFC thread.
3834 r = req->SendReceive(iMsgQ); //Long latency resource request are processed in controller thread.
3838 else if(pR->Usage())
3841 //Not checking the return value here because there is no allocation of client levels.
3842 CheckLevelAndAddClient(pC, req);
3846 //Single user set it to default
3847 req->ClientId() = -1;
3848 req->ReqType() = TPowerRequest::ESetDefaultLevel;
3850 //Change the state of resource for instantaneous resource.
3851 if((!pR->LatencySet()) && ((!pR->Usage()) || (pR->Usage() && req->RequiresChange())))
3854 r = pR->DoRequest(*req);
3858 //Complete notifications
3859 CompleteNotifications(req->ClientId(), pR, req->Level(), KErrNone, req->ClientId(), EFalse);
3861 pR->iLevelOwnerId = req->ClientId();
3862 pR->iCachedLevel = req->Level();
3863 if(pR->iIdleListEntry)
3865 pR->iIdleListEntry->iLevelOwnerId = req->ClientId();
3866 pR->iIdleListEntry->iCurrentLevel = req->Level();
3870 #ifdef PRM_INSTRUMENTATION_MACRO
3871 if(!pR->LatencySet())
3873 aNewState = req->Level();
3874 PRM_CLIENT_CHANGE_STATE_END_TRACE
3878 //Remove clientLevel from client
3880 for(SPowerResourceClientLevel* pCL = pC->iLevelList; pCL != NULL; pCL= pCL->iNextInList)
3882 if(pCL->iResourceId == aResourceId)
3884 LIST_REMOVE(pC->iLevelList, pCL, iNextInList, SPowerResourceClientLevel);
3885 //Remove from Resource
3887 LIST_PUSH(iClientLevelPool,pCL,iNextInList); // back to free pool
3888 if(pC->iUnderFlowClCount > 0)
3890 pC->iUnderFlowClCount--;
3891 iClientLevelPoolCount++;
3899 #ifdef PRM_ENABLE_EXTENDED_VERSION
3900 if(aResourceId & KIdMaskDynamic)
3901 ((DDynamicPowerResource*)pR)->UnLock();
3910 Interface to provide extended functionality.This provides support
3911 to register and deregister dynamic resources and handling of resource dependency, registering
3912 and deregistering resource dependency.
3913 This is not supported in basic version
3915 @pre Interrupts must be enabled
3916 @pre Kernel must be unlocked
3917 @pre No fast mutex can be held
3918 @pre Call in a thread context but not from null thread or DFC thread1
3919 @pre Can be used in a device driver.
3921 TInt DPowerResourceController::GetInterface(TUint aClientId, TUint aInterfaceId, TAny* aParam1, TAny* aParam2,
3924 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetInterface"));
3925 DThread& thread = Kern::CurrentThread();
3926 CHECK_CONTEXT(thread)
3927 if((iInitialised != EResConStartupCompleted) && (aInterfaceId != KResManControlIoGetVersion))
3928 return KErrNotSupported;
3931 SPowerResourceClient* pC = NULL;
3932 VALIDATE_CLIENT(thread);
3933 #ifndef PRM_ENABLE_EXTENDED_VERSION
3934 if(aInterfaceId == KResManControlIoGetVersion)
3939 *(TUint*)aParam1 = KResControllerBasicVersion;
3942 r = KErrNotSupported;
3946 //User side client is not allowed to register/deregister dynamic resource and dependencies
3947 if((aClientId & USER_SIDE_CLIENT_BIT_MASK) && (aInterfaceId >= KResManControlIoRegisterDynamicResource) &&
3948 (aInterfaceId <= KResManControlIoDeregisterDependency))
3949 return KErrAccessDenied;
3950 switch (aInterfaceId)
3952 case KResManControlIoGetVersion:
3957 *(TUint*)aParam1 = KResControllerExtendedVersion;
3960 case KResManControlIoRegisterDynamicResource:
3962 r = RegisterDynamicResource(pC, (DDynamicPowerResource *)aParam1, (TUint*)aParam2);
3965 case KResManControlIoDeregisterDynamicResource:
3967 r = DeregisterDynamicResource(pC, (TUint)aParam1, (TInt*)aParam2);
3970 case KResManControlIoRegisterDependency:
3973 r = RegisterResourceDependency(pC, (SResourceDependencyInfo*)aParam1, (SResourceDependencyInfo*)aParam2);
3976 case KResManControlIoDeregisterDependency:
3978 r = DeregisterResourceDependency(pC, (TUint)aParam1, (TUint)aParam2);
3979 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetInterface"));
3982 case KResManControlIoGetNumDependents:
3984 r = GetNumDependentsForResource((TUint)aParam1, (TUint*)aParam2);
3987 case KResManControlIoGetDependentsId:
3989 r = GetDependentsIdForResource((TUint)aParam1, (TAny*)aParam2, (TUint*)aParam3);
3994 r = KErrNotSupported;
3999 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetInterface"));