sl@0: // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32\drivers\resourceman\resourcecontrol_extended.cpp sl@0: // sl@0: // sl@0: sl@0: #include sl@0: sl@0: extern DPowerResourceController* PowerResourceController; sl@0: /** sl@0: @internalComponent sl@0: @prototype 9.5 sl@0: sl@0: Reserves the client level from pool to be used for updating resource client level in dependency resource. sl@0: sl@0: @param aCount Number of client levels to reserve from pool sl@0: sl@0: @return KErrNone On success sl@0: @return KErrNoMemory Not enough memory to grow the pool sl@0: */ sl@0: TInt DPowerResourceController::ReserveClientLevelPoolCount(TUint16 aCount) sl@0: { sl@0: if(aCount < iResourceLevelPoolCount) sl@0: iResourceLevelPoolCount = (TUint16)(iResourceLevelPoolCount - aCount); sl@0: else sl@0: { sl@0: TUint allocCount = (iStaticResDependencyCount / 2) + aCount; sl@0: // coverity[alloc_fn] sl@0: SPowerResourceClientLevel* pCL = new SPowerResourceClientLevel[allocCount]; sl@0: if(!pCL) sl@0: return KErrNoMemory; sl@0: for(TUint count = 0;count<(TUint)(allocCount);count++) sl@0: LIST_PUSH(iResourceLevelPool, &pCL[count], iNextInList); sl@0: iResourceLevelPoolCount= (TUint16)(iResourceLevelPoolCount + (iStaticResDependencyCount / 2)); sl@0: #ifdef PRM_INSTRUMENTATION_MACRO sl@0: TUint size = allocCount * sizeof(SPowerResourceClientLevel); sl@0: PRM_MEMORY_USAGE_TRACE sl@0: #endif sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: /** sl@0: @internalComponent sl@0: @prototype 9.5 sl@0: sl@0: Return a client level object from pool. sl@0: sl@0: @param aLevelPtr Pointer to update the client level object. sl@0: sl@0: @return None sl@0: */ sl@0: void DPowerResourceController::RemoveClientLevelFromPool(SPowerResourceClientLevel *&aLevelPtr) sl@0: { sl@0: LIST_POP(iResourceLevelPool, aLevelPtr, iNextInList); sl@0: return; sl@0: } sl@0: sl@0: /** sl@0: Update with number of dependent resources for the specified resource. sl@0: */ sl@0: TInt DPowerResourceController::GetNumDependentsForResource(TUint aResourceId, TUint* aNumResources) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetNumDependentsForResource")); sl@0: sl@0: if(!(aResourceId & KIdMaskResourceWithDependencies)) sl@0: return KErrNotSupported; sl@0: SNode* pN; sl@0: if(aResourceId & KIdMaskDynamic) sl@0: { sl@0: DDynamicPowerResourceD* pDR = iDynamicResDependencyList[(TUint16)(aResourceId & ID_INDEX_BIT_MASK)]; sl@0: if(!pDR) sl@0: return KErrNotFound; sl@0: pN = pDR->iDependencyList; sl@0: } sl@0: else sl@0: { sl@0: if((aResourceId & ID_INDEX_BIT_MASK) > iStaticResDependencyCount) sl@0: return KErrNotFound; sl@0: DStaticPowerResourceD* pDR = iStaticResDependencyArray[(TUint16)(aResourceId & ID_INDEX_BIT_MASK) - 1]; sl@0: pN = pDR->iDependencyList; sl@0: } sl@0: *aNumResources = 0; sl@0: for(;pN != NULL; pN = pN->iNext) sl@0: (*aNumResources)++; sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::GetDependentsIdForResource")); sl@0: sl@0: if(!(aResourceId & KIdMaskResourceWithDependencies)) sl@0: return KErrNotSupported; sl@0: sl@0: if(!aInfo || !*aNumDepResources) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: sl@0: TDes8 *pInfo = (TDes8*)aInfo; sl@0: sl@0: if((TUint)(pInfo->MaxLength() - pInfo->Length()) < (sizeof(SResourceDependencyInfo)*(*aNumDepResources))) sl@0: return KErrArgument; sl@0: sl@0: SResourceDependencyInfo sResDepInfo; sl@0: sl@0: SNode* pN; sl@0: if(aResourceId & KIdMaskDynamic) sl@0: { sl@0: DDynamicPowerResourceD* pDR = iDynamicResDependencyList[(TUint16)(aResourceId & ID_INDEX_BIT_MASK)]; sl@0: if(!pDR) sl@0: return KErrNotFound; sl@0: pN = pDR->iDependencyList; sl@0: } sl@0: else sl@0: { sl@0: if((aResourceId & ID_INDEX_BIT_MASK) > iStaticResDependencyCount) sl@0: return KErrNotFound; sl@0: DStaticPowerResourceD* pDR = iStaticResDependencyArray[(TUint16)(aResourceId & ID_INDEX_BIT_MASK) -1]; sl@0: pN = pDR->iDependencyList; sl@0: } sl@0: TUint count = 0; sl@0: TUint resCount = 0; sl@0: sl@0: for(; pN != NULL; pN = pN->iNext) sl@0: { sl@0: resCount++; sl@0: if(count == *aNumDepResources) sl@0: continue; sl@0: sResDepInfo.iResourceId = pN->iResource->iResourceId; sl@0: sResDepInfo.iDependencyPriority = pN->iPriority; sl@0: pInfo->Append(TPckgC(sResDepInfo)); sl@0: } sl@0: *aNumDepResources = resCount; sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DExtendedResourceController::RegisterResourceDependency")); sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId1 = 0x%x, ResourceId2 = 0x%x", sl@0: aClientPtr->iClientId, aInfo1->iResourceId, aInfo2->iResourceId)); sl@0: sl@0: if(iDfcQDependencyLock) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterResourceDependency::Resource In Use")); sl@0: return KErrInUse; sl@0: } sl@0: sl@0: TInt r = KErrNone; sl@0: //One of the resource must be dynamic resource sl@0: if(!(aInfo1->iResourceId & KIdMaskDynamic) && !(aInfo2->iResourceId & KIdMaskDynamic)) sl@0: return KErrNotSupported; sl@0: //Both the resources should have dependency resource bit set in its id. sl@0: if(!(aInfo1->iResourceId & KIdMaskResourceWithDependencies) || !(aInfo2->iResourceId & KIdMaskResourceWithDependencies)) sl@0: return KErrNotSupported; sl@0: sl@0: DDynamicPowerResourceD* pR1 = NULL; sl@0: DDynamicPowerResourceD* pR2 = NULL; sl@0: SNode* pN1 = NULL; sl@0: SNode* pN2 = NULL; sl@0: //Retrieve resource1 from the corresponding list. sl@0: if(aInfo1->iResourceId & KIdMaskDynamic) sl@0: { sl@0: pR1 = iDynamicResDependencyList[(TUint16)(aInfo1->iResourceId & ID_INDEX_BIT_MASK)]; sl@0: if(!pR1) sl@0: return KErrNotFound; sl@0: pN1 = pR1->iDependencyList; sl@0: } sl@0: else sl@0: { sl@0: if((aInfo1->iResourceId & ID_INDEX_BIT_MASK) > iStaticResDependencyCount) sl@0: return KErrNotFound; sl@0: pR1 = (DDynamicPowerResourceD*)iStaticResDependencyArray[(TUint16)(aInfo1->iResourceId & ID_INDEX_BIT_MASK) - 1]; sl@0: pN1 = ((DStaticPowerResourceD*)pR1)->iDependencyList; sl@0: } sl@0: //Retrieve resource2 from the corresponding list. sl@0: if(aInfo2->iResourceId & KIdMaskDynamic) sl@0: { sl@0: pR2 = iDynamicResDependencyList[(TUint16)(aInfo2->iResourceId & ID_INDEX_BIT_MASK)]; sl@0: if(!pR2) sl@0: return KErrNotFound; sl@0: pN2 = pR2->iDependencyList; sl@0: } sl@0: else sl@0: { sl@0: if((aInfo2->iResourceId & ID_INDEX_BIT_MASK) > iStaticResDependencyCount) sl@0: return KErrNotFound; sl@0: pR2 = (DDynamicPowerResourceD*)iStaticResDependencyArray[(TUint16)(aInfo2->iResourceId & ID_INDEX_BIT_MASK) - 1]; sl@0: pN2 = ((DStaticPowerResourceD*)pR2)->iDependencyList; sl@0: } sl@0: sl@0: //Only long latency resource is allowed to have dependents. sl@0: if(!pR1->LatencySet()) sl@0: pR1->iFlags |= KLongLatencySet; sl@0: if(!pR2->LatencySet()) sl@0: pR2->iFlags |= KLongLatencySet; sl@0: sl@0: //Check for closed loop sl@0: //NOTE: Panics, if any closed loop is encountered sl@0: if(pN1) sl@0: CheckForDependencyLoop((DStaticPowerResourceD*)pR1, pR1->iResourceId, pR2->iResourceId); sl@0: sl@0: if(pN2) sl@0: CheckForDependencyLoop((DStaticPowerResourceD*)pR2, pR2->iResourceId, pR1->iResourceId); sl@0: sl@0: //Check whether the passed priority already exists.Code will return with KErrAlreadyExists, if it exists. sl@0: CHECK_IF_PRIORITY_ALREADY_EXISTS(pN1, aInfo2->iDependencyPriority) sl@0: CHECK_IF_PRIORITY_ALREADY_EXISTS(pN2, aInfo1->iDependencyPriority) sl@0: UnLock(); sl@0: //Allocate nodes sl@0: // coverity[alloc_fn] sl@0: SNode* pSN1 = new (SNode); sl@0: // coverity[alloc_fn] sl@0: SNode* pSN2 = new (SNode); sl@0: Lock(); sl@0: if(!pSN1 || !pSN2) sl@0: return KErrNoMemory; sl@0: //Add the link sl@0: pSN1->iResource = (DStaticPowerResourceD*)pR1; sl@0: pSN1->iPropagatedLevel = 0; sl@0: pSN1->iPriority = aInfo1->iDependencyPriority; sl@0: pSN1->iVisited = EFalse; sl@0: pSN1->iNext = NULL; sl@0: sl@0: pSN2->iResource = (DStaticPowerResourceD*)pR2; sl@0: pSN2->iPropagatedLevel = 0; sl@0: pSN2->iPriority = aInfo2->iDependencyPriority; sl@0: pSN2->iVisited = EFalse; sl@0: pSN2->iNext = NULL; sl@0: sl@0: if(aInfo1->iResourceId & KIdMaskDynamic) //Dynamic resource sl@0: // coverity[memory_leak] sl@0: ADD_DEPENDENCY_NODE(pSN2, ((DDynamicPowerResourceD*)pR1)->iDependencyList) sl@0: else sl@0: ((DStaticPowerResourceD*)pR1)->AddNode(pSN2); sl@0: sl@0: //Add the second node sl@0: if(aInfo2->iResourceId & KIdMaskDynamic) //Dynamic resource sl@0: // coverity[memory_leak] sl@0: ADD_DEPENDENCY_NODE(pSN1, ((DDynamicPowerResourceD*)pR2)->iDependencyList) sl@0: else sl@0: ((DStaticPowerResourceD*)pR2)->AddNode(pSN1); sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DExtendedResourceController::RegisterDynamicResource")); sl@0: TInt r = KErrNone; sl@0: //Check for dynamic resource sl@0: if(!(aPDRes->iResourceId & KIdMaskDynamic)) sl@0: return KErrNotSupported; sl@0: //check for count sl@0: else if(aPDRes->LockCount() != 0) sl@0: return KErrAlreadyExists; sl@0: sl@0: TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get(); sl@0: req->ReqType() = TPowerRequest::ERegisterDynamicResource; sl@0: req->Resource() = (DStaticPowerResource*)aPDRes; sl@0: UnLock(); sl@0: req->SendReceive(iMsgQ); sl@0: Lock(); sl@0: if(req->ReturnCode() == KErrNone) sl@0: { sl@0: *aDynamicResourceId = req->ResourceId(); sl@0: aPDRes-> iOwnerId = aClientPtr->iClientId; sl@0: aPDRes->Lock(); sl@0: //Increment dynamic resource count in client sl@0: aClientPtr->iDynamicResCount++; sl@0: } sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DExtendedResourceController::DeregisterDynamicResource")); sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("aClientId = 0x%x, aDynamicResourceId = 0x%x, Default Level = %d", sl@0: aClientPtr->iClientId, aResourceId, aPDefLevel ? *aPDefLevel : 0)); sl@0: TInt r = KErrNone; sl@0: DDynamicPowerResource* pDR = NULL; sl@0: //Check for dynamic resource bit sl@0: if(!(aResourceId & KIdMaskDynamic)) sl@0: return KErrNotSupported; sl@0: sl@0: //Get the resource from appropriate container sl@0: if(aResourceId & KIdMaskResourceWithDependencies) sl@0: { sl@0: pDR = iDynamicResDependencyList[(TUint16)(aResourceId & ID_INDEX_BIT_MASK)]; sl@0: if(!pDR) sl@0: return KErrNotFound; sl@0: } sl@0: else sl@0: { sl@0: pDR = iDynamicResourceList[(TUint16)(aResourceId & ID_INDEX_BIT_MASK)]; sl@0: if(!pDR) sl@0: return KErrNotFound; sl@0: } sl@0: //Client which registered the dynamic resource is only allowed to deregister. sl@0: if(aClientPtr->iClientId != pDR->iOwnerId) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client attempting to deregister a dynamic resource which is not the owner!")); sl@0: return KErrAccessDenied; sl@0: } sl@0: // Don't allow to deregister if the some other operation is in progress or if the resource is shared and sl@0: // another client holds requirement on this resource sl@0: if((pDR->LockCount() > RESOURCE_NOT_IN_OPERATION) || pDR->InUse()) sl@0: { sl@0: return KErrInUse; sl@0: } sl@0: TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get(); sl@0: req->ResourceCb() = NULL; sl@0: req->ReturnCode() = KErrNone; sl@0: req->RequiresChange() = EFalse; sl@0: pDR->UnLock(); //Marked as deleted so that no other operation will be taking place. sl@0: req->ReqType() = TPowerRequest::ESetDefaultLevel; sl@0: //Handle dynamic resource with dependencies sl@0: if(aResourceId & KIdMaskResourceWithDependencies) sl@0: { sl@0: for(SNode* pNode = ((DDynamicPowerResourceD*)pDR)->iDependencyList; pNode != NULL; pNode = pNode->iNext) sl@0: { sl@0: if((TUint)pNode->iResource->iLevelOwnerId == aResourceId) sl@0: { sl@0: req->ResourceId() = pNode->iResource->iResourceId; sl@0: req->ClientId() = aResourceId; sl@0: req->Level() = pNode->iResource->iCachedLevel; sl@0: req->Resource() = pNode->iResource; sl@0: ((DDynamicPowerResourceD*)(pNode->iResource))->Lock(); sl@0: UnLock(); sl@0: req->SendReceive(iMsgQDependency); sl@0: Lock(); sl@0: } sl@0: //Remove entry from resource dependency list sl@0: for(SNode* pSN = pNode->iResource->iDependencyList; pSN != NULL; pSN = pSN->iNext) sl@0: { sl@0: if(pSN->iResource->iResourceId == aResourceId) sl@0: { sl@0: LIST_REMOVE(pNode->iResource->iDependencyList, pSN, iNext, SNode); sl@0: UnLock(); sl@0: delete pSN; sl@0: Lock(); sl@0: break; sl@0: } sl@0: } sl@0: //Remove from dependent resource "resource client level" list sl@0: for(SPowerResourceClientLevel* pL = ((DDynamicPowerResourceD*)(pNode->iResource))->iResourceClientList; sl@0: pL != NULL; pL = pL->iNextInList) sl@0: { sl@0: if(pL->iClientId == aResourceId) sl@0: { sl@0: LIST_REMOVE(((DDynamicPowerResourceD*)(pNode->iResource))->iResourceClientList, pL, iNextInList, sl@0: SPowerResourceClientLevel); sl@0: //Move to free pool sl@0: LIST_PUSH(iResourceLevelPool, pL, iNextInList); sl@0: iResourceLevelPoolCount++; sl@0: } sl@0: } sl@0: ((DDynamicPowerResource*)(pNode->iResource))->UnLock(); sl@0: } sl@0: //Move the resource to default level sl@0: req->ClientId() = -1; sl@0: req->ResourceId() = aResourceId; sl@0: req->Resource() = pDR; sl@0: if(aPDefLevel) sl@0: req->Level() = *aPDefLevel; //Set the resource to the passed level sl@0: else sl@0: req->Level() = pDR->iDefaultLevel; //Set the resource level to default level sl@0: UnLock(); sl@0: req->SendReceive(iMsgQDependency); sl@0: } sl@0: else sl@0: { sl@0: UnLock(); sl@0: req->ResourceId() = aResourceId; sl@0: req->ClientId() = KDynamicResourceDeRegistering; sl@0: req->Resource() = pDR; sl@0: req->ResourceCb() = NULL; sl@0: if(aPDefLevel) sl@0: req->Level() = *aPDefLevel; //Set the resource to the passed level sl@0: else sl@0: req->Level() = pDR->iDefaultLevel; //Set the resource level to default level sl@0: if(pDR->LatencySet()) sl@0: { sl@0: r = req->SendReceive(iMsgQ); sl@0: } sl@0: else sl@0: { sl@0: //Call custom function for custom sense resource sl@0: if(pDR->Sense() == DStaticPowerResource::ECustom) sl@0: { sl@0: if(!pDR->iCustomFunction) sl@0: Panic(ECustomFunctionNotSet); sl@0: pDR->iCustomFunction(req->ClientId(), *(aClientPtr->iName), aResourceId, sl@0: EDynamicResourceDeregister, req->Level(), sl@0: (TAny*)&pDR->iClientList, NULL); sl@0: } sl@0: //Not checking for error condition as the resource needs to be moved to default state sl@0: if(aPDefLevel) sl@0: { sl@0: //If the resource change to requested level fails trying to change it to default level. sl@0: req->ReqType() = TPowerRequest::EChange; sl@0: r = pDR->DoRequest(*req); sl@0: if(r != KErrNone) sl@0: { sl@0: req->ReqType() = TPowerRequest::ESetDefaultLevel; sl@0: req->Level() = pDR->iDefaultLevel; sl@0: pDR->DoRequest(*req); sl@0: } sl@0: } sl@0: else sl@0: pDR->DoRequest(*req); sl@0: //Send notifications. Passing -2 in clientId to indicate that this dynamic resource is deregistering sl@0: CompleteNotifications(KDynamicResourceDeRegistering, pDR, req->Level(),KErrNone, req->ClientId()); sl@0: } sl@0: } sl@0: Lock(); sl@0: //Remove client level sl@0: SPowerResourceClientLevel *pCL; sl@0: SPowerResourceClient *pC; sl@0: for(SDblQueLink* pRC = pDR->iClientList.First(); pRC != &pDR->iClientList.iA; pRC = pRC->iNext) sl@0: { sl@0: pCL = (SPowerResourceClientLevel*)pRC; sl@0: if(pCL->iClientId & USER_SIDE_CLIENT_BIT_MASK) sl@0: pC = iUserSideClientList[(TUint16)(pCL->iClientId & ID_INDEX_BIT_MASK)]; sl@0: else sl@0: pC = iClientList[(TUint16)(pCL->iClientId & ID_INDEX_BIT_MASK)]; sl@0: LIST_REMOVE(pC->iLevelList, pCL, iNextInList, SPowerResourceClientLevel); sl@0: LIST_PUSH(iClientLevelPool, pCL, iNextInList); sl@0: if(pC->iUnderFlowClCount > 0) sl@0: { sl@0: pC->iUnderFlowClCount--; sl@0: iClientLevelPoolCount++; sl@0: } sl@0: else sl@0: pC->iReservedCl++; sl@0: } sl@0: //Decrement dynamic resource count in client sl@0: aClientPtr->iDynamicResCount--; sl@0: if(aResourceId & KIdMaskResourceWithDependencies) sl@0: { sl@0: iDynamicResDependencyList.Remove((DDynamicPowerResourceD*)pDR, (TUint16)(pDR->iResourceId & ID_INDEX_BIT_MASK)); sl@0: iDynamicResDependencyCount--; sl@0: } sl@0: else sl@0: { sl@0: iDynamicResourceList.Remove(pDR, (TUint16)(pDR->iResourceId & ID_INDEX_BIT_MASK)); sl@0: iDynamicResourceCount--; sl@0: } sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("Level(); sl@0: PRM_DEREGISTER_DYNAMIC_RESOURCE_TRACE sl@0: #endif sl@0: return r; sl@0: } sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype 9.6 sl@0: Default implementation, PSL re-implements this if features supported. sl@0: */ sl@0: TInt DPowerResourceController::DoRegisterStaticResourcesDependency(DStaticPowerResourceD**& aStaticResourceDArray, sl@0: TUint16& aStaticResourceDCount) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DExtendedResourceController::DoRegisterStaticResourcesDependency default implementation")); sl@0: aStaticResourceDArray = NULL; sl@0: aStaticResourceDCount = 0; sl@0: return KErrNone; sl@0: } sl@0: sl@0: /** sl@0: This function checks for any closed loop dependency, if so panics. sl@0: */ sl@0: void DPowerResourceController::CheckForDependencyLoop(DStaticPowerResourceD* pR, TUint aParentResId, TUint aTargetResId) sl@0: { sl@0: SNode *pN; sl@0: sl@0: if(pR->iResourceId & KIdMaskDynamic) sl@0: pN = ((DDynamicPowerResourceD*)pR)->iDependencyList; sl@0: else sl@0: pN = pR->iDependencyList; sl@0: sl@0: for(; pN != NULL; pN = pN->iNext) sl@0: { sl@0: if(pN->iResource->iResourceId == aParentResId) sl@0: continue; sl@0: if(pN->iVisited || (pN->iResource->iResourceId == aTargetResId)) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("Loop encountered\n")); sl@0: DPowerResourceController::Panic(DPowerResourceController::EClosedLoopDependencies); sl@0: } sl@0: pN->iVisited = ETrue; sl@0: CheckForDependencyLoop(pN->iResource, pR->iResourceId, aTargetResId); sl@0: pN->iVisited = EFalse; sl@0: } sl@0: } sl@0: sl@0: /** sl@0: This is called from the controller thread to handle the dependency resource state change operation. sl@0: */ sl@0: TInt DPowerResourceController::HandleDependencyResourceStateChange(SPowerResourceClient* pC, TPowerRequest& aRequest) sl@0: { sl@0: DStaticPowerResourceD* pR = (DStaticPowerResourceD*)aRequest.Resource(); sl@0: if(aRequest.ReqType() == TPowerRequest::EChange) //Handle resource change operation sl@0: { sl@0: if(aRequest.Resource()->Usage()) //Shared resource sl@0: { sl@0: Lock(); sl@0: aRequest.ReturnCode() = CheckLevelAndAddClient(pC, &aRequest); sl@0: UnLock(); sl@0: if((aRequest.ReturnCode()!= KErrNone) || (!aRequest.RequiresChange())) sl@0: { sl@0: aRequest.Level() = pR->iCachedLevel; //If no change then send the current level back. sl@0: return aRequest.ReturnCode(); sl@0: } sl@0: } sl@0: else if(pR->iClientList.IsEmpty()) sl@0: { sl@0: Lock(); sl@0: if(pC->iReservedCl==0 && !iClientLevelPoolCount) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("Reserved Client Level exhausted and its free pool empty")); sl@0: aRequest.ReturnCode() = KErrUnderflow; sl@0: UNLOCK_RETURN(KErrUnderflow); sl@0: } sl@0: SPowerResourceClientLevel* pSCL=NULL; sl@0: LIST_POP(iClientLevelPool, pSCL, iNextInList); sl@0: pSCL->iClientId=pC->iClientId; sl@0: pSCL->iResourceId=aRequest.ResourceId(); sl@0: pSCL->iLevel=aRequest.Level(); sl@0: LIST_PUSH(pC->iLevelList, pSCL, iNextInList); //Add to client sl@0: pR->iClientList.Add(pSCL); //Add in resource sl@0: if(pC->iReservedCl==0) sl@0: { sl@0: iClientLevelPoolCount--; sl@0: pC->iUnderFlowClCount++; sl@0: } sl@0: else sl@0: pC->iReservedCl--; sl@0: if(pR->iCachedLevel == aRequest.Level()) sl@0: { sl@0: pR->iLevelOwnerId = aRequest.ClientId(); sl@0: if(pR->iIdleListEntry) sl@0: pR->iIdleListEntry->iLevelOwnerId = aRequest.ClientId(); sl@0: aRequest.ReturnCode() = KErrNone; sl@0: UNLOCK_RETURN(KErrNone); sl@0: } sl@0: UnLock(); sl@0: } sl@0: else sl@0: { sl@0: //Update the level in the client list. sl@0: SPowerResourceClientLevel* pSCL = (SPowerResourceClientLevel*)pR->iClientList.First(); sl@0: pSCL->iLevel = aRequest.Level(); sl@0: } sl@0: //Call appropriate resource's handle change propagation function sl@0: if(pR->iResourceId & KIdMaskDynamic) sl@0: aRequest.ReturnCode() = ((DDynamicPowerResourceD*)pR)->HandleChangePropagation(aRequest, EChangeStart, pC->iClientId, *(pC->iName)); sl@0: else sl@0: aRequest.ReturnCode() = pR->HandleChangePropagation(aRequest, EChangeStart,pC->iClientId, *(pC->iName)); sl@0: return aRequest.ReturnCode(); sl@0: } sl@0: if(aRequest.ClientId() == -1) //Special where the resource needs to set to default level, when dynamic resource deregisters sl@0: { sl@0: //If resource is asked to change to certain value, instead of default then sl@0: //try to set it to that value. If not able to set then try to set it to default level. sl@0: if(aRequest.Level() != pR->iDefaultLevel) sl@0: aRequest.ReqType() = TPowerRequest::EChange; sl@0: aRequest.ReturnCode() = pR->DoRequest(aRequest); sl@0: if((aRequest.ReturnCode() != KErrNone) && (aRequest.ReqType() == TPowerRequest::EChange)) sl@0: { sl@0: aRequest.ReqType() = TPowerRequest::ESetDefaultLevel; sl@0: aRequest.Level() = pR->iDefaultLevel; sl@0: pR->DoRequest(aRequest); sl@0: } sl@0: //Set clientId to -2, indicating that the resource is deregistered. sl@0: CompleteNotifications(KDynamicResourceDeRegistering, pR, aRequest.Level(), KErrNone, aRequest.ClientId()); sl@0: return KErrNone; sl@0: } sl@0: //Handle custom sense resource sl@0: if(aRequest.Resource()->Sense() == DStaticPowerResource::ECustom) sl@0: { sl@0: if(pR->iResourceId & KIdMaskDynamic) sl@0: { sl@0: aRequest.RequiresChange() = ((DDynamicPowerResourceD*)pR)->iDepCustomFunction(aRequest.ClientId(), *(pC->iName), aRequest.ResourceId(), sl@0: EClientRelinquishLevel, aRequest.Level(), (TAny*)&pR->iClientList, sl@0: (TAny*)&((DDynamicPowerResourceD*)pR)->iResourceClientList, NULL); sl@0: } sl@0: else sl@0: { sl@0: aRequest.RequiresChange() = pR->iDepCustomFunction(aRequest.ClientId(), *(pC->iName), aRequest.ResourceId(), sl@0: EClientRelinquishLevel, aRequest.Level(), (TAny*)&pR->iClientList, sl@0: (TAny*)&pR->iResourceClientList, NULL); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: SPowerResourceClientLevel* pL = NULL; sl@0: SPowerResourceClientLevel* pMCL = NULL; sl@0: TInt maxLevel = KMinTInt; sl@0: //Find the maximum level from client sl@0: for(SDblQueLink* pCL = pR->iClientList.First(); pCL != &pR->iClientList.iA; pCL = pCL->iNext) sl@0: { sl@0: pL = (SPowerResourceClientLevel*)pCL; sl@0: if(pL->iClientId == (TUint)aRequest.ClientId()) sl@0: continue; sl@0: if(pMCL == NULL) sl@0: { sl@0: maxLevel = pL->iLevel; sl@0: pMCL = pL; sl@0: continue; sl@0: } sl@0: if(((pR->Sense() == DStaticPowerResource::ENegative) && (pL->iLevel < maxLevel)) || sl@0: ((pR->Sense() == DStaticPowerResource::EPositive) && (pL->iLevel > maxLevel))) sl@0: { sl@0: maxLevel = pL->iLevel; sl@0: pMCL = pL; sl@0: } sl@0: } sl@0: //Find the maximum level from resource client level sl@0: if(pR->iResourceId & KIdMaskDynamic) sl@0: pL = ((DDynamicPowerResourceD*)pR)->iResourceClientList; sl@0: else sl@0: pL = pR->iResourceClientList; sl@0: for(; pL != NULL; pL = pL->iNextInList) sl@0: { sl@0: if(pL->iClientId == (TUint)aRequest.ClientId()) sl@0: continue; sl@0: if(pMCL == NULL) sl@0: { sl@0: maxLevel = pL->iLevel; sl@0: pMCL = pL; sl@0: continue; sl@0: } sl@0: if(((pR->Sense() == DStaticPowerResource::ENegative) && (pL->iLevel < maxLevel)) || sl@0: ((pR->Sense() == DStaticPowerResource::EPositive) && (pL->iLevel > maxLevel))) sl@0: { sl@0: maxLevel = pL->iLevel; sl@0: pMCL = pL; sl@0: } sl@0: } sl@0: if(pMCL == NULL) sl@0: { sl@0: aRequest.ClientId() = -1; sl@0: aRequest.Level() = pR->iDefaultLevel; sl@0: } sl@0: else sl@0: { sl@0: aRequest.ClientId() = pMCL->iClientId; sl@0: aRequest.Level() = maxLevel; sl@0: } sl@0: } sl@0: if((aRequest.Level() == pR->iCachedLevel) && !aRequest.RequiresChange()) //No need to change the resource just update the owner sl@0: { sl@0: pR->iLevelOwnerId = aRequest.ClientId(); sl@0: if(pR->iIdleListEntry) sl@0: pR->iIdleListEntry->iLevelOwnerId = aRequest.ClientId(); sl@0: aRequest.ReturnCode() = KErrNone; sl@0: return KErrNone; sl@0: } sl@0: aRequest.ReqType() = TPowerRequest::EChange; //Make the change otherwise PSL set to default level sl@0: sl@0: const TDesC8 *name; sl@0: if(aRequest.ClientId() == -1) sl@0: name = &KNoClient; sl@0: else sl@0: { sl@0: if(aRequest.ClientId() & (1 << RESOURCE_BIT_IN_ID_CHECK)) sl@0: { sl@0: DStaticPowerResourceD* pResource; sl@0: if(aRequest.ClientId() & KIdMaskDynamic) sl@0: pResource = (DStaticPowerResourceD*)iDynamicResDependencyList[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)]; sl@0: else sl@0: pResource = iStaticResDependencyArray[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK) - 1]; sl@0: name = pResource->iName; sl@0: } sl@0: else sl@0: { sl@0: SPowerResourceClient* pClient; sl@0: if(aRequest.ClientId() & USER_SIDE_CLIENT_BIT_MASK) sl@0: pClient = iUserSideClientList[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)]; sl@0: else // coverity[returned_null] sl@0: pClient = iClientList[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)]; sl@0: name = pClient->iName; sl@0: } sl@0: } sl@0: sl@0: if(pR->iResourceId & KIdMaskDynamic) sl@0: aRequest.ReturnCode() = ((DDynamicPowerResourceD*)pR)->HandleChangePropagation(aRequest, EChangeStart, aRequest.ClientId(), *name); sl@0: else sl@0: aRequest.ReturnCode() = pR->HandleChangePropagation(aRequest, EChangeStart, aRequest.ClientId(), *name); sl@0: if(aRequest.ReturnCode() == KErrPermissionDenied) //Update the ownerId alone sl@0: { sl@0: pR->iLevelOwnerId = aRequest.ClientId(); sl@0: if(pR->iIdleListEntry) sl@0: pR->iIdleListEntry->iLevelOwnerId = aRequest.ClientId(); sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: /** sl@0: Deregisters resource dependency. sl@0: */ sl@0: TInt DPowerResourceController::DeregisterResourceDependency(SPowerResourceClient* aClientPtr, TUint aResId1, TUint aResId2) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::DeregisterResourceDependency")); sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId1 = 0x%x, ResourceId2 = 0x%x", sl@0: aClientPtr->iClientId, aResId1, aResId2)); sl@0: if(iDfcQDependencyLock) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterResourceDependency::Resource In Use")); sl@0: UNLOCK_RETURN(KErrInUse); sl@0: } sl@0: DDynamicPowerResourceD *pDR1 = NULL; sl@0: DDynamicPowerResourceD *pDR2 = NULL; sl@0: SNode* pN1 = NULL; sl@0: SNode* pN2 = NULL; sl@0: SPowerResourceClientLevel* pCL1 = NULL; sl@0: SPowerResourceClientLevel* pCL2 = NULL; sl@0: //Get first resource from list sl@0: if(!(aResId1 & KIdMaskResourceWithDependencies) || !(aResId2 & KIdMaskResourceWithDependencies)) sl@0: UNLOCK_RETURN(KErrAccessDenied); sl@0: sl@0: if(aResId1 & KIdMaskDynamic) sl@0: { sl@0: pDR1 = iDynamicResDependencyList[(TUint16)(aResId1 & ID_INDEX_BIT_MASK)]; sl@0: if(!pDR1) sl@0: UNLOCK_RETURN(KErrNotFound); sl@0: pN1 = pDR1->iDependencyList; sl@0: pCL1 = pDR1->iResourceClientList; sl@0: } sl@0: else sl@0: { sl@0: if((aResId1 & ID_INDEX_BIT_MASK) > iStaticResDependencyCount) sl@0: UNLOCK_RETURN(KErrNotFound); sl@0: pDR1 = (DDynamicPowerResourceD*)iStaticResDependencyArray[(aResId1 & ID_INDEX_BIT_MASK) - 1]; sl@0: pN1 = ((DStaticPowerResourceD*)pDR1)->iDependencyList; sl@0: pCL1 = ((DStaticPowerResourceD*)pDR1)->iResourceClientList; sl@0: } sl@0: sl@0: //Get second resource from list sl@0: if(aResId2 & KIdMaskDynamic) sl@0: { sl@0: pDR2 = iDynamicResDependencyList[(TUint16)(aResId2 & ID_INDEX_BIT_MASK)]; sl@0: if(!pDR2) sl@0: UNLOCK_RETURN(KErrNotFound); sl@0: pN2 = pDR2->iDependencyList; sl@0: pCL2 = pDR2->iResourceClientList; sl@0: } sl@0: else sl@0: { sl@0: if((aResId2 & ID_INDEX_BIT_MASK)> iStaticResDependencyCount) sl@0: UNLOCK_RETURN(KErrNotFound); sl@0: pDR2 = (DDynamicPowerResourceD*)iStaticResDependencyArray[(TUint16)(aResId2 & ID_INDEX_BIT_MASK) - 1]; sl@0: pN2 = ((DStaticPowerResourceD*)pDR2)->iDependencyList; sl@0: pCL2 = ((DStaticPowerResourceD*)pDR2)->iResourceClientList; sl@0: } sl@0: sl@0: //Check whether dependency exist between the two sl@0: SNode* pN = NULL; sl@0: for(pN = pN1; pN != NULL; pN = pN->iNext) sl@0: { sl@0: if(pN->iResource->iResourceId == pDR2->iResourceId) sl@0: break; sl@0: } sl@0: if(pN == NULL) sl@0: UNLOCK_RETURN(KErrNotFound); sl@0: pN1 = pN; //Storing for later use. sl@0: for(pN = pN2; pN != NULL; pN = pN->iNext) sl@0: { sl@0: if(pN->iResource->iResourceId == pDR1->iResourceId) sl@0: break; sl@0: } sl@0: if(pN == NULL) sl@0: return KErrNotFound; sl@0: pN2 = pN; //Storing for later use sl@0: //Remove the dependency link from both the resource sl@0: if(aResId1 & KIdMaskDynamic) sl@0: { sl@0: LIST_REMOVE(pDR1->iDependencyList, pN1, iNext, SNode); sl@0: } sl@0: else sl@0: { sl@0: LIST_REMOVE(((DStaticPowerResourceD*)pDR1)->iDependencyList, pN1, iNext, SNode); sl@0: } sl@0: sl@0: if(aResId2 & KIdMaskDynamic) sl@0: { sl@0: LIST_REMOVE(pDR2->iDependencyList, pN2, iNext, SNode); sl@0: } sl@0: else sl@0: { sl@0: LIST_REMOVE(((DStaticPowerResourceD*)pDR2)->iDependencyList, pN2, iNext, SNode); sl@0: } sl@0: sl@0: //Remove the resource client level from each resource sl@0: for(; pCL1 != NULL; pCL1 = pCL1->iNextInList) sl@0: { sl@0: if(pCL1->iClientId == pDR2->iResourceId) sl@0: { sl@0: if(aResId1 & KIdMaskDynamic) sl@0: { sl@0: LIST_REMOVE(pDR1->iResourceClientList, pCL1, iNextInList, SPowerResourceClientLevel); sl@0: } sl@0: else sl@0: { sl@0: LIST_REMOVE(((DStaticPowerResourceD*)pDR1)->iResourceClientList, pCL1, iNextInList, sl@0: SPowerResourceClientLevel); sl@0: } sl@0: LIST_PUSH(iResourceLevelPool, pCL1, iNextInList); sl@0: iResourceLevelPoolCount++; sl@0: break; sl@0: } sl@0: } sl@0: for(; pCL2 != NULL; pCL2 = pCL2->iNextInList) sl@0: { sl@0: if(pCL2->iClientId == pDR1->iResourceId) sl@0: { sl@0: if(aResId2 & KIdMaskDynamic) sl@0: { sl@0: LIST_REMOVE(pDR2->iResourceClientList, pCL2, iNextInList, SPowerResourceClientLevel); sl@0: } sl@0: else sl@0: { sl@0: LIST_REMOVE(((DStaticPowerResourceD*)pDR2)->iResourceClientList, pCL2, iNextInList, sl@0: SPowerResourceClientLevel); sl@0: } sl@0: LIST_PUSH(iResourceLevelPool, pCL2, iNextInList); sl@0: iResourceLevelPoolCount++; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get(); sl@0: req->ResourceCb() = NULL; sl@0: req->ReqType() = TPowerRequest::ESetDefaultLevel; sl@0: req->RequiresChange() = EFalse; sl@0: req->ReturnCode() = KErrNone; sl@0: if((TUint)pDR1->iLevelOwnerId == pDR2->iResourceId) sl@0: { sl@0: //Ask to change to default level. Process this in the RC thread; sl@0: req->ResourceId() = pDR1->iResourceId; sl@0: req->ClientId() = pDR2->iResourceId; sl@0: req->Resource() = pDR1; sl@0: req->Level() = pDR1->iDefaultLevel; sl@0: if(aResId1 & KIdMaskDynamic) sl@0: pDR1->Lock(); sl@0: UnLock(); sl@0: req->SendReceive(iMsgQDependency); sl@0: Lock(); sl@0: if(aResId1 & KIdMaskDynamic) sl@0: pDR1->UnLock(); sl@0: } sl@0: if((TUint)pDR2->iLevelOwnerId == pDR1->iResourceId) sl@0: { sl@0: //Ask to change to default level. Process this in the RC thread. sl@0: req->ResourceId() = pDR2->iResourceId; sl@0: req->ClientId() = pDR1->iResourceId; sl@0: req->Resource() = pDR2; sl@0: req->Level() = pDR2->iDefaultLevel; sl@0: if(aResId2 & KIdMaskDynamic) sl@0: pDR2->Lock(); sl@0: UnLock(); sl@0: req->SendReceive(iMsgQDependency); sl@0: Lock(); sl@0: if(aResId2 & KIdMaskDynamic) sl@0: pDR2->UnLock(); sl@0: } sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("HandleResourceChange(aRequest, aProp, aOriginatorId, aOriginatorName, this); sl@0: return result; sl@0: } sl@0: //Function to change the resource state of dependency resource. sl@0: TInt DPowerResourceController::HandleResourceChange(TPowerRequest &aRequest, TPropagation aProp, TUint aOriginatorId, sl@0: const TDesC8& aOriginatorName, DStaticPowerResourceD* aResource) sl@0: { sl@0: static TUint16 clientLevelCount = 0; sl@0: DStaticPowerResourceD* pDR = (DStaticPowerResourceD*)aRequest.Resource(); sl@0: DStaticPowerResourceD* pDepRes = NULL; sl@0: SNode* dependencyList = NULL; sl@0: TPowerRequest depRequest; sl@0: TInt result = KErrNone; sl@0: TInt resState; sl@0: depRequest.ReqType() = TPowerRequest::EChange; sl@0: depRequest.ResourceCb() = NULL; sl@0: depRequest.ReturnCode() = KErrNone; sl@0: depRequest.RequiresChange() = EFalse; sl@0: sl@0: if(pDR->iResourceId & KIdMaskDynamic) sl@0: dependencyList = ((DDynamicPowerResourceD*)pDR)->iDependencyList; sl@0: else sl@0: dependencyList = pDR->iDependencyList; sl@0: switch(aProp) sl@0: { sl@0: case EChangeStart: sl@0: { sl@0: if(!dependencyList) /*No dependents so change state of the resource*/ sl@0: { sl@0: aRequest.ReturnCode() = pDR->DoRequest(aRequest); sl@0: if(aRequest.ReturnCode() == KErrNone) sl@0: { sl@0: aResource->iCachedLevel = aRequest.Level(); sl@0: aResource->iLevelOwnerId = aRequest.ClientId(); sl@0: if(aResource->iIdleListEntry) sl@0: { sl@0: aResource->iIdleListEntry->iCurrentLevel = aRequest.Level(); sl@0: aResource->iIdleListEntry->iLevelOwnerId = aRequest.ClientId(); sl@0: } sl@0: CompleteNotifications(aRequest.ClientId(), pDR, sl@0: aRequest.Level(), aRequest.ReturnCode(), aRequest.ClientId()); sl@0: } sl@0: break; sl@0: } sl@0: depRequest.ResourceId() = aRequest.ResourceId(); sl@0: depRequest.ClientId() = aRequest.ResourceId(); sl@0: depRequest.Level() = aRequest.Level(); sl@0: depRequest.Resource() = pDR; sl@0: result = pDR->HandleChangePropagation(depRequest, ECheckChangeAllowed, aOriginatorId, aOriginatorName); sl@0: if(result != KErrNone) sl@0: return result; sl@0: /*Adjust resource client level*/ sl@0: if(clientLevelCount) sl@0: { sl@0: result = ReserveClientLevelPoolCount(clientLevelCount); sl@0: if(result != KErrNone) sl@0: return result; sl@0: } sl@0: /*Resource change of dependents */ sl@0: pDR->HandleChangePropagation(aRequest, ERequestStateChange, aOriginatorId, aOriginatorName); sl@0: /*Notification to dependents */ sl@0: pDR->HandleChangePropagation(aRequest, EIssueNotifications, aOriginatorId, aOriginatorName); sl@0: break; sl@0: } sl@0: case ECheckChangeAllowed: sl@0: { sl@0: TChangePropagationStatus status; sl@0: for(SNode* depNode = dependencyList; depNode != NULL; depNode = depNode->iNext) sl@0: { sl@0: pDepRes = depNode->iResource; sl@0: if((aRequest.ClientId() & KIdMaskResourceWithDependencies) && sl@0: (pDepRes->iResourceId == (TUint)aRequest.ClientId())) sl@0: continue; sl@0: /*Resource need not change if it is already in that state, so continue with sl@0: another dependent state.*/ sl@0: if(pDepRes->iResourceId & KIdMaskDynamic) sl@0: status = ((DDynamicPowerResourceD*)pDepRes)->TranslateDependentState(aRequest.ResourceId(), sl@0: aRequest.Level(), resState); sl@0: else sl@0: status = ((DStaticPowerResourceD*)pDepRes)->TranslateDependentState(aRequest.ResourceId(), sl@0: aRequest.Level(), resState); sl@0: if((status == ENoChange) || (pDepRes->iCachedLevel == resState)) sl@0: { sl@0: depNode->iRequiresChange = EFalse; sl@0: continue; sl@0: } sl@0: if(status == EChangeNotAccepted) sl@0: return KErrPermissionDenied; sl@0: depRequest.ResourceId() = pDepRes->iResourceId; sl@0: depRequest.ClientId() = aRequest.ResourceId(); /*ID of the dependent resource */ sl@0: depRequest.Level() = resState; sl@0: depRequest.Resource() = pDepRes; sl@0: /*Check resource client list and resource list to see whether change is allowed.*/ sl@0: if(pDepRes->Sense() == DStaticPowerResource::ECustom) sl@0: { sl@0: /*Call custom function to check whether change is allowed.*/ sl@0: if(pDepRes->iResourceId & KIdMaskDynamic) sl@0: depRequest.RequiresChange() = ((DDynamicPowerResourceD*)pDepRes)->iDepCustomFunction(depRequest.ClientId(), sl@0: aOriginatorName, depRequest.ResourceId(), EClientRequestLevel, depRequest.Level(), (TAny*)&pDepRes->iClientList, sl@0: (TAny*)&((DDynamicPowerResourceD*)pDepRes)->iResourceClientList, NULL); sl@0: else sl@0: depRequest.RequiresChange() = ((DStaticPowerResourceD*)pDepRes)->iDepCustomFunction(depRequest.ClientId(), sl@0: aOriginatorName, depRequest.ResourceId(), EClientRequestLevel, depRequest.Level(), (TAny*)&pDepRes->iClientList, sl@0: (TAny*)&((DStaticPowerResourceD*)pDepRes)->iResourceClientList, NULL); sl@0: if(!depRequest.RequiresChange()) sl@0: return KErrPermissionDenied; sl@0: } sl@0: SPowerResourceClientLevel*pN=NULL; sl@0: for(SDblQueLink* pNL=pDepRes->iClientList.First();pNL!=&pDepRes->iClientList.iA; pNL=pNL->iNext) sl@0: { sl@0: pN = (SPowerResourceClientLevel*)pNL; sl@0: if(pDepRes->Sense() == DStaticPowerResource::EPositive) sl@0: { sl@0: if(pN->iLevel > depRequest.Level()) sl@0: return KErrPermissionDenied; sl@0: } sl@0: else if(pDepRes->Sense() == DStaticPowerResource::ENegative) sl@0: { sl@0: if(pN->iLevel < depRequest.Level()) sl@0: return KErrPermissionDenied; sl@0: } sl@0: } sl@0: /*check through the resource client level */ sl@0: SPowerResourceClientLevel*pCL = NULL; sl@0: if(pDepRes->iResourceId & KIdMaskDynamic) sl@0: pCL = ((DDynamicPowerResourceD*)pDepRes)->iResourceClientList; sl@0: else sl@0: pCL = ((DStaticPowerResourceD*)pDepRes)->iResourceClientList; sl@0: for(; pCL != NULL; pCL = pCL->iNextInList) sl@0: { sl@0: if(pCL->iClientId == pDR->iResourceId) sl@0: break; sl@0: } sl@0: if(!pCL) sl@0: clientLevelCount++; sl@0: /*check dependent resource client list & resource list to see whether change is allowed */ sl@0: if(pDepRes->iResourceId & KIdMaskDynamic) sl@0: result = ((DDynamicPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest, sl@0: ECheckChangeAllowed, aOriginatorId, aOriginatorName); sl@0: else sl@0: result = ((DStaticPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest, sl@0: ECheckChangeAllowed, aOriginatorId, aOriginatorName); sl@0: if(result != KErrNone) sl@0: return result; sl@0: depNode->iPropagatedLevel = resState; sl@0: depNode->iRequiresChange = ETrue; sl@0: } sl@0: break; sl@0: } sl@0: case ERequestStateChange: sl@0: { sl@0: SPowerResourceClientLevel* pCL = NULL; sl@0: for(SNode* depNode = dependencyList; depNode != NULL; depNode = depNode->iNext) sl@0: { sl@0: pDepRes = depNode->iResource; sl@0: if((!depNode->iRequiresChange) || (pDepRes->iResourceId == (TUint)aRequest.ClientId())) sl@0: continue; sl@0: depRequest.ResourceId() = pDepRes->iResourceId; sl@0: depRequest.ClientId() = aRequest.ResourceId(); sl@0: depRequest.Level() = depNode->iPropagatedLevel; sl@0: depRequest.Resource() = pDepRes; sl@0: if(pDepRes->iResourceId & KIdMaskDynamic) sl@0: ((DDynamicPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest, ERequestStateChange, sl@0: aOriginatorId, aOriginatorName); sl@0: else sl@0: ((DStaticPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest, ERequestStateChange, sl@0: aOriginatorId, aOriginatorName); sl@0: /*Update level if resource client level is already present for this resource.*/ sl@0: if(pDepRes->iResourceId & KIdMaskDynamic) sl@0: pCL = ((DDynamicPowerResourceD*)pDepRes)->iResourceClientList; sl@0: else sl@0: pCL = ((DStaticPowerResourceD*)pDepRes)->iResourceClientList; sl@0: for(; pCL != NULL; pCL = pCL->iNextInList) sl@0: { sl@0: if(pCL->iClientId == pDR->iResourceId) sl@0: { sl@0: pCL->iLevel = depNode->iPropagatedLevel; sl@0: break; sl@0: } sl@0: } sl@0: if(!pCL) /*Create a new resource client level*/ sl@0: { sl@0: RemoveClientLevelFromPool(pCL); sl@0: pCL->iClientId = pDR->iResourceId; sl@0: pCL->iResourceId = pDepRes->iResourceId; sl@0: pCL->iLevel = depNode->iPropagatedLevel; sl@0: if(pDepRes->iResourceId & KIdMaskDynamic) sl@0: { sl@0: LIST_PUSH(((DDynamicPowerResourceD*)pDepRes)->iResourceClientList, pCL, iNextInList); sl@0: } sl@0: else sl@0: { sl@0: LIST_PUSH(((DStaticPowerResourceD*)pDepRes)->iResourceClientList, pCL, iNextInList); sl@0: } sl@0: clientLevelCount--; sl@0: } sl@0: } sl@0: #ifdef PRM_INSTRUMENTATION_MACRO sl@0: if(aRequest.ClientId() & KIdMaskResourceWithDependencies) sl@0: { sl@0: SPowerResourceClient res; sl@0: SPowerResourceClient* pC = &res; sl@0: pC->iClientId = aRequest.ClientId(); sl@0: pC->iName = &KParentResource; sl@0: DStaticPowerResource*pR = (DStaticPowerResource*)pDR; sl@0: TUint aResourceId = pDR->iResourceId; sl@0: TInt aNewState = aRequest.Level(); sl@0: PRM_CLIENT_CHANGE_STATE_START_TRACE sl@0: } sl@0: #endif sl@0: aResource->DoRequest(aRequest); sl@0: #ifdef PRM_INSTRUMENTATION_MACRO sl@0: if(aRequest.ClientId() & KIdMaskResourceWithDependencies) sl@0: { sl@0: SPowerResourceClient res; sl@0: SPowerResourceClient* pC = &res; sl@0: pC->iClientId = aRequest.ClientId(); sl@0: pC->iName = &KParentResource; sl@0: DStaticPowerResource*pR = (DStaticPowerResource*)pDR; sl@0: TUint aResourceId = pDR->iResourceId; sl@0: TInt aNewState = aRequest.Level(); sl@0: TInt r = KErrNone; sl@0: PRM_CLIENT_CHANGE_STATE_END_TRACE sl@0: } sl@0: #endif sl@0: pDR->iCachedLevel = aRequest.Level(); sl@0: pDR->iLevelOwnerId = aRequest.ClientId(); sl@0: if(pDR->iIdleListEntry) sl@0: { sl@0: pDR->iIdleListEntry->iCurrentLevel = aRequest.Level(); sl@0: pDR->iIdleListEntry->iLevelOwnerId = aRequest.ClientId(); sl@0: } sl@0: break; sl@0: } sl@0: case EIssueNotifications: sl@0: { sl@0: for(SNode* depNode = dependencyList; depNode != NULL; depNode = depNode->iNext) sl@0: { sl@0: pDepRes = depNode->iResource; sl@0: if((!depNode->iRequiresChange) || (pDepRes->iResourceId == (TUint)aRequest.ClientId())) sl@0: continue; sl@0: depRequest.ResourceId() = pDepRes->iResourceId; sl@0: depRequest.ClientId() = pDepRes->iLevelOwnerId; sl@0: depRequest.Level() = pDepRes->iCachedLevel; sl@0: depRequest.Resource() = pDepRes; sl@0: if(pDepRes->iResourceId & KIdMaskDynamic) sl@0: ((DDynamicPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest, EIssueNotifications, sl@0: aOriginatorId, aOriginatorName); sl@0: else sl@0: ((DStaticPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest, EIssueNotifications, sl@0: aOriginatorId, aOriginatorName); sl@0: } sl@0: CompleteNotifications(aRequest.ClientId(), pDR, aRequest.Level(), KErrNone, sl@0: aRequest.ClientId()); sl@0: break; sl@0: } sl@0: default: sl@0: return KErrNotSupported; sl@0: } sl@0: return result; sl@0: } sl@0: sl@0: