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_extended.cpp
18 #include <drivers/resourcecontrol.h>
20 extern DPowerResourceController* PowerResourceController;
25 Reserves the client level from pool to be used for updating resource client level in dependency resource.
27 @param aCount Number of client levels to reserve from pool
29 @return KErrNone On success
30 @return KErrNoMemory Not enough memory to grow the pool
32 TInt DPowerResourceController::ReserveClientLevelPoolCount(TUint16 aCount)
34 if(aCount < iResourceLevelPoolCount)
35 iResourceLevelPoolCount = (TUint16)(iResourceLevelPoolCount - aCount);
38 TUint allocCount = (iStaticResDependencyCount / 2) + aCount;
40 SPowerResourceClientLevel* pCL = new SPowerResourceClientLevel[allocCount];
43 for(TUint count = 0;count<(TUint)(allocCount);count++)
44 LIST_PUSH(iResourceLevelPool, &pCL[count], iNextInList);
45 iResourceLevelPoolCount= (TUint16)(iResourceLevelPoolCount + (iStaticResDependencyCount / 2));
46 #ifdef PRM_INSTRUMENTATION_MACRO
47 TUint size = allocCount * sizeof(SPowerResourceClientLevel);
48 PRM_MEMORY_USAGE_TRACE
58 Return a client level object from pool.
60 @param aLevelPtr Pointer to update the client level object.
64 void DPowerResourceController::RemoveClientLevelFromPool(SPowerResourceClientLevel *&aLevelPtr)
66 LIST_POP(iResourceLevelPool, aLevelPtr, iNextInList);
71 Update with number of dependent resources for the specified resource.
73 TInt DPowerResourceController::GetNumDependentsForResource(TUint aResourceId, TUint* aNumResources)
75 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetNumDependentsForResource"));
77 if(!(aResourceId & KIdMaskResourceWithDependencies))
78 return KErrNotSupported;
80 if(aResourceId & KIdMaskDynamic)
82 DDynamicPowerResourceD* pDR = iDynamicResDependencyList[(TUint16)(aResourceId & ID_INDEX_BIT_MASK)];
85 pN = pDR->iDependencyList;
89 if((aResourceId & ID_INDEX_BIT_MASK) > iStaticResDependencyCount)
91 DStaticPowerResourceD* pDR = iStaticResDependencyArray[(TUint16)(aResourceId & ID_INDEX_BIT_MASK) - 1];
92 pN = pDR->iDependencyList;
95 for(;pN != NULL; pN = pN->iNext)
97 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetNumDependentsForResource"));
102 Update the specified array with dependent resource Id's of the specified resource.
104 TInt DPowerResourceController::GetDependentsIdForResource(TUint aResourceId, TAny* aInfo, TUint* aNumDepResources)
106 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetDependentsIdForResource"));
108 if(!(aResourceId & KIdMaskResourceWithDependencies))
109 return KErrNotSupported;
111 if(!aInfo || !*aNumDepResources)
116 TDes8 *pInfo = (TDes8*)aInfo;
118 if((TUint)(pInfo->MaxLength() - pInfo->Length()) < (sizeof(SResourceDependencyInfo)*(*aNumDepResources)))
121 SResourceDependencyInfo sResDepInfo;
124 if(aResourceId & KIdMaskDynamic)
126 DDynamicPowerResourceD* pDR = iDynamicResDependencyList[(TUint16)(aResourceId & ID_INDEX_BIT_MASK)];
129 pN = pDR->iDependencyList;
133 if((aResourceId & ID_INDEX_BIT_MASK) > iStaticResDependencyCount)
135 DStaticPowerResourceD* pDR = iStaticResDependencyArray[(TUint16)(aResourceId & ID_INDEX_BIT_MASK) -1];
136 pN = pDR->iDependencyList;
141 for(; pN != NULL; pN = pN->iNext)
144 if(count == *aNumDepResources)
146 sResDepInfo.iResourceId = pN->iResource->iResourceId;
147 sResDepInfo.iDependencyPriority = pN->iPriority;
148 pInfo->Append(TPckgC<SResourceDependencyInfo>(sResDepInfo));
150 *aNumDepResources = resCount;
151 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetDependentsIdForResource"));
156 Registers resource dependency. This could be between 2 dynamic resource or between
157 dynamic and static resource.
159 TInt DPowerResourceController::RegisterResourceDependency(SPowerResourceClient* aClientPtr, SResourceDependencyInfo* aInfo1,
160 SResourceDependencyInfo* aInfo2)
162 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DExtendedResourceController::RegisterResourceDependency"));
163 __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId1 = 0x%x, ResourceId2 = 0x%x",
164 aClientPtr->iClientId, aInfo1->iResourceId, aInfo2->iResourceId));
166 if(iDfcQDependencyLock)
168 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterResourceDependency::Resource In Use"));
173 //One of the resource must be dynamic resource
174 if(!(aInfo1->iResourceId & KIdMaskDynamic) && !(aInfo2->iResourceId & KIdMaskDynamic))
175 return KErrNotSupported;
176 //Both the resources should have dependency resource bit set in its id.
177 if(!(aInfo1->iResourceId & KIdMaskResourceWithDependencies) || !(aInfo2->iResourceId & KIdMaskResourceWithDependencies))
178 return KErrNotSupported;
180 DDynamicPowerResourceD* pR1 = NULL;
181 DDynamicPowerResourceD* pR2 = NULL;
184 //Retrieve resource1 from the corresponding list.
185 if(aInfo1->iResourceId & KIdMaskDynamic)
187 pR1 = iDynamicResDependencyList[(TUint16)(aInfo1->iResourceId & ID_INDEX_BIT_MASK)];
190 pN1 = pR1->iDependencyList;
194 if((aInfo1->iResourceId & ID_INDEX_BIT_MASK) > iStaticResDependencyCount)
196 pR1 = (DDynamicPowerResourceD*)iStaticResDependencyArray[(TUint16)(aInfo1->iResourceId & ID_INDEX_BIT_MASK) - 1];
197 pN1 = ((DStaticPowerResourceD*)pR1)->iDependencyList;
199 //Retrieve resource2 from the corresponding list.
200 if(aInfo2->iResourceId & KIdMaskDynamic)
202 pR2 = iDynamicResDependencyList[(TUint16)(aInfo2->iResourceId & ID_INDEX_BIT_MASK)];
205 pN2 = pR2->iDependencyList;
209 if((aInfo2->iResourceId & ID_INDEX_BIT_MASK) > iStaticResDependencyCount)
211 pR2 = (DDynamicPowerResourceD*)iStaticResDependencyArray[(TUint16)(aInfo2->iResourceId & ID_INDEX_BIT_MASK) - 1];
212 pN2 = ((DStaticPowerResourceD*)pR2)->iDependencyList;
215 //Only long latency resource is allowed to have dependents.
216 if(!pR1->LatencySet())
217 pR1->iFlags |= KLongLatencySet;
218 if(!pR2->LatencySet())
219 pR2->iFlags |= KLongLatencySet;
221 //Check for closed loop
222 //NOTE: Panics, if any closed loop is encountered
224 CheckForDependencyLoop((DStaticPowerResourceD*)pR1, pR1->iResourceId, pR2->iResourceId);
227 CheckForDependencyLoop((DStaticPowerResourceD*)pR2, pR2->iResourceId, pR1->iResourceId);
229 //Check whether the passed priority already exists.Code will return with KErrAlreadyExists, if it exists.
230 CHECK_IF_PRIORITY_ALREADY_EXISTS(pN1, aInfo2->iDependencyPriority)
231 CHECK_IF_PRIORITY_ALREADY_EXISTS(pN2, aInfo1->iDependencyPriority)
234 // coverity[alloc_fn]
235 SNode* pSN1 = new (SNode);
236 // coverity[alloc_fn]
237 SNode* pSN2 = new (SNode);
242 pSN1->iResource = (DStaticPowerResourceD*)pR1;
243 pSN1->iPropagatedLevel = 0;
244 pSN1->iPriority = aInfo1->iDependencyPriority;
245 pSN1->iVisited = EFalse;
248 pSN2->iResource = (DStaticPowerResourceD*)pR2;
249 pSN2->iPropagatedLevel = 0;
250 pSN2->iPriority = aInfo2->iDependencyPriority;
251 pSN2->iVisited = EFalse;
254 if(aInfo1->iResourceId & KIdMaskDynamic) //Dynamic resource
255 // coverity[memory_leak]
256 ADD_DEPENDENCY_NODE(pSN2, ((DDynamicPowerResourceD*)pR1)->iDependencyList)
258 ((DStaticPowerResourceD*)pR1)->AddNode(pSN2);
260 //Add the second node
261 if(aInfo2->iResourceId & KIdMaskDynamic) //Dynamic resource
262 // coverity[memory_leak]
263 ADD_DEPENDENCY_NODE(pSN1, ((DDynamicPowerResourceD*)pR2)->iDependencyList)
265 ((DStaticPowerResourceD*)pR2)->AddNode(pSN1);
266 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DExtendedResourceController::RegisterResourceDependency"));
267 #ifdef PRM_INSTRUMENTATION_MACRO
268 PRM_REGISTER_RESOURCE_DEPENDENCY_TRACE
274 Registers dynamic resource.
276 TInt DPowerResourceController::RegisterDynamicResource(SPowerResourceClient* aClientPtr, DDynamicPowerResource* aPDRes,
277 TUint* aDynamicResourceId)
279 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DExtendedResourceController::RegisterDynamicResource"));
281 //Check for dynamic resource
282 if(!(aPDRes->iResourceId & KIdMaskDynamic))
283 return KErrNotSupported;
285 else if(aPDRes->LockCount() != 0)
286 return KErrAlreadyExists;
288 TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
289 req->ReqType() = TPowerRequest::ERegisterDynamicResource;
290 req->Resource() = (DStaticPowerResource*)aPDRes;
292 req->SendReceive(iMsgQ);
294 if(req->ReturnCode() == KErrNone)
296 *aDynamicResourceId = req->ResourceId();
297 aPDRes-> iOwnerId = aClientPtr->iClientId;
299 //Increment dynamic resource count in client
300 aClientPtr->iDynamicResCount++;
302 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DExtendedResourceController::RegisterDynamicResource, resource ID = 0x%x",
303 *aDynamicResourceId));
304 #ifdef PRM_INSTRUMENTATION_MACRO
305 PRM_REGISTER_DYNAMIC_RESOURCE_TRACE
311 Deregisters dynamic resource.
313 TInt DPowerResourceController::DeregisterDynamicResource(SPowerResourceClient* aClientPtr, TUint aResourceId,
316 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DExtendedResourceController::DeregisterDynamicResource"));
317 __KTRACE_OPT(KRESMANAGER, Kern::Printf("aClientId = 0x%x, aDynamicResourceId = 0x%x, Default Level = %d",
318 aClientPtr->iClientId, aResourceId, aPDefLevel ? *aPDefLevel : 0));
320 DDynamicPowerResource* pDR = NULL;
321 //Check for dynamic resource bit
322 if(!(aResourceId & KIdMaskDynamic))
323 return KErrNotSupported;
325 //Get the resource from appropriate container
326 if(aResourceId & KIdMaskResourceWithDependencies)
328 pDR = iDynamicResDependencyList[(TUint16)(aResourceId & ID_INDEX_BIT_MASK)];
334 pDR = iDynamicResourceList[(TUint16)(aResourceId & ID_INDEX_BIT_MASK)];
338 //Client which registered the dynamic resource is only allowed to deregister.
339 if(aClientPtr->iClientId != pDR->iOwnerId)
341 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client attempting to deregister a dynamic resource which is not the owner!"));
342 return KErrAccessDenied;
344 // Don't allow to deregister if the some other operation is in progress or if the resource is shared and
345 // another client holds requirement on this resource
346 if((pDR->LockCount() > RESOURCE_NOT_IN_OPERATION) || pDR->InUse())
350 TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
351 req->ResourceCb() = NULL;
352 req->ReturnCode() = KErrNone;
353 req->RequiresChange() = EFalse;
354 pDR->UnLock(); //Marked as deleted so that no other operation will be taking place.
355 req->ReqType() = TPowerRequest::ESetDefaultLevel;
356 //Handle dynamic resource with dependencies
357 if(aResourceId & KIdMaskResourceWithDependencies)
359 for(SNode* pNode = ((DDynamicPowerResourceD*)pDR)->iDependencyList; pNode != NULL; pNode = pNode->iNext)
361 if((TUint)pNode->iResource->iLevelOwnerId == aResourceId)
363 req->ResourceId() = pNode->iResource->iResourceId;
364 req->ClientId() = aResourceId;
365 req->Level() = pNode->iResource->iCachedLevel;
366 req->Resource() = pNode->iResource;
367 ((DDynamicPowerResourceD*)(pNode->iResource))->Lock();
369 req->SendReceive(iMsgQDependency);
372 //Remove entry from resource dependency list
373 for(SNode* pSN = pNode->iResource->iDependencyList; pSN != NULL; pSN = pSN->iNext)
375 if(pSN->iResource->iResourceId == aResourceId)
377 LIST_REMOVE(pNode->iResource->iDependencyList, pSN, iNext, SNode);
384 //Remove from dependent resource "resource client level" list
385 for(SPowerResourceClientLevel* pL = ((DDynamicPowerResourceD*)(pNode->iResource))->iResourceClientList;
386 pL != NULL; pL = pL->iNextInList)
388 if(pL->iClientId == aResourceId)
390 LIST_REMOVE(((DDynamicPowerResourceD*)(pNode->iResource))->iResourceClientList, pL, iNextInList,
391 SPowerResourceClientLevel);
393 LIST_PUSH(iResourceLevelPool, pL, iNextInList);
394 iResourceLevelPoolCount++;
397 ((DDynamicPowerResource*)(pNode->iResource))->UnLock();
399 //Move the resource to default level
400 req->ClientId() = -1;
401 req->ResourceId() = aResourceId;
402 req->Resource() = pDR;
404 req->Level() = *aPDefLevel; //Set the resource to the passed level
406 req->Level() = pDR->iDefaultLevel; //Set the resource level to default level
408 req->SendReceive(iMsgQDependency);
413 req->ResourceId() = aResourceId;
414 req->ClientId() = KDynamicResourceDeRegistering;
415 req->Resource() = pDR;
416 req->ResourceCb() = NULL;
418 req->Level() = *aPDefLevel; //Set the resource to the passed level
420 req->Level() = pDR->iDefaultLevel; //Set the resource level to default level
421 if(pDR->LatencySet())
423 r = req->SendReceive(iMsgQ);
427 //Call custom function for custom sense resource
428 if(pDR->Sense() == DStaticPowerResource::ECustom)
430 if(!pDR->iCustomFunction)
431 Panic(ECustomFunctionNotSet);
432 pDR->iCustomFunction(req->ClientId(), *(aClientPtr->iName), aResourceId,
433 EDynamicResourceDeregister, req->Level(),
434 (TAny*)&pDR->iClientList, NULL);
436 //Not checking for error condition as the resource needs to be moved to default state
439 //If the resource change to requested level fails trying to change it to default level.
440 req->ReqType() = TPowerRequest::EChange;
441 r = pDR->DoRequest(*req);
444 req->ReqType() = TPowerRequest::ESetDefaultLevel;
445 req->Level() = pDR->iDefaultLevel;
446 pDR->DoRequest(*req);
450 pDR->DoRequest(*req);
451 //Send notifications. Passing -2 in clientId to indicate that this dynamic resource is deregistering
452 CompleteNotifications(KDynamicResourceDeRegistering, pDR, req->Level(),KErrNone, req->ClientId());
456 //Remove client level
457 SPowerResourceClientLevel *pCL;
458 SPowerResourceClient *pC;
459 for(SDblQueLink* pRC = pDR->iClientList.First(); pRC != &pDR->iClientList.iA; pRC = pRC->iNext)
461 pCL = (SPowerResourceClientLevel*)pRC;
462 if(pCL->iClientId & USER_SIDE_CLIENT_BIT_MASK)
463 pC = iUserSideClientList[(TUint16)(pCL->iClientId & ID_INDEX_BIT_MASK)];
465 pC = iClientList[(TUint16)(pCL->iClientId & ID_INDEX_BIT_MASK)];
466 LIST_REMOVE(pC->iLevelList, pCL, iNextInList, SPowerResourceClientLevel);
467 LIST_PUSH(iClientLevelPool, pCL, iNextInList);
468 if(pC->iUnderFlowClCount > 0)
470 pC->iUnderFlowClCount--;
471 iClientLevelPoolCount++;
476 //Decrement dynamic resource count in client
477 aClientPtr->iDynamicResCount--;
478 if(aResourceId & KIdMaskResourceWithDependencies)
480 iDynamicResDependencyList.Remove((DDynamicPowerResourceD*)pDR, (TUint16)(pDR->iResourceId & ID_INDEX_BIT_MASK));
481 iDynamicResDependencyCount--;
485 iDynamicResourceList.Remove(pDR, (TUint16)(pDR->iResourceId & ID_INDEX_BIT_MASK));
486 iDynamicResourceCount--;
488 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DExtendedResourceController::DeregisterDynamicResource"));
489 #ifdef PRM_INSTRUMENTATION_MACRO
490 TInt level = req->Level();
491 PRM_DEREGISTER_DYNAMIC_RESOURCE_TRACE
499 Default implementation, PSL re-implements this if features supported.
501 TInt DPowerResourceController::DoRegisterStaticResourcesDependency(DStaticPowerResourceD**& aStaticResourceDArray,
502 TUint16& aStaticResourceDCount)
504 __KTRACE_OPT(KRESMANAGER, Kern::Printf("DExtendedResourceController::DoRegisterStaticResourcesDependency default implementation"));
505 aStaticResourceDArray = NULL;
506 aStaticResourceDCount = 0;
511 This function checks for any closed loop dependency, if so panics.
513 void DPowerResourceController::CheckForDependencyLoop(DStaticPowerResourceD* pR, TUint aParentResId, TUint aTargetResId)
517 if(pR->iResourceId & KIdMaskDynamic)
518 pN = ((DDynamicPowerResourceD*)pR)->iDependencyList;
520 pN = pR->iDependencyList;
522 for(; pN != NULL; pN = pN->iNext)
524 if(pN->iResource->iResourceId == aParentResId)
526 if(pN->iVisited || (pN->iResource->iResourceId == aTargetResId))
528 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Loop encountered\n"));
529 DPowerResourceController::Panic(DPowerResourceController::EClosedLoopDependencies);
531 pN->iVisited = ETrue;
532 CheckForDependencyLoop(pN->iResource, pR->iResourceId, aTargetResId);
533 pN->iVisited = EFalse;
538 This is called from the controller thread to handle the dependency resource state change operation.
540 TInt DPowerResourceController::HandleDependencyResourceStateChange(SPowerResourceClient* pC, TPowerRequest& aRequest)
542 DStaticPowerResourceD* pR = (DStaticPowerResourceD*)aRequest.Resource();
543 if(aRequest.ReqType() == TPowerRequest::EChange) //Handle resource change operation
545 if(aRequest.Resource()->Usage()) //Shared resource
548 aRequest.ReturnCode() = CheckLevelAndAddClient(pC, &aRequest);
550 if((aRequest.ReturnCode()!= KErrNone) || (!aRequest.RequiresChange()))
552 aRequest.Level() = pR->iCachedLevel; //If no change then send the current level back.
553 return aRequest.ReturnCode();
556 else if(pR->iClientList.IsEmpty())
559 if(pC->iReservedCl==0 && !iClientLevelPoolCount)
561 __KTRACE_OPT(KRESMANAGER, Kern::Printf("Reserved Client Level exhausted and its free pool empty"));
562 aRequest.ReturnCode() = KErrUnderflow;
563 UNLOCK_RETURN(KErrUnderflow);
565 SPowerResourceClientLevel* pSCL=NULL;
566 LIST_POP(iClientLevelPool, pSCL, iNextInList);
567 pSCL->iClientId=pC->iClientId;
568 pSCL->iResourceId=aRequest.ResourceId();
569 pSCL->iLevel=aRequest.Level();
570 LIST_PUSH(pC->iLevelList, pSCL, iNextInList); //Add to client
571 pR->iClientList.Add(pSCL); //Add in resource
572 if(pC->iReservedCl==0)
574 iClientLevelPoolCount--;
575 pC->iUnderFlowClCount++;
579 if(pR->iCachedLevel == aRequest.Level())
581 pR->iLevelOwnerId = aRequest.ClientId();
582 if(pR->iIdleListEntry)
583 pR->iIdleListEntry->iLevelOwnerId = aRequest.ClientId();
584 aRequest.ReturnCode() = KErrNone;
585 UNLOCK_RETURN(KErrNone);
591 //Update the level in the client list.
592 SPowerResourceClientLevel* pSCL = (SPowerResourceClientLevel*)pR->iClientList.First();
593 pSCL->iLevel = aRequest.Level();
595 //Call appropriate resource's handle change propagation function
596 if(pR->iResourceId & KIdMaskDynamic)
597 aRequest.ReturnCode() = ((DDynamicPowerResourceD*)pR)->HandleChangePropagation(aRequest, EChangeStart, pC->iClientId, *(pC->iName));
599 aRequest.ReturnCode() = pR->HandleChangePropagation(aRequest, EChangeStart,pC->iClientId, *(pC->iName));
600 return aRequest.ReturnCode();
602 if(aRequest.ClientId() == -1) //Special where the resource needs to set to default level, when dynamic resource deregisters
604 //If resource is asked to change to certain value, instead of default then
605 //try to set it to that value. If not able to set then try to set it to default level.
606 if(aRequest.Level() != pR->iDefaultLevel)
607 aRequest.ReqType() = TPowerRequest::EChange;
608 aRequest.ReturnCode() = pR->DoRequest(aRequest);
609 if((aRequest.ReturnCode() != KErrNone) && (aRequest.ReqType() == TPowerRequest::EChange))
611 aRequest.ReqType() = TPowerRequest::ESetDefaultLevel;
612 aRequest.Level() = pR->iDefaultLevel;
613 pR->DoRequest(aRequest);
615 //Set clientId to -2, indicating that the resource is deregistered.
616 CompleteNotifications(KDynamicResourceDeRegistering, pR, aRequest.Level(), KErrNone, aRequest.ClientId());
619 //Handle custom sense resource
620 if(aRequest.Resource()->Sense() == DStaticPowerResource::ECustom)
622 if(pR->iResourceId & KIdMaskDynamic)
624 aRequest.RequiresChange() = ((DDynamicPowerResourceD*)pR)->iDepCustomFunction(aRequest.ClientId(), *(pC->iName), aRequest.ResourceId(),
625 EClientRelinquishLevel, aRequest.Level(), (TAny*)&pR->iClientList,
626 (TAny*)&((DDynamicPowerResourceD*)pR)->iResourceClientList, NULL);
630 aRequest.RequiresChange() = pR->iDepCustomFunction(aRequest.ClientId(), *(pC->iName), aRequest.ResourceId(),
631 EClientRelinquishLevel, aRequest.Level(), (TAny*)&pR->iClientList,
632 (TAny*)&pR->iResourceClientList, NULL);
637 SPowerResourceClientLevel* pL = NULL;
638 SPowerResourceClientLevel* pMCL = NULL;
639 TInt maxLevel = KMinTInt;
640 //Find the maximum level from client
641 for(SDblQueLink* pCL = pR->iClientList.First(); pCL != &pR->iClientList.iA; pCL = pCL->iNext)
643 pL = (SPowerResourceClientLevel*)pCL;
644 if(pL->iClientId == (TUint)aRequest.ClientId())
648 maxLevel = pL->iLevel;
652 if(((pR->Sense() == DStaticPowerResource::ENegative) && (pL->iLevel < maxLevel)) ||
653 ((pR->Sense() == DStaticPowerResource::EPositive) && (pL->iLevel > maxLevel)))
655 maxLevel = pL->iLevel;
659 //Find the maximum level from resource client level
660 if(pR->iResourceId & KIdMaskDynamic)
661 pL = ((DDynamicPowerResourceD*)pR)->iResourceClientList;
663 pL = pR->iResourceClientList;
664 for(; pL != NULL; pL = pL->iNextInList)
666 if(pL->iClientId == (TUint)aRequest.ClientId())
670 maxLevel = pL->iLevel;
674 if(((pR->Sense() == DStaticPowerResource::ENegative) && (pL->iLevel < maxLevel)) ||
675 ((pR->Sense() == DStaticPowerResource::EPositive) && (pL->iLevel > maxLevel)))
677 maxLevel = pL->iLevel;
683 aRequest.ClientId() = -1;
684 aRequest.Level() = pR->iDefaultLevel;
688 aRequest.ClientId() = pMCL->iClientId;
689 aRequest.Level() = maxLevel;
692 if((aRequest.Level() == pR->iCachedLevel) && !aRequest.RequiresChange()) //No need to change the resource just update the owner
694 pR->iLevelOwnerId = aRequest.ClientId();
695 if(pR->iIdleListEntry)
696 pR->iIdleListEntry->iLevelOwnerId = aRequest.ClientId();
697 aRequest.ReturnCode() = KErrNone;
700 aRequest.ReqType() = TPowerRequest::EChange; //Make the change otherwise PSL set to default level
703 if(aRequest.ClientId() == -1)
707 if(aRequest.ClientId() & (1 << RESOURCE_BIT_IN_ID_CHECK))
709 DStaticPowerResourceD* pResource;
710 if(aRequest.ClientId() & KIdMaskDynamic)
711 pResource = (DStaticPowerResourceD*)iDynamicResDependencyList[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)];
713 pResource = iStaticResDependencyArray[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK) - 1];
714 name = pResource->iName;
718 SPowerResourceClient* pClient;
719 if(aRequest.ClientId() & USER_SIDE_CLIENT_BIT_MASK)
720 pClient = iUserSideClientList[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)];
721 else // coverity[returned_null]
722 pClient = iClientList[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)];
723 name = pClient->iName;
727 if(pR->iResourceId & KIdMaskDynamic)
728 aRequest.ReturnCode() = ((DDynamicPowerResourceD*)pR)->HandleChangePropagation(aRequest, EChangeStart, aRequest.ClientId(), *name);
730 aRequest.ReturnCode() = pR->HandleChangePropagation(aRequest, EChangeStart, aRequest.ClientId(), *name);
731 if(aRequest.ReturnCode() == KErrPermissionDenied) //Update the ownerId alone
733 pR->iLevelOwnerId = aRequest.ClientId();
734 if(pR->iIdleListEntry)
735 pR->iIdleListEntry->iLevelOwnerId = aRequest.ClientId();
741 Deregisters resource dependency.
743 TInt DPowerResourceController::DeregisterResourceDependency(SPowerResourceClient* aClientPtr, TUint aResId1, TUint aResId2)
745 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::DeregisterResourceDependency"));
746 __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId1 = 0x%x, ResourceId2 = 0x%x",
747 aClientPtr->iClientId, aResId1, aResId2));
748 if(iDfcQDependencyLock)
750 __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterResourceDependency::Resource In Use"));
751 UNLOCK_RETURN(KErrInUse);
753 DDynamicPowerResourceD *pDR1 = NULL;
754 DDynamicPowerResourceD *pDR2 = NULL;
757 SPowerResourceClientLevel* pCL1 = NULL;
758 SPowerResourceClientLevel* pCL2 = NULL;
759 //Get first resource from list
760 if(!(aResId1 & KIdMaskResourceWithDependencies) || !(aResId2 & KIdMaskResourceWithDependencies))
761 UNLOCK_RETURN(KErrAccessDenied);
763 if(aResId1 & KIdMaskDynamic)
765 pDR1 = iDynamicResDependencyList[(TUint16)(aResId1 & ID_INDEX_BIT_MASK)];
767 UNLOCK_RETURN(KErrNotFound);
768 pN1 = pDR1->iDependencyList;
769 pCL1 = pDR1->iResourceClientList;
773 if((aResId1 & ID_INDEX_BIT_MASK) > iStaticResDependencyCount)
774 UNLOCK_RETURN(KErrNotFound);
775 pDR1 = (DDynamicPowerResourceD*)iStaticResDependencyArray[(aResId1 & ID_INDEX_BIT_MASK) - 1];
776 pN1 = ((DStaticPowerResourceD*)pDR1)->iDependencyList;
777 pCL1 = ((DStaticPowerResourceD*)pDR1)->iResourceClientList;
780 //Get second resource from list
781 if(aResId2 & KIdMaskDynamic)
783 pDR2 = iDynamicResDependencyList[(TUint16)(aResId2 & ID_INDEX_BIT_MASK)];
785 UNLOCK_RETURN(KErrNotFound);
786 pN2 = pDR2->iDependencyList;
787 pCL2 = pDR2->iResourceClientList;
791 if((aResId2 & ID_INDEX_BIT_MASK)> iStaticResDependencyCount)
792 UNLOCK_RETURN(KErrNotFound);
793 pDR2 = (DDynamicPowerResourceD*)iStaticResDependencyArray[(TUint16)(aResId2 & ID_INDEX_BIT_MASK) - 1];
794 pN2 = ((DStaticPowerResourceD*)pDR2)->iDependencyList;
795 pCL2 = ((DStaticPowerResourceD*)pDR2)->iResourceClientList;
798 //Check whether dependency exist between the two
800 for(pN = pN1; pN != NULL; pN = pN->iNext)
802 if(pN->iResource->iResourceId == pDR2->iResourceId)
806 UNLOCK_RETURN(KErrNotFound);
807 pN1 = pN; //Storing for later use.
808 for(pN = pN2; pN != NULL; pN = pN->iNext)
810 if(pN->iResource->iResourceId == pDR1->iResourceId)
815 pN2 = pN; //Storing for later use
816 //Remove the dependency link from both the resource
817 if(aResId1 & KIdMaskDynamic)
819 LIST_REMOVE(pDR1->iDependencyList, pN1, iNext, SNode);
823 LIST_REMOVE(((DStaticPowerResourceD*)pDR1)->iDependencyList, pN1, iNext, SNode);
826 if(aResId2 & KIdMaskDynamic)
828 LIST_REMOVE(pDR2->iDependencyList, pN2, iNext, SNode);
832 LIST_REMOVE(((DStaticPowerResourceD*)pDR2)->iDependencyList, pN2, iNext, SNode);
835 //Remove the resource client level from each resource
836 for(; pCL1 != NULL; pCL1 = pCL1->iNextInList)
838 if(pCL1->iClientId == pDR2->iResourceId)
840 if(aResId1 & KIdMaskDynamic)
842 LIST_REMOVE(pDR1->iResourceClientList, pCL1, iNextInList, SPowerResourceClientLevel);
846 LIST_REMOVE(((DStaticPowerResourceD*)pDR1)->iResourceClientList, pCL1, iNextInList,
847 SPowerResourceClientLevel);
849 LIST_PUSH(iResourceLevelPool, pCL1, iNextInList);
850 iResourceLevelPoolCount++;
854 for(; pCL2 != NULL; pCL2 = pCL2->iNextInList)
856 if(pCL2->iClientId == pDR1->iResourceId)
858 if(aResId2 & KIdMaskDynamic)
860 LIST_REMOVE(pDR2->iResourceClientList, pCL2, iNextInList, SPowerResourceClientLevel);
864 LIST_REMOVE(((DStaticPowerResourceD*)pDR2)->iResourceClientList, pCL2, iNextInList,
865 SPowerResourceClientLevel);
867 LIST_PUSH(iResourceLevelPool, pCL2, iNextInList);
868 iResourceLevelPoolCount++;
873 TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
874 req->ResourceCb() = NULL;
875 req->ReqType() = TPowerRequest::ESetDefaultLevel;
876 req->RequiresChange() = EFalse;
877 req->ReturnCode() = KErrNone;
878 if((TUint)pDR1->iLevelOwnerId == pDR2->iResourceId)
880 //Ask to change to default level. Process this in the RC thread;
881 req->ResourceId() = pDR1->iResourceId;
882 req->ClientId() = pDR2->iResourceId;
883 req->Resource() = pDR1;
884 req->Level() = pDR1->iDefaultLevel;
885 if(aResId1 & KIdMaskDynamic)
888 req->SendReceive(iMsgQDependency);
890 if(aResId1 & KIdMaskDynamic)
893 if((TUint)pDR2->iLevelOwnerId == pDR1->iResourceId)
895 //Ask to change to default level. Process this in the RC thread.
896 req->ResourceId() = pDR2->iResourceId;
897 req->ClientId() = pDR1->iResourceId;
898 req->Resource() = pDR2;
899 req->Level() = pDR2->iDefaultLevel;
900 if(aResId2 & KIdMaskDynamic)
903 req->SendReceive(iMsgQDependency);
905 if(aResId2 & KIdMaskDynamic)
908 __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::DeregisterResourceDependency"));
909 #ifdef PRM_INSTRUMENTATION_MACRO
910 PRM_DEREGISTER_RESOURCE_DEPENDENCY_TRACE
919 This function takes care of resource state change of static dependency resource.
920 This propagates the change to all of its dependents.
921 This function takes Originator name and id as parameter as this needs to be passed for custom sense function.
923 TInt DStaticPowerResourceD::HandleChangePropagation(TPowerRequest aRequest, TPropagation aProp, TUint aOriginatorId, const TDesC8& aOriginatorName)
925 TInt result = KErrNone;
926 result = PowerResourceController->HandleResourceChange(aRequest, aProp, aOriginatorId, aOriginatorName, this);
929 //Function to change the resource state of dependency resource.
930 TInt DPowerResourceController::HandleResourceChange(TPowerRequest &aRequest, TPropagation aProp, TUint aOriginatorId,
931 const TDesC8& aOriginatorName, DStaticPowerResourceD* aResource)
933 static TUint16 clientLevelCount = 0;
934 DStaticPowerResourceD* pDR = (DStaticPowerResourceD*)aRequest.Resource();
935 DStaticPowerResourceD* pDepRes = NULL;
936 SNode* dependencyList = NULL;
937 TPowerRequest depRequest;
938 TInt result = KErrNone;
940 depRequest.ReqType() = TPowerRequest::EChange;
941 depRequest.ResourceCb() = NULL;
942 depRequest.ReturnCode() = KErrNone;
943 depRequest.RequiresChange() = EFalse;
945 if(pDR->iResourceId & KIdMaskDynamic)
946 dependencyList = ((DDynamicPowerResourceD*)pDR)->iDependencyList;
948 dependencyList = pDR->iDependencyList;
953 if(!dependencyList) /*No dependents so change state of the resource*/
955 aRequest.ReturnCode() = pDR->DoRequest(aRequest);
956 if(aRequest.ReturnCode() == KErrNone)
958 aResource->iCachedLevel = aRequest.Level();
959 aResource->iLevelOwnerId = aRequest.ClientId();
960 if(aResource->iIdleListEntry)
962 aResource->iIdleListEntry->iCurrentLevel = aRequest.Level();
963 aResource->iIdleListEntry->iLevelOwnerId = aRequest.ClientId();
965 CompleteNotifications(aRequest.ClientId(), pDR,
966 aRequest.Level(), aRequest.ReturnCode(), aRequest.ClientId());
970 depRequest.ResourceId() = aRequest.ResourceId();
971 depRequest.ClientId() = aRequest.ResourceId();
972 depRequest.Level() = aRequest.Level();
973 depRequest.Resource() = pDR;
974 result = pDR->HandleChangePropagation(depRequest, ECheckChangeAllowed, aOriginatorId, aOriginatorName);
975 if(result != KErrNone)
977 /*Adjust resource client level*/
980 result = ReserveClientLevelPoolCount(clientLevelCount);
981 if(result != KErrNone)
984 /*Resource change of dependents */
985 pDR->HandleChangePropagation(aRequest, ERequestStateChange, aOriginatorId, aOriginatorName);
986 /*Notification to dependents */
987 pDR->HandleChangePropagation(aRequest, EIssueNotifications, aOriginatorId, aOriginatorName);
990 case ECheckChangeAllowed:
992 TChangePropagationStatus status;
993 for(SNode* depNode = dependencyList; depNode != NULL; depNode = depNode->iNext)
995 pDepRes = depNode->iResource;
996 if((aRequest.ClientId() & KIdMaskResourceWithDependencies) &&
997 (pDepRes->iResourceId == (TUint)aRequest.ClientId()))
999 /*Resource need not change if it is already in that state, so continue with
1000 another dependent state.*/
1001 if(pDepRes->iResourceId & KIdMaskDynamic)
1002 status = ((DDynamicPowerResourceD*)pDepRes)->TranslateDependentState(aRequest.ResourceId(),
1003 aRequest.Level(), resState);
1005 status = ((DStaticPowerResourceD*)pDepRes)->TranslateDependentState(aRequest.ResourceId(),
1006 aRequest.Level(), resState);
1007 if((status == ENoChange) || (pDepRes->iCachedLevel == resState))
1009 depNode->iRequiresChange = EFalse;
1012 if(status == EChangeNotAccepted)
1013 return KErrPermissionDenied;
1014 depRequest.ResourceId() = pDepRes->iResourceId;
1015 depRequest.ClientId() = aRequest.ResourceId(); /*ID of the dependent resource */
1016 depRequest.Level() = resState;
1017 depRequest.Resource() = pDepRes;
1018 /*Check resource client list and resource list to see whether change is allowed.*/
1019 if(pDepRes->Sense() == DStaticPowerResource::ECustom)
1021 /*Call custom function to check whether change is allowed.*/
1022 if(pDepRes->iResourceId & KIdMaskDynamic)
1023 depRequest.RequiresChange() = ((DDynamicPowerResourceD*)pDepRes)->iDepCustomFunction(depRequest.ClientId(),
1024 aOriginatorName, depRequest.ResourceId(), EClientRequestLevel, depRequest.Level(), (TAny*)&pDepRes->iClientList,
1025 (TAny*)&((DDynamicPowerResourceD*)pDepRes)->iResourceClientList, NULL);
1027 depRequest.RequiresChange() = ((DStaticPowerResourceD*)pDepRes)->iDepCustomFunction(depRequest.ClientId(),
1028 aOriginatorName, depRequest.ResourceId(), EClientRequestLevel, depRequest.Level(), (TAny*)&pDepRes->iClientList,
1029 (TAny*)&((DStaticPowerResourceD*)pDepRes)->iResourceClientList, NULL);
1030 if(!depRequest.RequiresChange())
1031 return KErrPermissionDenied;
1033 SPowerResourceClientLevel*pN=NULL;
1034 for(SDblQueLink* pNL=pDepRes->iClientList.First();pNL!=&pDepRes->iClientList.iA; pNL=pNL->iNext)
1036 pN = (SPowerResourceClientLevel*)pNL;
1037 if(pDepRes->Sense() == DStaticPowerResource::EPositive)
1039 if(pN->iLevel > depRequest.Level())
1040 return KErrPermissionDenied;
1042 else if(pDepRes->Sense() == DStaticPowerResource::ENegative)
1044 if(pN->iLevel < depRequest.Level())
1045 return KErrPermissionDenied;
1048 /*check through the resource client level */
1049 SPowerResourceClientLevel*pCL = NULL;
1050 if(pDepRes->iResourceId & KIdMaskDynamic)
1051 pCL = ((DDynamicPowerResourceD*)pDepRes)->iResourceClientList;
1053 pCL = ((DStaticPowerResourceD*)pDepRes)->iResourceClientList;
1054 for(; pCL != NULL; pCL = pCL->iNextInList)
1056 if(pCL->iClientId == pDR->iResourceId)
1061 /*check dependent resource client list & resource list to see whether change is allowed */
1062 if(pDepRes->iResourceId & KIdMaskDynamic)
1063 result = ((DDynamicPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest,
1064 ECheckChangeAllowed, aOriginatorId, aOriginatorName);
1066 result = ((DStaticPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest,
1067 ECheckChangeAllowed, aOriginatorId, aOriginatorName);
1068 if(result != KErrNone)
1070 depNode->iPropagatedLevel = resState;
1071 depNode->iRequiresChange = ETrue;
1075 case ERequestStateChange:
1077 SPowerResourceClientLevel* pCL = NULL;
1078 for(SNode* depNode = dependencyList; depNode != NULL; depNode = depNode->iNext)
1080 pDepRes = depNode->iResource;
1081 if((!depNode->iRequiresChange) || (pDepRes->iResourceId == (TUint)aRequest.ClientId()))
1083 depRequest.ResourceId() = pDepRes->iResourceId;
1084 depRequest.ClientId() = aRequest.ResourceId();
1085 depRequest.Level() = depNode->iPropagatedLevel;
1086 depRequest.Resource() = pDepRes;
1087 if(pDepRes->iResourceId & KIdMaskDynamic)
1088 ((DDynamicPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest, ERequestStateChange,
1089 aOriginatorId, aOriginatorName);
1091 ((DStaticPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest, ERequestStateChange,
1092 aOriginatorId, aOriginatorName);
1093 /*Update level if resource client level is already present for this resource.*/
1094 if(pDepRes->iResourceId & KIdMaskDynamic)
1095 pCL = ((DDynamicPowerResourceD*)pDepRes)->iResourceClientList;
1097 pCL = ((DStaticPowerResourceD*)pDepRes)->iResourceClientList;
1098 for(; pCL != NULL; pCL = pCL->iNextInList)
1100 if(pCL->iClientId == pDR->iResourceId)
1102 pCL->iLevel = depNode->iPropagatedLevel;
1106 if(!pCL) /*Create a new resource client level*/
1108 RemoveClientLevelFromPool(pCL);
1109 pCL->iClientId = pDR->iResourceId;
1110 pCL->iResourceId = pDepRes->iResourceId;
1111 pCL->iLevel = depNode->iPropagatedLevel;
1112 if(pDepRes->iResourceId & KIdMaskDynamic)
1114 LIST_PUSH(((DDynamicPowerResourceD*)pDepRes)->iResourceClientList, pCL, iNextInList);
1118 LIST_PUSH(((DStaticPowerResourceD*)pDepRes)->iResourceClientList, pCL, iNextInList);
1123 #ifdef PRM_INSTRUMENTATION_MACRO
1124 if(aRequest.ClientId() & KIdMaskResourceWithDependencies)
1126 SPowerResourceClient res;
1127 SPowerResourceClient* pC = &res;
1128 pC->iClientId = aRequest.ClientId();
1129 pC->iName = &KParentResource;
1130 DStaticPowerResource*pR = (DStaticPowerResource*)pDR;
1131 TUint aResourceId = pDR->iResourceId;
1132 TInt aNewState = aRequest.Level();
1133 PRM_CLIENT_CHANGE_STATE_START_TRACE
1136 aResource->DoRequest(aRequest);
1137 #ifdef PRM_INSTRUMENTATION_MACRO
1138 if(aRequest.ClientId() & KIdMaskResourceWithDependencies)
1140 SPowerResourceClient res;
1141 SPowerResourceClient* pC = &res;
1142 pC->iClientId = aRequest.ClientId();
1143 pC->iName = &KParentResource;
1144 DStaticPowerResource*pR = (DStaticPowerResource*)pDR;
1145 TUint aResourceId = pDR->iResourceId;
1146 TInt aNewState = aRequest.Level();
1148 PRM_CLIENT_CHANGE_STATE_END_TRACE
1151 pDR->iCachedLevel = aRequest.Level();
1152 pDR->iLevelOwnerId = aRequest.ClientId();
1153 if(pDR->iIdleListEntry)
1155 pDR->iIdleListEntry->iCurrentLevel = aRequest.Level();
1156 pDR->iIdleListEntry->iLevelOwnerId = aRequest.ClientId();
1160 case EIssueNotifications:
1162 for(SNode* depNode = dependencyList; depNode != NULL; depNode = depNode->iNext)
1164 pDepRes = depNode->iResource;
1165 if((!depNode->iRequiresChange) || (pDepRes->iResourceId == (TUint)aRequest.ClientId()))
1167 depRequest.ResourceId() = pDepRes->iResourceId;
1168 depRequest.ClientId() = pDepRes->iLevelOwnerId;
1169 depRequest.Level() = pDepRes->iCachedLevel;
1170 depRequest.Resource() = pDepRes;
1171 if(pDepRes->iResourceId & KIdMaskDynamic)
1172 ((DDynamicPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest, EIssueNotifications,
1173 aOriginatorId, aOriginatorName);
1175 ((DStaticPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest, EIssueNotifications,
1176 aOriginatorId, aOriginatorName);
1178 CompleteNotifications(aRequest.ClientId(), pDR, aRequest.Level(), KErrNone,
1179 aRequest.ClientId());
1183 return KErrNotSupported;