1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/drivers/resourceman/resourcecontrol.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,4002 @@
1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32\drivers\resourceman\resourcecontrol.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include <drivers/resourcecontrol.h>
1.22 +#include <drivers/resourcecontrol_trace.h>
1.23 +#ifdef DEBUG_VERSION
1.24 +#define GET_CRITICAL_SECTION_COUNT \
1.25 + DThread& thread = Kern::CurrentThread(); \
1.26 + TInt CsCount = thread.iNThread.iCsCount;
1.27 +
1.28 +#define LOCK_AND_CRITICAL_SECTION_COUNT_CHECK \
1.29 + if(thread.iNThread.iCsCount != CsCount) \
1.30 + Kern::Fault("PowerResourceController CScount", __LINE__); \
1.31 + if(PowerResourceController->iResourceMutex->iHoldCount != 0) \
1.32 + Kern::Fault("PowerResourceController HoldCount", __LINE__);
1.33 +#else
1.34 +#define GET_CRITICAL_SECTION_COUNT
1.35 +#define LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.36 +#endif
1.37 +
1.38 +/** Allow interface class to call this. */
1.39 +DPowerResourceController* PowerResourceController = NULL;
1.40 +
1.41 +/** Resource Controller factory class implementation */
1.42 +#ifdef RESOURCE_MANAGER_SIMULATED_PSL
1.43 +#ifndef PRM_ENABLE_EXTENDED_VERSION
1.44 +_LIT(KPddName,"resourcecontroller.pdd");
1.45 +#else
1.46 +_LIT(KPddName, "resourcecontrollerextended.pdd");
1.47 +#endif
1.48 +#else
1.49 +#ifndef PRM_ENABLE_EXTENDED_VERSION
1.50 +_LIT(KPddName, "resman.pdd");
1.51 +#else
1.52 +_LIT(KPddName, "resmanextended.pdd");
1.53 +#endif
1.54 +#endif
1.55 +
1.56 +/** Factory class constructor */
1.57 +DResConPddFactory::DResConPddFactory()
1.58 + {
1.59 + //Set Version number
1.60 + iVersion = DResConPddFactory::VersionRequired();
1.61 + }
1.62 +
1.63 +TInt DResConPddFactory::Install()
1.64 + {
1.65 + // Set a Name for Resource Controller Factory class object.
1.66 + return(SetName(&KPddName));
1.67 + }
1.68 +
1.69 +/** Called by the kernel's device driver framework to create a Physical Channel. */
1.70 +TInt DResConPddFactory::Create(DBase*& aChannel, TInt /*aUint*/, const TDesC8* /*anInfo*/, const TVersion& /*aVer*/)
1.71 + {
1.72 + //Create new interface for each channel.
1.73 + DUserSideProxyInterface *pI = new (DUserSideProxyInterface);
1.74 + if(!pI)
1.75 + return KErrNoMemory;
1.76 + pI->iController = PowerResourceController; //Store the resource controller.
1.77 + aChannel = (DBase*)pI;
1.78 + return KErrNone;
1.79 + }
1.80 +
1.81 +/** Called by the kernel's device driver framework to check if this PDD is suitable for use with a Logical Channel.*/
1.82 +TInt DResConPddFactory::Validate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
1.83 + {
1.84 + if (!Kern::QueryVersionSupported(DResConPddFactory::VersionRequired(),aVer))
1.85 + return(KErrNotSupported);
1.86 + return KErrNone;
1.87 + }
1.88 +
1.89 +/** Return the driver capabilities */
1.90 +void DResConPddFactory::GetCaps(TDes8& aDes) const
1.91 + {
1.92 + // Create a capabilities object
1.93 + TCaps caps;
1.94 + caps.iVersion = iVersion;
1.95 + // Zero the buffer
1.96 + TInt maxLen = aDes.MaxLength();
1.97 + aDes.FillZ(maxLen);
1.98 + // Copy cpabilities
1.99 + TInt size=sizeof(caps);
1.100 + if(size>maxLen)
1.101 + size=maxLen;
1.102 + aDes.Copy((TUint8*)&caps,size);
1.103 + }
1.104 +
1.105 +/** Entry point for a standard physical device driver (PDD) that is also an extension */
1.106 +#ifndef RESOURCE_MANAGER_SIMULATED_PSL
1.107 +DECLARE_EXTENSION_PDD()
1.108 + {
1.109 + return new DResConPddFactory;
1.110 + }
1.111 +#endif
1.112 +
1.113 +/** Interface class implementation */
1.114 +TInt TInterface::RegisterClient(TUint& aClientId, const TDesC8& aName, TOwnerType aType)
1.115 + {
1.116 + GET_CRITICAL_SECTION_COUNT
1.117 + TInt r;
1.118 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::RegisterClient"));
1.119 + r = PowerResourceController->RegisterClient(aClientId, aName, aType);
1.120 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.121 + return r;
1.122 + }
1.123 +
1.124 +TInt TInterface::DeRegisterClient(TUint aClientId)
1.125 + {
1.126 + GET_CRITICAL_SECTION_COUNT
1.127 + TInt r;
1.128 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::DeRegisterClient"));
1.129 + r = PowerResourceController->DeRegisterClient(aClientId);
1.130 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.131 + return r;
1.132 + }
1.133 +
1.134 +TInt TInterface::GetClientName(TUint aClientId, TUint aTargetClientId, TDes8& aName)
1.135 + {
1.136 + GET_CRITICAL_SECTION_COUNT
1.137 + TInt r;
1.138 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetClientName"));
1.139 + r = PowerResourceController->GetClientName(aClientId, aTargetClientId, aName);
1.140 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.141 + return r;
1.142 + }
1.143 +
1.144 +TInt TInterface::GetClientId(TUint aClientId, TDesC8& aClientName, TUint& aTargetClientId)
1.145 + {
1.146 + GET_CRITICAL_SECTION_COUNT
1.147 + TInt r;
1.148 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetClientId"));
1.149 + r = PowerResourceController->GetClientId(aClientId, aClientName, aTargetClientId);
1.150 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.151 + return r;
1.152 + }
1.153 +
1.154 +TInt TInterface::GetResourceId(TUint aClientId, TDesC8& aResourceName, TUint& aResourceId)
1.155 + {
1.156 + GET_CRITICAL_SECTION_COUNT
1.157 + TInt r;
1.158 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetResourceId"));
1.159 + r = PowerResourceController->GetResourceId(aClientId, aResourceName, aResourceId);
1.160 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.161 + return r;
1.162 + }
1.163 +
1.164 +TInt TInterface::GetResourceInfo(TUint aClientId, TUint aResourceId, TAny* aInfo)
1.165 + {
1.166 + GET_CRITICAL_SECTION_COUNT
1.167 + TInt r;
1.168 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetResourceInfo"));
1.169 + r = PowerResourceController->GetResourceInfo(aClientId, aResourceId, aInfo);
1.170 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.171 + return r;
1.172 + }
1.173 +
1.174 +TInt TInterface::GetNumResourcesInUseByClient(TUint aClientId, TUint aTargetClientId, TUint& aNumResource)
1.175 + {
1.176 + GET_CRITICAL_SECTION_COUNT
1.177 + TInt r;
1.178 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetNumResourcesInUseByClient"));
1.179 + r = PowerResourceController->GetNumResourcesInUseByClient(aClientId, aTargetClientId, aNumResource);
1.180 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.181 + return r;
1.182 + }
1.183 +
1.184 +TInt TInterface::GetInfoOnResourcesInUseByClient(TUint aClientId, TUint aTargetClientId, TUint& aNumResources, TAny* aInfo)
1.185 + {
1.186 + GET_CRITICAL_SECTION_COUNT
1.187 + TInt r;
1.188 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetInfoOnResourcesInUseByClient"));
1.189 + r = PowerResourceController->GetInfoOnResourcesInUseByClient(aClientId, aTargetClientId, aNumResources, aInfo);
1.190 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.191 + return r;
1.192 + }
1.193 +
1.194 +TInt TInterface::GetNumClientsUsingResource(TUint aClientId, TUint aResourceId, TUint& aNumClients)
1.195 + {
1.196 + GET_CRITICAL_SECTION_COUNT
1.197 + TInt r;
1.198 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetNumClientsUsingResource"));
1.199 + r = PowerResourceController->GetNumClientsUsingResource(aClientId, aResourceId, aNumClients);
1.200 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.201 + return r;
1.202 + }
1.203 +
1.204 +TInt TInterface::GetInfoOnClientsUsingResource(TUint aClientId, TUint aResourceId, TUint& aNumClients, TAny* aInfo)
1.205 + {
1.206 + GET_CRITICAL_SECTION_COUNT
1.207 + TInt r;
1.208 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetInfoOnClientsUsingResource"));
1.209 + r = PowerResourceController->GetInfoOnClientsUsingResource(aClientId, aResourceId, aNumClients, aInfo);
1.210 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.211 + return r;
1.212 + }
1.213 +
1.214 +TInt TInterface::ChangeResourceState(TUint aClientId, TUint aResourceId, TInt aNewState, TPowerResourceCb* aCb)
1.215 + {
1.216 + GET_CRITICAL_SECTION_COUNT
1.217 + TInt r;
1.218 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::ChangeResourceState"));
1.219 + r = PowerResourceController->ChangeResourceState(aClientId, aResourceId, aNewState, aCb);
1.220 + if(!aCb) //Not checking incase of asynchronous function as mutex might be held in RC thread, when this is checked.
1.221 + {
1.222 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.223 + }
1.224 + return r;
1.225 + }
1.226 +
1.227 +TInt TInterface::GetResourceState(TUint aClientId, TUint aResourceId, TBool aCached, TInt& aState, TInt& aLevelOwnerId)
1.228 + {
1.229 + GET_CRITICAL_SECTION_COUNT
1.230 + TInt r;
1.231 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetResourceState"));
1.232 + r = PowerResourceController->GetResourceState(aClientId, aResourceId, aCached, aState, aLevelOwnerId);
1.233 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.234 + return r;
1.235 + }
1.236 +
1.237 +TInt TInterface::GetResourceState(TUint aClientId, TUint aResourceId, TBool aCached, TPowerResourceCb& aCb)
1.238 + {
1.239 + TInt r;
1.240 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetResourceState"));
1.241 + r = PowerResourceController->GetResourceState(aClientId, aResourceId, aCached, aCb);
1.242 + return r;
1.243 + }
1.244 +
1.245 +TInt TInterface::CancelAsyncRequestCallBack(TUint aClientId, TUint aResourceId, TPowerResourceCb& aCb)
1.246 + {
1.247 + GET_CRITICAL_SECTION_COUNT
1.248 + TInt r;
1.249 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::CancelAsyncRequestCallback"));
1.250 + r = PowerResourceController->CancelAsyncRequestCallBack(aClientId, aResourceId, aCb);
1.251 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.252 + return r;
1.253 + }
1.254 +
1.255 +TInt TInterface::RequestNotification(TUint aClientId, TUint aResourceId, DPowerResourceNotification& aN)
1.256 + {
1.257 + GET_CRITICAL_SECTION_COUNT
1.258 + TInt r;
1.259 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::RequestNotification"));
1.260 + r = PowerResourceController->RequestNotification(aClientId, aResourceId, aN);
1.261 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.262 + return r;
1.263 + }
1.264 +
1.265 +TInt TInterface::RequestNotification(TUint aClientId, TUint aResourceId, DPowerResourceNotification& aN, TInt aThreshold,
1.266 + TBool aDirection)
1.267 + {
1.268 + GET_CRITICAL_SECTION_COUNT
1.269 + TInt r;
1.270 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::RequestNotification"));
1.271 + r = PowerResourceController->RequestNotification(aClientId, aResourceId, aN, aThreshold, aDirection);
1.272 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.273 + return r;
1.274 + }
1.275 +
1.276 +TInt TInterface::CancelNotification(TUint aClientId, TUint aResourceId, DPowerResourceNotification& aN)
1.277 + {
1.278 + GET_CRITICAL_SECTION_COUNT
1.279 + TInt r;
1.280 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::CancelNotification"));
1.281 + r = PowerResourceController->CancelNotification(aClientId, aResourceId, aN);
1.282 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.283 + return r;
1.284 + }
1.285 +
1.286 +TInt TInterface::DeRegisterClientLevelFromResource(TUint aClientId, TUint aResourceId)
1.287 + {
1.288 + GET_CRITICAL_SECTION_COUNT
1.289 + TInt r;
1.290 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::DeRegisterClientLevelFromResource"));
1.291 + r = PowerResourceController->DeRegisterClientLevelFromResource(aClientId, aResourceId);
1.292 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.293 + return r;
1.294 + }
1.295 +
1.296 +TInt TInterface::AllocReserve(TUint aClientId, TUint8 aNumCl, TUint8 aNumRm)
1.297 + {
1.298 + GET_CRITICAL_SECTION_COUNT
1.299 + TInt r;
1.300 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::AllocReserve"));
1.301 + r = PowerResourceController->AllocReserve(aClientId, aNumCl, aNumRm);
1.302 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.303 + return r;
1.304 + }
1.305 +
1.306 +/** This function is used by export functions of Resource contoller defined in seperate file */
1.307 +DPowerResourceController* TInterface::GetPowerResourceController(void)
1.308 + {
1.309 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::GetPowerResourceController"));
1.310 + return PowerResourceController;
1.311 + }
1.312 +
1.313 +TInt TInterface::ControlIO(TUint aClientId, TUint aFunction, TAny* aParam1, TAny* aParam2, TAny* aParam3)
1.314 + {
1.315 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">TInterface::ControlIO"));
1.316 + return PowerResourceController->GetInterface(aClientId, aFunction, aParam1, aParam2, aParam3);
1.317 + }
1.318 +
1.319 +/** Resouce controller panic */
1.320 +void DPowerResourceController::Panic(TUint8 aPanic)
1.321 + {
1.322 + Kern::Fault("Power Resource Controller", aPanic);
1.323 + }
1.324 +
1.325 +/** Constructor for power controller. Creates message queue and generates ID for power controller to use. */
1.326 +DPowerResourceController::DPowerResourceController()
1.327 + {
1.328 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::DPowerResouceController()"));
1.329 + //Constructor is expected to invoke multiple times (during creation, variant init 0 and extension init 1)
1.330 + if(PowerResourceController)
1.331 + return;
1.332 + PowerResourceController = this;
1.333 + iClientList.Initialise(0);
1.334 + iUserSideClientList.Initialise(0);
1.335 + iInitialised = EResConCreated;
1.336 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.337 + iDynamicResourceList.Initialise(0);
1.338 + iDynamicResDependencyList.Initialise(0);
1.339 +#endif
1.340 + }
1.341 +
1.342 +/** Destructor for power controller. Frees the memory allocated in kernel heap. */
1.343 +DPowerResourceController::~DPowerResourceController()
1.344 + {
1.345 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::~DPowerResourceController()"));
1.346 +#ifdef RESOURCE_MANAGER_SIMULATED_PSL
1.347 + iCleanList.ResetAndDestroy();
1.348 +#endif
1.349 + iClientList.Delete();
1.350 + iUserSideClientList.Delete();
1.351 +
1.352 +
1.353 +
1.354 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.355 + iDynamicResourceList.Delete();
1.356 + iDynamicResDependencyList.Delete();
1.357 +#endif
1.358 +
1.359 + SPowerResourceClientLevel *pCL = iClientLevelPool;
1.360 + while(iClientLevelPool) //Find the starting position of array to delete
1.361 + {
1.362 + if(iClientLevelPool < pCL)
1.363 + pCL = iClientLevelPool;
1.364 + iClientLevelPool = iClientLevelPool->iNextInList;
1.365 + }
1.366 + //delete pCL;
1.367 + delete []pCL;
1.368 + SPowerRequest *pReq = iRequestPool;
1.369 + while(iRequestPool) //Find the starting position of array to delete
1.370 + {
1.371 + if(iRequestPool < pReq)
1.372 + pReq = iRequestPool;
1.373 + iRequestPool = iRequestPool->iNext;
1.374 + }
1.375 + //delete pR
1.376 + delete []pReq;
1.377 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.378 + pCL = iResourceLevelPool;
1.379 + while(iResourceLevelPool)
1.380 + {
1.381 + if(iResourceLevelPool < pCL)
1.382 + pCL = iResourceLevelPool;
1.383 + iResourceLevelPool = iResourceLevelPool->iNextInList;
1.384 + }
1.385 + //delete resource pool
1.386 + delete []pCL;
1.387 + //delete Message Queue dependency
1.388 + delete iMsgQDependency;
1.389 +#endif
1.390 + //delete Message Queue
1.391 + delete iMsgQ;
1.392 + }
1.393 +
1.394 +/** Send notificatins to clients registered for it for the specified resource. */
1.395 +void DPowerResourceController::CompleteNotifications(TInt aClientId, DStaticPowerResource* aResource, TInt aState,
1.396 + TInt aReturnCode, TInt aLevelOwnerId, TBool aLock)
1.397 + {
1.398 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::CompleteNotifications"));
1.399 + if(aLock)
1.400 + Lock();
1.401 + DPowerResourceNotification*pN=NULL;
1.402 + for(SDblQueLink* pNL=aResource->iNotificationList.First();pNL!=&aResource->iNotificationList.iA; pNL=pNL->iNext)
1.403 + {
1.404 + pN = _LOFF(pNL, DPowerResourceNotification, iNotificationLink);
1.405 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.406 + //If dyanmic resource is deregistering, send notification to all clients requested for it
1.407 + if((pN->iCallback.iResourceId & KIdMaskDynamic) && (aClientId == KDynamicResourceDeRegistering))
1.408 + {
1.409 + pN->iCallback.iResult = aReturnCode;
1.410 + pN->iCallback.iLevel = aState;
1.411 + pN->iCallback.iClientId = aClientId;
1.412 + pN->iCallback.iLevelOwnerId = aLevelOwnerId;
1.413 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("Notification ClientId = 0x%x, ResourceId = %d, state = %d, Result = %d",
1.414 + pN->iCallback.iClientId, pN->iCallback.iResourceId, aState, aReturnCode));
1.415 + PRM_POSTNOTIFICATION_SENT_TRACE
1.416 + pN->iCallback.Enque();
1.417 + continue;
1.418 + }
1.419 +#endif
1.420 + if((pN->iType==DPowerResourceNotification::EUnconditional) ||
1.421 + (pN->iDirection && ((pN->iPreviousLevel < pN->iThreshold) && (aState >= pN->iThreshold))) ||
1.422 + (!pN->iDirection && ((pN->iPreviousLevel > pN->iThreshold) && (aState <= pN->iThreshold))))
1.423 + {
1.424 + pN->iCallback.iResult=aReturnCode;
1.425 + pN->iCallback.iLevel=aState;
1.426 + pN->iCallback.iClientId = aClientId;
1.427 + pN->iCallback.iLevelOwnerId = aLevelOwnerId;
1.428 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("Notifications ClientId = 0x%x, ResourceId = %d, State = %d, Result = %d",
1.429 + pN->iCallback.iClientId, pN->iCallback.iResourceId, aState, aReturnCode));
1.430 + PRM_POSTNOTIFICATION_SENT_TRACE
1.431 + pN->iCallback.Enque();
1.432 + }
1.433 + pN->iPreviousLevel = aState; //Update the state
1.434 + }
1.435 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::CompleteNotifications"));
1.436 + if(aLock)
1.437 + UnLock();
1.438 + return;
1.439 + }
1.440 +
1.441 +/** Complete the asynchronous request. */
1.442 +void DPowerResourceController::CompleteRequest(TPowerRequest& aRequest)
1.443 + {
1.444 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::CompleteRequest"));
1.445 + // Complete notification for state change operation
1.446 + DStaticPowerResource* pR=aRequest.Resource();
1.447 + //If request in EChange or ESetDefaultValue and no error and if shared resources and if change is done then
1.448 + //issue notification.
1.449 + if(((aRequest.ReqType() == TPowerRequest::EChange) || (aRequest.ReqType() == TPowerRequest::ESetDefaultLevel))
1.450 + && (aRequest.ReturnCode() == KErrNone) && ((!pR->Usage()) || (pR->Usage() && aRequest.RequiresChange())))
1.451 + {
1.452 + CompleteNotifications(aRequest.ClientId(), aRequest.Resource(), aRequest.Level(),
1.453 + aRequest.ReturnCode(), aRequest.ClientId());
1.454 + }
1.455 + //Do not update the level if the resource is shared and change is not required or any error.
1.456 + if(aRequest.ReturnCode()==KErrNone && ((aRequest.ReqType() ==TPowerRequest::EGet) ||
1.457 + (((aRequest.ReqType()==TPowerRequest::EChange) || (aRequest.ReqType()==TPowerRequest::ESetDefaultLevel))
1.458 + && ((!pR->Usage()) || (pR->Usage() && aRequest.RequiresChange())))))
1.459 + {
1.460 + Lock();
1.461 + // Cache the latest value
1.462 + pR->iCachedLevel=aRequest.Level();
1.463 + //Need to update client ID only during state change.
1.464 + if(aRequest.ReqType() != TPowerRequest::EGet)
1.465 + pR->iLevelOwnerId=aRequest.ClientId();
1.466 + // Cache Idle list entry for this reosurce if requested.
1.467 + if(pR->iIdleListEntry)
1.468 + {
1.469 + SIdleResourceInfo* pI=pR->iIdleListEntry;
1.470 + if(aRequest.ReqType() != TPowerRequest::EGet)
1.471 + pI->iLevelOwnerId= aRequest.ClientId();
1.472 + pI->iCurrentLevel=aRequest.Level();
1.473 + }
1.474 + UnLock();
1.475 + }
1.476 +
1.477 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::CompleteRequest"));
1.478 + }
1.479 +
1.480 +/** Handle/process the asynchronous request sent to resource controller.
1.481 + The request can be one of the following
1.482 + 1) State change of long latency reosurce
1.483 + 2) Get the state of long latency resource
1.484 + 3) Set the default value of long latency resource */
1.485 +void DPowerResourceController::HandleMsg(TPowerRequest& aRequest)
1.486 + {
1.487 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::HandleMsg"));
1.488 + DStaticPowerResource* pR=aRequest.Resource();
1.489 + //Get client using client ID
1.490 + TUint aClientId = aRequest.ClientId();
1.491 + SPowerResourceClient* pC = NULL;
1.492 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.493 + if((TInt)aClientId != KDynamicResourceDeRegistering)
1.494 + {
1.495 + if(aClientId & USER_SIDE_CLIENT_BIT_MASK)
1.496 + pC = iUserSideClientList[TUint16(aClientId & ID_INDEX_BIT_MASK)];
1.497 + else
1.498 + pC = iClientList[TUint16(aClientId & ID_INDEX_BIT_MASK)];
1.499 + }
1.500 +#else
1.501 + if(aClientId & USER_SIDE_CLIENT_BIT_MASK)
1.502 + pC = iUserSideClientList[TUint16(aClientId & ID_INDEX_BIT_MASK)];
1.503 + else
1.504 + pC = iClientList[TUint16(aClientId & ID_INDEX_BIT_MASK)];
1.505 +#endif
1.506 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("Request Type = %d, ClientId = 0x%x, ResourceId = %d",
1.507 + aRequest.ReqType(), aRequest.ClientId(), aRequest.ResourceId()));
1.508 + if(aRequest.ReqType()==TPowerRequest::EChange)
1.509 + {
1.510 + if(pR->Usage()) //Handling shared resource
1.511 + {
1.512 + Lock(); //To avoid race condition between deregister resource level.
1.513 + aRequest.ReturnCode() = CheckLevelAndAddClient(pC, &aRequest);
1.514 + UnLock();
1.515 + if((aRequest.ReturnCode()!= KErrNone) || (!aRequest.RequiresChange()))
1.516 + {
1.517 + aRequest.Level() = pR->iCachedLevel; //If no change then send the current level back.
1.518 + CompleteRequest(aRequest);
1.519 + return;
1.520 + }
1.521 + }
1.522 + else if(pR->iLevelOwnerId ==-1) //No existing client.
1.523 + {
1.524 + // Add client Level
1.525 + if(pC->iReservedCl==0 && !iClientLevelPoolCount)
1.526 + {
1.527 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("Reserved Client Level exhausted and its free pool empty"));
1.528 + aRequest.ReturnCode() = KErrUnderflow;
1.529 + CompleteRequest(aRequest);
1.530 + return;
1.531 + }
1.532 + SPowerResourceClientLevel* pSCL=NULL;
1.533 + LIST_POP(iClientLevelPool, pSCL, iNextInList);
1.534 + pSCL->iClientId=aClientId;
1.535 + pSCL->iResourceId=aRequest.ResourceId();
1.536 + pSCL->iLevel=aRequest.Level();
1.537 + LIST_PUSH(pC->iLevelList, pSCL, iNextInList); //Add to client
1.538 + pR->iClientList.Add(pSCL); //Add in resource
1.539 + if(pC->iReservedCl==0)
1.540 + {
1.541 + iClientLevelPoolCount--;
1.542 + pC->iUnderFlowClCount++;
1.543 + }
1.544 + else
1.545 + pC->iReservedCl--;
1.546 + }
1.547 + else
1.548 + {
1.549 + //Update the level in the client list.
1.550 + SPowerResourceClientLevel* pSCL = (SPowerResourceClientLevel*)pR->iClientList.First();
1.551 + pSCL->iLevel = aRequest.Level();
1.552 + }
1.553 + }
1.554 + else if(aRequest.ReqType()==TPowerRequest::ESetDefaultLevel)
1.555 + {
1.556 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.557 + if((aRequest.ResourceId() & KIdMaskDynamic) && ((TInt)aClientId == KDynamicResourceDeRegistering))
1.558 + {
1.559 + //Try to change the resource to requested level and if that fails try to change it to default level
1.560 + if(pR->iDefaultLevel != aRequest.Level())
1.561 + {
1.562 + aRequest.ReqType() = TPowerRequest::EChange;
1.563 + aRequest.ReturnCode() = pR->DoRequest(aRequest);
1.564 + if(aRequest.ReturnCode() != KErrNone)
1.565 + {
1.566 + aRequest.ReqType() = TPowerRequest::ESetDefaultLevel;
1.567 + aRequest.Level() = pR->iDefaultLevel;
1.568 + pR->DoRequest(aRequest);
1.569 + }
1.570 + }
1.571 + else
1.572 + pR->DoRequest(aRequest);
1.573 + aRequest.ReturnCode() = KErrNone;
1.574 + aRequest.RequiresChange() = ETrue;
1.575 + CompleteRequest(aRequest);
1.576 + return;
1.577 + }
1.578 +#endif
1.579 + if(pR->Usage())
1.580 + {
1.581 + aRequest.ReturnCode() = CheckLevelAndAddClient(pC, &aRequest);
1.582 + if((aRequest.ReturnCode()!= KErrNone) || (!aRequest.RequiresChange()))
1.583 + {
1.584 + aRequest.Level() = pR->iCachedLevel; //If no change then send the current level back.
1.585 + CompleteRequest(aRequest);
1.586 + return;
1.587 + }
1.588 + }
1.589 + else
1.590 + {
1.591 + aRequest.ClientId() = -1;
1.592 + aRequest.Level() = pR->iDefaultLevel;
1.593 + }
1.594 + }
1.595 + if((aRequest.ReqType() == TPowerRequest::EGet) || (pR->iCachedLevel != aRequest.Level()))
1.596 + aRequest.ReturnCode() = pR->DoRequest(aRequest);
1.597 + CompleteRequest(aRequest);
1.598 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::HandleMsg"));
1.599 + }
1.600 +
1.601 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.602 +/** Handle/process the dependency resource.
1.603 + The request can be one of the following
1.604 + 1) State change of a dependency resource
1.605 + 2) Get the state of a dependency resource
1.606 + 3) Set the default value of a dependency resource */
1.607 +void DPowerResourceController::HandleDependencyMsg(TPowerRequest& aRequest)
1.608 + {
1.609 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::HandleDependencyMsg"));
1.610 + DStaticPowerResource* pR=aRequest.Resource();
1.611 + //Get client using client ID
1.612 + TUint aClientId = aRequest.ClientId();
1.613 + SPowerResourceClient* pC = NULL;
1.614 +
1.615 + if((TInt)aClientId != KDynamicResourceDeRegistering)
1.616 + {
1.617 + if(aClientId & USER_SIDE_CLIENT_BIT_MASK)
1.618 + pC = iUserSideClientList[TUint16(aClientId & ID_INDEX_BIT_MASK)];
1.619 + else
1.620 + pC = iClientList[TUint16(aClientId & ID_INDEX_BIT_MASK)];
1.621 + }
1.622 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("Request Type = %d, ClientId = 0x%x, ResourceId = %d",
1.623 + aRequest.ReqType(), aRequest.ClientId(), aRequest.ResourceId()));
1.624 + if((aRequest.ResourceId() & KIdMaskResourceWithDependencies) && (aRequest.ReqType() != TPowerRequest::EGet))
1.625 + {
1.626 + Lock();
1.627 + iDfcQDependencyLock = ETrue;
1.628 + UnLock();
1.629 + PowerResourceController->HandleDependencyResourceStateChange(pC, aRequest);
1.630 + Lock();
1.631 + iDfcQDependencyLock = EFalse;
1.632 + UnLock();
1.633 + return;
1.634 + }
1.635 + //Get the resource current level.
1.636 + aRequest.ReturnCode() = pR->DoRequest(aRequest);
1.637 + CompleteRequest(aRequest);
1.638 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::HandleDependencyMsg"));
1.639 + }
1.640 +#endif
1.641 +
1.642 +/** Function called whenever there is a message in resource controller message queue. */
1.643 +void DPowerResourceController::MsgQFunc(TAny* aPtr)
1.644 + {
1.645 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::MsgQFunc"));
1.646 + DPowerResourceController* pRC=(DPowerResourceController*)aPtr;
1.647 + TPowerRequest* aReq=(TPowerRequest*)pRC->iMsgQ->iMessage;
1.648 + DStaticPowerResource *pR = aReq->Resource();
1.649 + if(aReq->ReqType() == TPowerRequest::EAllocReserve)
1.650 + {
1.651 + aReq->ReturnCode() = pRC->HandleReservationOfObjects(*aReq);
1.652 + aReq->Complete(aReq->ReturnCode(),ETrue);
1.653 + return;
1.654 + }
1.655 + if((aReq->ReqType() == TPowerRequest::ERegisterKernelClient) || (aReq->ReqType() == TPowerRequest::ERegisterUsersideClient))
1.656 + {
1.657 + aReq->ReturnCode() = pRC->HandleClientRegistration(*aReq);
1.658 + aReq->Complete(aReq->ReturnCode(), ETrue);
1.659 + return;
1.660 + }
1.661 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.662 + if(aReq->ReqType() == TPowerRequest::ERegisterDynamicResource)
1.663 + {
1.664 + aReq->ReturnCode() = pRC->HandleResourceRegistration(*aReq);
1.665 + aReq->Complete(aReq->ReturnCode(), ETrue);
1.666 + return;
1.667 + }
1.668 +#endif
1.669 + pRC->HandleMsg(*aReq);
1.670 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.671 + if((aReq->ResourceId() & KIdMaskDynamic) && (aReq->ResourceCb()))
1.672 + {
1.673 + pRC->Lock();
1.674 + ((DDynamicPowerResource*)aReq->Resource())->UnLock();
1.675 + pRC->UnLock();
1.676 + }
1.677 +#endif
1.678 + //Below code is for Btrace
1.679 +#ifdef PRM_INSTRUMENTATION_MACRO
1.680 + SPowerResourceClient* pC = NULL;
1.681 + SPowerResourceClient tRes;
1.682 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.683 + if((aReq->ClientId() == -1) || (aReq->ClientId() == KDynamicResourceDeRegistering))
1.684 +#else
1.685 + if(aReq->ClientId() == -1)
1.686 +#endif
1.687 + {
1.688 + pC = &tRes;
1.689 + pC->iClientId = (TUint)-1;
1.690 + pC->iName = &KNoClient;
1.691 + }
1.692 + else if(aReq->ClientId() & USER_SIDE_CLIENT_BIT_MASK)
1.693 + pC = pRC->iUserSideClientList[TUint16(aReq->ClientId() & ID_INDEX_BIT_MASK)];
1.694 + else
1.695 + pC = pRC->iClientList[TUint16(aReq->ClientId() & ID_INDEX_BIT_MASK)];
1.696 +
1.697 + TUint aResourceId = aReq->ResourceId();
1.698 + TInt r = aReq->ReturnCode();
1.699 + if(aReq->ReqType()==TPowerRequest::EGet)
1.700 + {
1.701 + TInt aState = aReq->Level();
1.702 + PRM_RESOURCE_GET_STATE_END_TRACE
1.703 + }
1.704 + else
1.705 + {
1.706 + TInt aNewState = aReq->Level();
1.707 + PRM_CLIENT_CHANGE_STATE_END_TRACE
1.708 + }
1.709 +#endif
1.710 + //Check whether callback is cancelled and if not queue the DFC.
1.711 + TPowerResourceCb* pCb = aReq->ResourceCb();
1.712 + if(pCb)
1.713 + {
1.714 + pCb->iResult=aReq->ReturnCode();
1.715 + pCb->iLevel=aReq->Level();
1.716 + pCb->iResourceId=aReq->ResourceId();
1.717 + pCb->iClientId=aReq->ClientId();
1.718 + pCb->iLevelOwnerId = pR->iLevelOwnerId;
1.719 + pCb->Enque();
1.720 + }
1.721 + aReq->Complete(aReq->ReturnCode(),ETrue);
1.722 + if(aReq->ResourceCb())
1.723 + pRC->MoveRequestToFreePool(aReq);
1.724 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::MsgQFunc"));
1.725 + return;
1.726 + }
1.727 +
1.728 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.729 +/** Function called whenever there is a message in resource controller Dependency message queue. */
1.730 +void DPowerResourceController::MsgQDependencyFunc(TAny* aPtr)
1.731 + {
1.732 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::MsgQDependencyFunc"));
1.733 + DPowerResourceController* pRC=(DPowerResourceController*)aPtr;
1.734 + TPowerRequest* aReq=(TPowerRequest*)pRC->iMsgQDependency->iMessage;
1.735 + DStaticPowerResource *pR = aReq->Resource();
1.736 + pRC->HandleDependencyMsg(*aReq);
1.737 + if((aReq->ResourceId() & KIdMaskDynamic) && (aReq->ResourceCb()))
1.738 + {
1.739 + pRC->Lock();
1.740 + ((DDynamicPowerResource*)aReq->Resource())->UnLock();
1.741 + pRC->UnLock();
1.742 + }
1.743 + //Below code is for Btrace
1.744 +#ifdef PRM_INSTRUMENTATION_MACRO
1.745 + SPowerResourceClient* pC = NULL;
1.746 + SPowerResourceClient tRes;
1.747 + if((aReq->ClientId() != -1) && (aReq->ClientId() != KDynamicResourceDeRegistering) &&
1.748 + (aReq->ClientId() & KIdMaskResourceWithDependencies))
1.749 + {
1.750 + pC = &tRes;
1.751 + pC->iClientId = aReq->ClientId();
1.752 + DDynamicPowerResourceD* pDRes;
1.753 + if(aReq->ClientId() & KIdMaskDynamic)
1.754 + pDRes = pRC->iDynamicResDependencyList[(TUint16)(aReq->ClientId() & ID_INDEX_BIT_MASK)];
1.755 + else
1.756 + pDRes = (DDynamicPowerResourceD*)pRC->iStaticResDependencyArray[(aReq->ClientId() & ID_INDEX_BIT_MASK) - 1];
1.757 + pC->iName = pDRes->iName;
1.758 + }
1.759 + else if((aReq->ClientId() == -1) || (aReq->ClientId() == KDynamicResourceDeRegistering))
1.760 + {
1.761 + pC = &tRes;
1.762 + pC->iClientId = (TUint)-1;
1.763 + pC->iName = &KNoClient;
1.764 + }
1.765 + else if(aReq->ClientId() & USER_SIDE_CLIENT_BIT_MASK)
1.766 + pC = pRC->iUserSideClientList[TUint16(aReq->ClientId() & ID_INDEX_BIT_MASK)];
1.767 + else
1.768 + pC = pRC->iClientList[TUint16(aReq->ClientId() & ID_INDEX_BIT_MASK)];
1.769 +
1.770 + TUint aResourceId = aReq->ResourceId();
1.771 + TInt r = aReq->ReturnCode();
1.772 + if(aReq->ReqType()==TPowerRequest::EGet)
1.773 + {
1.774 + TInt aState = aReq->Level();
1.775 + PRM_RESOURCE_GET_STATE_END_TRACE
1.776 + }
1.777 + else
1.778 + {
1.779 + TInt aNewState = aReq->Level();
1.780 + PRM_CLIENT_CHANGE_STATE_END_TRACE
1.781 + }
1.782 +#endif
1.783 + //Check whether callback is cancelled and if not queue the DFC.
1.784 + TPowerResourceCb* pCb = aReq->ResourceCb();
1.785 + if(pCb)
1.786 + {
1.787 + pCb->iResult=aReq->ReturnCode();
1.788 + pCb->iLevel=aReq->Level();
1.789 + pCb->iResourceId=aReq->ResourceId();
1.790 + pCb->iClientId=aReq->ClientId();
1.791 + pCb->iLevelOwnerId = pR->iLevelOwnerId;
1.792 + pCb->Enque();
1.793 + }
1.794 + aReq->Complete(aReq->ReturnCode(),ETrue);
1.795 + if(aReq->ResourceCb())
1.796 + pRC->MoveRequestToFreePool(aReq);
1.797 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::MsgQDependencyFunc"));
1.798 + return;
1.799 + }
1.800 +#endif
1.801 +/** Function to move the request object to free pool and update client request count accordingly. */
1.802 +void DPowerResourceController::MoveRequestToFreePool(TPowerRequest *aReq)
1.803 + {
1.804 + //Return request to free pool
1.805 + SPowerRequest* pS=_LOFF(aReq, SPowerRequest, iRequest);
1.806 + Lock();
1.807 + LIST_PUSH(iRequestPool, pS, iNext);
1.808 + SPowerResourceClient* pC = NULL;
1.809 + if(aReq->ClientId() & USER_SIDE_CLIENT_BIT_MASK)
1.810 + pC = iUserSideClientList[TUint16(aReq->ClientId() & ID_INDEX_BIT_MASK)];
1.811 + else
1.812 + pC = iClientList[TUint16(aReq->ClientId() & ID_INDEX_BIT_MASK)];
1.813 + pC->iPendingReqCount--;
1.814 + if(pC->iUnderFlowRmCount > 0)
1.815 + {
1.816 + iRequestPoolCount++;
1.817 + pC->iUnderFlowRmCount--;
1.818 + }
1.819 + else
1.820 + pC->iReservedRm++;
1.821 + UnLock();
1.822 + return;
1.823 + }
1.824 +
1.825 +/** This function is called by PSL to set the DFC queue created */
1.826 +void DPowerResourceController::SetDfcQ(TDfcQue* aDfcQ)
1.827 + {
1.828 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::SetDfcQ"));
1.829 + iDfcQ=aDfcQ;
1.830 + iMsgQ->SetDfcQ(iDfcQ);
1.831 + }
1.832 +
1.833 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.834 +/** This function is called by PSL to set the DFC Dependency queue created */
1.835 +void DPowerResourceController::SetDfcQDependency(TDfcQue* aDfcQDependency)
1.836 + {
1.837 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::SetDfcQDependency"));
1.838 + iDfcQDependency=aDfcQDependency;
1.839 + iMsgQDependency->SetDfcQ(iDfcQDependency);
1.840 + }
1.841 +#endif
1.842 +/**This is called as a result of DFC queued in supervisor thread to complete the initialisation
1.843 + of resource controller.It registers the resource controller with the power controller. It also
1.844 + calls PSL (DoInitResources()) to initialise all static resources to their post-reboot state.
1.845 + Finally mark resource controller as fully initialised (ready to accept state change and get request)
1.846 + and start the message queue if exists. */
1.847 +TInt DPowerResourceController::InitResources()
1.848 + {
1.849 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::InitResources()"));
1.850 + TUint16 count;
1.851 + //Create a Kernel client object for Power Controller
1.852 + Lock();
1.853 + SPowerResourceClient * pC = NULL;
1.854 + // By now client pool should be created
1.855 + LIST_POP(iClientPool, pC, iNextInList);
1.856 + TUint16 growBy = iClientList.GrowBy();
1.857 + if(!pC)
1.858 + {
1.859 + UnLock();
1.860 + // coverity[alloc_fn]
1.861 + SPowerResourceClient *pCL = new SPowerResourceClient[growBy];
1.862 + if(!pCL)
1.863 + {
1.864 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("No memory to grow client pool"));
1.865 + Panic(ENoMemToCreatePowerControllerClient);
1.866 + }
1.867 +#ifdef RESOURCE_MANAGER_SIMULATED_PSL
1.868 + iCleanList.Append(pCL);
1.869 +#endif
1.870 + Lock();
1.871 + for(count = 0; count < growBy-1; count++)
1.872 + LIST_PUSH(iClientPool, &pCL[count], iNextInList);
1.873 + pC = &pCL[count];
1.874 +#ifdef PRM_INSTRUMENTATION_MACRO
1.875 + TUint size = growBy *sizeof(SPowerResourceClient);
1.876 + PRM_MEMORY_USAGE_TRACE
1.877 +#endif
1.878 + }
1.879 + pC->iName = (const TDesC8*)&KPowerController;
1.880 + UnLock();
1.881 + if(iClientList.Allocd()==iClientList.Count())
1.882 + {
1.883 + if(iClientList.ReSize(growBy))
1.884 + {
1.885 + Panic(ENoMemToCreatePowerControllerClient);
1.886 + }
1.887 + }
1.888 + Lock();
1.889 + iClientList.Add(pC, iPowerControllerId);
1.890 + pC->iClientId = iPowerControllerId | CLIENT_POWER_CONTROLLER_BIT_MASK;
1.891 + iPowerControllerId = pC->iClientId;
1.892 + iClientCount++;
1.893 + if(TPowerController::PowerController())
1.894 + TPowerController::PowerController()->RegisterResourceController(this, iPowerControllerId);
1.895 + iInitialised =EResConStartupCompleted;
1.896 + UnLock();
1.897 + //Check the resource for postboot level and send notifications to clients registered for it.
1.898 + DStaticPowerResource *pR = NULL;
1.899 + TInt r;
1.900 + TPowerRequest req = TPowerRequest::Get();
1.901 + //For Static resource with no dependencies
1.902 + for(count = 0; count< iStaticResourceArrayEntries; count++)
1.903 + {
1.904 + pR = iStaticResourceArray[count];
1.905 + if(pR && (pR->iFlags & SET_VALID_POST_BOOT_LEVEL))
1.906 + {
1.907 + //Form the request message
1.908 + req.ReqType() = TPowerRequest::EChange;
1.909 + req.ResourceId() = count+1;
1.910 + req.ClientId() = -1;
1.911 + req.Level() = pR->iPostBootLevel;
1.912 + req.Resource() = pR;
1.913 + req.ResourceCb() = NULL;
1.914 + req.RequiresChange() = ETrue;
1.915 + r = pR->DoRequest(req);
1.916 + if(r == KErrNone)
1.917 + {
1.918 + CompleteNotifications(-1, pR, req.Level(), r, -1, ETrue);
1.919 + pR->iCachedLevel = req.Level(); //Update the cached level.
1.920 + }
1.921 + }
1.922 + }
1.923 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.924 + //For Static resource with dependencies
1.925 + for(count = 0; count < iStaticResDependencyCount; count++)
1.926 + {
1.927 + pR = iStaticResDependencyArray[count];
1.928 + if(pR->iFlags & SET_VALID_POST_BOOT_LEVEL)
1.929 + {
1.930 + req.ReqType() = TPowerRequest::EChange;
1.931 + req.ResourceId() = ((DStaticPowerResourceD*)pR)->iResourceId;
1.932 + req.ClientId() = -1;
1.933 + req.Level() = pR->iPostBootLevel;
1.934 + req.Resource() = pR;
1.935 + req.ResourceCb() = NULL;
1.936 + req.RequiresChange() = ETrue;
1.937 + //Form the request message
1.938 + ((DStaticPowerResourceD*)pR)->HandleChangePropagation(req, EChangeStart, req.ClientId(), KNoClient);
1.939 + }
1.940 + }
1.941 +#endif
1.942 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::InitResources()"));
1.943 + return KErrNone;
1.944 + }
1.945 +
1.946 +/** @internalComponent
1.947 + This function is called for shared resources to determine level for the shared resource.
1.948 + This takes care of updating the resource level for each client.
1.949 +*/
1.950 +TInt DPowerResourceController::CheckLevelAndAddClient(SPowerResourceClient* pC, TPowerRequest* aReq)
1.951 + {
1.952 + //Client level addition in state change needs to be taken care.
1.953 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient, ClientId = 0x%x, ResourceId = %d, ReqType = %d",
1.954 + pC->iClientId, aReq->ResourceId(), aReq->ReqType()));
1.955 +
1.956 + SPowerResourceClientLevel* pSCL=NULL; //Place to hold the current client
1.957 + SPowerResourceClientLevel* pMCL=NULL; //Place to hold the prevailing client.
1.958 + DStaticPowerResource* aResource = aReq->Resource();
1.959 + aReq->RequiresChange() = EFalse;
1.960 + TInt maxLevel=KMinTInt;
1.961 + TInt CurrentLevel;
1.962 + TInt count = 0;
1.963 + //Get the nextmaximum, current client information.If the change is requested by client holding the prevailing
1.964 + //level of the resource then maxlevel will be next highest level with respect to sense. Otherwise will contain
1.965 + //the maximum level.
1.966 + SPowerResourceClientLevel* pL = NULL;
1.967 + for(SDblQueLink* pCL=aResource->iClientList.First();pCL!=&aResource->iClientList.iA;pCL=pCL->iNext,count++)
1.968 + {
1.969 + pL=(SPowerResourceClientLevel*)pCL;
1.970 + if(pL->iClientId == pC->iClientId)
1.971 + {
1.972 + pSCL=pL;
1.973 + if(aResource->Sense() == DStaticPowerResource::ECustom)
1.974 + break;
1.975 + continue;
1.976 + }
1.977 +
1.978 + if((count == 0) || ((pSCL != NULL) && (maxLevel == KMinTInt)))
1.979 + {
1.980 + maxLevel = pL->iLevel;
1.981 + pMCL = pL;
1.982 + continue;
1.983 + }
1.984 + if(((aResource->Sense() == DStaticPowerResource::ENegative) && (pL->iLevel < maxLevel)) ||
1.985 + ((aResource->Sense() == DStaticPowerResource::EPositive) && (pL->iLevel > maxLevel)))
1.986 + {
1.987 + maxLevel=pL->iLevel;
1.988 + pMCL = pL;
1.989 + }
1.990 + }
1.991 + //Get the current level.
1.992 + if(((TInt)pC->iClientId == aResource->iLevelOwnerId))
1.993 + // coverity[var_deref_op]
1.994 + CurrentLevel = pSCL->iLevel;
1.995 + else
1.996 + CurrentLevel = maxLevel;
1.997 +
1.998 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.999 + if(aResource->iLevelOwnerId & KIdMaskResourceWithDependencies)
1.1000 + {
1.1001 + CurrentLevel = aResource->iCachedLevel;
1.1002 + }
1.1003 +#endif
1.1004 + TBool newClient = EFalse;
1.1005 + if(!pSCL)
1.1006 + {
1.1007 + // If the client is new, get free client level from pool and populate with client information
1.1008 + // and add it to the client list and in resource list.
1.1009 + if((pC->iReservedCl ==0) && !iClientLevelPoolCount)
1.1010 + {
1.1011 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client level quota exhausted and its free pool empty, iReservedCl = %d, iClientLevelPoolCount = %d",
1.1012 + pC->iReservedCl, iClientLevelPoolCount));
1.1013 + return KErrUnderflow;
1.1014 + }
1.1015 + LIST_POP(iClientLevelPool, pSCL, iNextInList);
1.1016 + pSCL->iClientId=pC->iClientId;
1.1017 + pSCL->iResourceId=aReq->ResourceId();
1.1018 + pSCL->iLevel = aReq->Level();
1.1019 + //Add to the resource list
1.1020 + aResource->iClientList.Add(pSCL);
1.1021 + //Add to the client List
1.1022 + LIST_PUSH(pC->iLevelList, pSCL, iNextInList);
1.1023 + if(pC->iReservedCl == 0)
1.1024 + {
1.1025 + iClientLevelPoolCount--;
1.1026 + pC->iUnderFlowClCount++;
1.1027 + }
1.1028 + else
1.1029 + pC->iReservedCl--;
1.1030 + //If no client is holding the resource already and is not custom sense resource, then change is allowed
1.1031 + if((aResource->iLevelOwnerId == -1) && (aResource->Sense() != DStaticPowerResource::ECustom))
1.1032 + {
1.1033 + aReq->RequiresChange() = ETrue;
1.1034 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
1.1035 + return KErrNone;
1.1036 + }
1.1037 + if(aResource->Sense() == DStaticPowerResource::ECustom)
1.1038 + newClient = ETrue;
1.1039 + }
1.1040 + else
1.1041 + // Capture the new level requested by the client.
1.1042 + pSCL->iLevel=aReq->Level();
1.1043 +
1.1044 + if(aResource->Sense() == DStaticPowerResource::ECustom)
1.1045 + {
1.1046 +
1.1047 + if(!aResource->iCustomFunction)
1.1048 + Panic(ECustomFunctionNotSet);
1.1049 + // coverity[var_deref_op]
1.1050 + if(aReq->ReqType() == TPowerRequest::EChange)
1.1051 + {
1.1052 + aReq->RequiresChange() = aResource->iCustomFunction(aReq->ClientId(), *(pC->iName), aReq->ResourceId(),
1.1053 + newClient ? EClientRequestLevel : EClientChangeLevel,
1.1054 + aReq->Level(), (TAny*)&aResource->iClientList, NULL);
1.1055 + }
1.1056 + else
1.1057 + {
1.1058 + aReq->RequiresChange() = aResource->iCustomFunction(aReq->ClientId(), *(pC->iName), aReq->ResourceId(),
1.1059 + EClientRelinquishLevel,
1.1060 + aReq->Level(), (TAny*)&aResource->iClientList, NULL);
1.1061 + }
1.1062 + if((aReq->ClientId() != -1) && (aReq->ClientId() != (TInt)pC->iClientId) )
1.1063 + {
1.1064 + //Check whether the updated client Id (by custom function) is in the client level list.
1.1065 + for(SDblQueLink* pCL=aResource->iClientList.First();pCL!=&aResource->iClientList.iA;pCL=pCL->iNext)
1.1066 + {
1.1067 + pL = (SPowerResourceClientLevel*)pCL;
1.1068 + if((TInt)pL->iClientId == aReq->ClientId())
1.1069 + break;
1.1070 + }
1.1071 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.1072 + if(aReq->ClientId() & (1 << RESOURCE_BIT_IN_ID_CHECK))
1.1073 + {
1.1074 + if(aResource->iResourceId & KIdMaskDynamic)
1.1075 + pL = ((DDynamicPowerResourceD*)aResource)->iResourceClientList;
1.1076 + else
1.1077 + pL = ((DStaticPowerResourceD*)aResource)->iResourceClientList;
1.1078 + while(pL != NULL)
1.1079 + {
1.1080 + if((TInt)pL->iClientId == aReq->ClientId())
1.1081 + break;
1.1082 + }
1.1083 + }
1.1084 +#endif
1.1085 + // coverity[var_deref_op]
1.1086 + if((TInt)pL->iClientId != aReq->ClientId())
1.1087 + Panic(EClientIdNotInClientLevelList);
1.1088 + }
1.1089 + if(!aReq->RequiresChange() && (aReq->ClientId() != (TInt)pC->iClientId))
1.1090 + {
1.1091 + aResource->iLevelOwnerId=aReq->ClientId();
1.1092 + //Update resource details for Idle
1.1093 + if(aResource->iIdleListEntry)
1.1094 + aResource->iIdleListEntry->iLevelOwnerId=aReq->ClientId();
1.1095 + }
1.1096 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
1.1097 + return KErrNone;
1.1098 + }
1.1099 + //Handle client deregistration
1.1100 + if(aReq->ReqType() == TPowerRequest::ESetDefaultLevel)
1.1101 + {
1.1102 + aReq->RequiresChange() = ETrue;
1.1103 + // If the client is the only ask PSL to set to default level.
1.1104 + if(count == 1)
1.1105 + {
1.1106 + aReq->ReqType() = TPowerRequest::ESetDefaultLevel;
1.1107 + aReq->Level() = aResource->iDefaultLevel;
1.1108 + aReq->ClientId() = -1;
1.1109 + }
1.1110 + else
1.1111 + {
1.1112 + //Change the state to next maximum level with respect to sense.
1.1113 + aReq->ReqType() = TPowerRequest::EChange;
1.1114 + // coverity[var_deref_op]
1.1115 + aReq->ClientId() = pMCL->iClientId;
1.1116 + aReq->Level() = pMCL->iLevel;
1.1117 + if(pSCL->iLevel == pMCL->iLevel)
1.1118 + {
1.1119 + //Change the client alone and level remains the same.
1.1120 + aResource->iLevelOwnerId = pMCL->iClientId;
1.1121 + if(aResource->iIdleListEntry)
1.1122 + aResource->iIdleListEntry->iLevelOwnerId = pMCL->iClientId;
1.1123 + aReq->RequiresChange() = EFalse;
1.1124 + }
1.1125 + }
1.1126 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
1.1127 + return KErrNone;
1.1128 + }
1.1129 +
1.1130 + //If the level is in increasing order with respect to sense the change is allowed.
1.1131 + if(((aResource->Sense() == DStaticPowerResource::ENegative) && aReq->Level()<CurrentLevel) ||
1.1132 + ((aResource->Sense() == DStaticPowerResource::EPositive) && aReq->Level()>CurrentLevel))
1.1133 + {
1.1134 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("Resource is in increasing order with respect to sense and level is %d",
1.1135 + aReq->Level()));
1.1136 + aReq->RequiresChange()=ETrue;
1.1137 + return KErrNone;
1.1138 + }
1.1139 + if((TInt)pC->iClientId == aResource->iLevelOwnerId)
1.1140 + {
1.1141 + if(aReq->Level() == CurrentLevel)
1.1142 + {
1.1143 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
1.1144 + return KErrNone;
1.1145 + }
1.1146 + if(count == 1)
1.1147 + {
1.1148 + aReq->RequiresChange() = ETrue;
1.1149 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
1.1150 + return KErrNone;
1.1151 + }
1.1152 + // If the client requesting is the client holding current level, then chnage it to the nextmaximum level.
1.1153 + // Next maximum level is the max of requesting level or next maximum level.
1.1154 + if(((aResource->Sense()==DStaticPowerResource::ENegative) && maxLevel < aReq->Level()) ||
1.1155 + ((aResource->Sense()==DStaticPowerResource::EPositive) && maxLevel > aReq->Level()))
1.1156 + {
1.1157 + aReq->Level() = maxLevel;
1.1158 + aReq->ClientId() = pMCL->iClientId;
1.1159 + if(maxLevel == CurrentLevel)
1.1160 + {
1.1161 + aResource->iLevelOwnerId=pMCL->iClientId;
1.1162 + //Update resource details for Idle
1.1163 + if(aResource->iIdleListEntry)
1.1164 + aResource->iIdleListEntry->iLevelOwnerId=pMCL->iClientId;
1.1165 + aReq->RequiresChange() = EFalse;
1.1166 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
1.1167 + return KErrNone;
1.1168 + }
1.1169 + }
1.1170 + aReq->RequiresChange() = ETrue;
1.1171 + }
1.1172 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerResourceController::CheckLevelAndAddClient"));
1.1173 + return KErrNone;
1.1174 + }
1.1175 +
1.1176 +/**
1.1177 + Initialise pools of request structures, client strutures and client power level structures.
1.1178 + By preallocating sufficiently large structures we remove any allocations whilst the resource manager mutex is held.
1.1179 + The function basically ensures that sufficient memory is preallocated to the resource manager to ensure that none is
1.1180 + required at run time.
1.1181 + @param aKClients number of kernel side clients expected in the resource manager
1.1182 + @param aUClients number of user side clients expected in the resource manager
1.1183 + @param aNClientLevels number of client levels the RM should preallocate. This is roughly the number of clients
1.1184 + that are expected to use shared resources multiplied by the number of shared resources.
1.1185 + @param aNRequest number of simultaneous asynchronous requests the resource manager is likely to handle
1.1186 + @return KErrNone if preallocations succeed
1.1187 + @return KErrNoMemory if one the prealocations fails
1.1188 + */
1.1189 +TInt DPowerResourceController::InitPools(TUint16 aKClients, TUint16 aUClients, TUint16 aNClientLevels, TUint16 aNRequests)
1.1190 + {
1.1191 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::InitPools"));
1.1192 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("aKClients = %d, aUClients = %d, aNClientLevels = %d, aNRequests = %d",
1.1193 + aKClients, aUClients, aNClientLevels, aNRequests));
1.1194 + __ASSERT_ALWAYS((iInitialised == EResConCreated) && !(iClientPool || iRequestPool || iClientLevelPool), Kern::Fault("Already initialized"
1.1195 + __FILE__, __LINE__));
1.1196 +
1.1197 + // Create client pool
1.1198 + SPowerResourceClient* pC = NULL;
1.1199 + SPowerResourceClientLevel* pCL = NULL;
1.1200 + SPowerRequest* pR = NULL;
1.1201 + aKClients++; //Add one default for PowerController
1.1202 + if(aKClients + aUClients)
1.1203 + {
1.1204 + // coverity[alloc_fn]
1.1205 + pC = new SPowerResourceClient[aKClients+aUClients];
1.1206 + if(!pC)
1.1207 + {
1.1208 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client Pool Allocation Failed"));
1.1209 + return KErrNoMemory;
1.1210 + }
1.1211 + }
1.1212 + // Create Client level pool
1.1213 + if(aNClientLevels)
1.1214 + {
1.1215 + // coverity[alloc_fn]
1.1216 + pCL = new SPowerResourceClientLevel[aNClientLevels];
1.1217 + if(!pCL)
1.1218 + {
1.1219 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client Level Pool Allocation Failed"));
1.1220 + delete []pC;
1.1221 + return KErrNoMemory;
1.1222 + }
1.1223 + }
1.1224 + // Create Request pool
1.1225 + if(aNRequests)
1.1226 + {
1.1227 + // coverity[alloc_fn]
1.1228 + pR = new SPowerRequest[aNRequests];
1.1229 + if(!pR)
1.1230 + {
1.1231 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("Request Pool Allocation Failed"));
1.1232 + delete []pC;
1.1233 + delete []pCL;
1.1234 + return KErrNoMemory;
1.1235 + }
1.1236 + }
1.1237 + //Create the client Array for kernel and user side clients.
1.1238 + if(iClientList.Initialise(aKClients))
1.1239 + {
1.1240 + delete []pC;
1.1241 + delete []pCL;
1.1242 + delete []pR;
1.1243 + return KErrNoMemory;
1.1244 + }
1.1245 + if(iUserSideClientList.Initialise(aUClients))
1.1246 + {
1.1247 + delete []pC;
1.1248 + delete []pCL;
1.1249 + delete []pR;
1.1250 + iClientList.Delete();
1.1251 + return KErrNoMemory;
1.1252 + }
1.1253 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.1254 + SPowerResourceClientLevel* pRL = NULL;
1.1255 + if(iStaticResDependencyCount)
1.1256 + {
1.1257 + pRL = new SPowerResourceClientLevel[iStaticResDependencyCount];
1.1258 + if(!pRL)
1.1259 + {
1.1260 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("Resource level Pool Allocation Failed"));
1.1261 + delete []pC;
1.1262 + delete []pCL;
1.1263 + delete []pR;
1.1264 + iClientList.Delete();
1.1265 + iUserSideClientList.Delete();
1.1266 + return KErrNoMemory;
1.1267 + }
1.1268 + }
1.1269 +#ifdef RESOURCE_MANAGER_SIMULATED_PSL
1.1270 + iCleanList.Append(pC);
1.1271 +#endif
1.1272 + Lock();
1.1273 + TUint16 c;
1.1274 + for(c = 0; c < iStaticResDependencyCount; c++)
1.1275 + {
1.1276 + LIST_PUSH(iResourceLevelPool, &pRL[c], iNextInList);
1.1277 + }
1.1278 + iResourceLevelPoolCount = iStaticResDependencyCount;
1.1279 +#else
1.1280 +#ifdef RESOURCE_MANAGER_SIMULATED_PSL
1.1281 + iCleanList.Append(pC);
1.1282 +#endif
1.1283 + Lock();
1.1284 + TUint16 c;
1.1285 +#endif
1.1286 + // Create Client pool list
1.1287 + for(c = 0; c< (aKClients + aUClients); c++)
1.1288 + {
1.1289 + LIST_PUSH(iClientPool, &pC[c], iNextInList);
1.1290 + }
1.1291 + // Create client level pool list
1.1292 + for(c = 0; c < aNClientLevels; c++)
1.1293 + {
1.1294 + LIST_PUSH(iClientLevelPool, &pCL[c], iNextInList);
1.1295 + }
1.1296 + // Create request pool list
1.1297 + for(c = 0; c < aNRequests; c++)
1.1298 + {
1.1299 + LIST_PUSH(iRequestPool, &pR[c], iNext);
1.1300 + }
1.1301 + // When the pool is exhausted they are increased by half of initial size. */
1.1302 + iClientLevelPoolGrowBy=(TUint16)(aNClientLevels/2);
1.1303 + iRequestPoolGrowBy=(TUint16)(aNRequests/2);
1.1304 + // Initialise the free pool size
1.1305 + iClientLevelPoolCount=aNClientLevels;
1.1306 + iRequestPoolCount=aNRequests;
1.1307 +#ifdef PRM_INSTRUMENTATION_MACRO
1.1308 + TUint size = (((aKClients + aUClients)*sizeof(SPowerResourceClient)) +
1.1309 + (aNClientLevels * sizeof(SPowerResourceClientLevel)) + (aNRequests * sizeof(SPowerRequest)));
1.1310 + PRM_MEMORY_USAGE_TRACE
1.1311 +#endif
1.1312 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::InitPools"));
1.1313 + UNLOCK_RETURN(KErrNone);
1.1314 + }
1.1315 +
1.1316 +/**
1.1317 +@publishedPartner
1.1318 +@prototype 9.5
1.1319 +
1.1320 +Register a client with the Resource Manager.
1.1321 +
1.1322 +@param aClientId A reference to a client ID: returns a unique handle if registration was
1.1323 + successful, 0 otherwise.
1.1324 +@param aName Descriptor with name for client. The descriptor is created by the client
1.1325 + in kernel data space or its user address space.
1.1326 + NOTE: Name should ideally relate to component name and should take care
1.1327 + of name uniqueness as it is checked only if DEBUG_VERSION macro is enabled.
1.1328 +@param aType Defines ownership
1.1329 + EOwnerProcess - The client ID can be used by all thread in the process to
1.1330 + call the resource manager API's
1.1331 + EOwnerThread - The client ID can only be used by the thread that registered
1.1332 + the client to resource manager to call the PRM API's
1.1333 + By default this is set to EOwnerProcess.
1.1334 +
1.1335 +@return KErrNone if the operation was successful,
1.1336 + KErrNoMemory if a new client link was needed but could not be created and
1.1337 + added to the client list,
1.1338 + KErrTooBig if the length of the descriptor passed is greater than 32.
1.1339 + KErrAlreadyExists if the specified name already exists. This is valid only if
1.1340 + DEBUG_VERSION macro is enabled.
1.1341 + KErrNotSupported if number of expected kernel side clients is set to zero by
1.1342 + PSL.
1.1343 +
1.1344 +@pre Interrupts must be enabled.
1.1345 +@pre Kernel must be unlocked.
1.1346 +@pre No fast mutex can be held.
1.1347 +@pre Call in a thread context, but not from null thread or DFC thread1.
1.1348 +@pre Can be used in a device driver
1.1349 +*/
1.1350 +TInt DPowerResourceController::RegisterClient(TUint& aClientId, const TDesC8& aName, TOwnerType aType)
1.1351 + {
1.1352 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterClient, Name = %S, Type = %d", &aName, aType));
1.1353 + DThread& thread = Kern::CurrentThread();
1.1354 + CHECK_CONTEXT(thread)
1.1355 + //If number of expected kernel side clients is set to 0 during initial configuration
1.1356 + //then dont allow to configure kernel side clients.
1.1357 + if(!iClientList.GrowBy())
1.1358 + return KErrNotSupported;
1.1359 + if (aName.Length() > KMaxClientNameLength) return KErrTooBig;
1.1360 + SPowerResourceClient *pC = NULL;
1.1361 + Lock();
1.1362 +#ifdef DEBUG_VERSION
1.1363 + if(!iClientList.Find(pC, (TDesC8&)aName))
1.1364 + UNLOCK_RETURN(KErrAlreadyExists);
1.1365 +#endif
1.1366 + //Call from thread Id.
1.1367 + TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
1.1368 + req->ReqType() = TPowerRequest::ERegisterKernelClient;
1.1369 + UnLock();
1.1370 + req->SendReceive(iMsgQ);
1.1371 + if(req->ReturnCode() == KErrNone)
1.1372 + {
1.1373 + pC = iClientList[(TUint16)(req->ClientId() & ID_INDEX_BIT_MASK)];
1.1374 + if(aType == EOwnerThread)
1.1375 + {
1.1376 + pC->iClientId |= CLIENT_THREAD_RELATIVE_BIT_MASK; //Set 31st bit;
1.1377 + //Store the current thread Id;
1.1378 + pC->iThreadId = thread.iId;
1.1379 + }
1.1380 + pC->iName = &aName;
1.1381 + aClientId = pC->iClientId;
1.1382 + }
1.1383 + PRM_CLIENT_REGISTER_TRACE
1.1384 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterClient, clientId = 0x%x", aClientId));
1.1385 + return(req->ReturnCode());
1.1386 + }
1.1387 +
1.1388 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.1389 +TInt DPowerResourceController::HandleResourceRegistration(TPowerRequest& aReq)
1.1390 + {
1.1391 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::HandleResourceRegistration"));
1.1392 + DDynamicPowerResource* pDRes = (DDynamicPowerResource*)aReq.Resource();
1.1393 + //Add to appropriate container
1.1394 + if(pDRes->iResourceId & KIdMaskResourceWithDependencies)
1.1395 + ADD_TO_RESOURCE_CONTAINER(iDynamicResDependencyList, ((DDynamicPowerResourceD*)pDRes), aReq.ResourceId(),
1.1396 + iDynamicResDependencyCount)
1.1397 + else
1.1398 + ADD_TO_RESOURCE_CONTAINER(iDynamicResourceList, pDRes, aReq.ResourceId(), iDynamicResourceCount)
1.1399 +
1.1400 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::HandleResourceRegistration"));
1.1401 + return KErrNone;
1.1402 + }
1.1403 +#endif
1.1404 +
1.1405 +/**
1.1406 +@internalComponent
1.1407 +@prototype 9.5
1.1408 +
1.1409 +This function runs in the context of the RC thread and
1.1410 +handles registration of client (kernel and user side).
1.1411 +*/
1.1412 +TInt DPowerResourceController::HandleClientRegistration(TPowerRequest& aRequest)
1.1413 + {
1.1414 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterClient"));
1.1415 + SPowerResourceClient* pC = NULL;
1.1416 + TUint clientId;
1.1417 + if(aRequest.ReqType() == TPowerRequest::ERegisterKernelClient)
1.1418 + {
1.1419 + //Get Next client from FreePool
1.1420 + LIST_POP(iClientPool, pC, iNextInList);
1.1421 +
1.1422 + TUint16 growBy = iClientList.GrowBy();
1.1423 + if(!pC)
1.1424 + {
1.1425 + //Free Pool is empty, so try to grow the pool.
1.1426 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client pool exhausted so growing client Pool by %d", growBy));
1.1427 + // coverity[alloc_fn]
1.1428 + SPowerResourceClient *pCL = (SPowerResourceClient*)Kern::Alloc(sizeof(SPowerResourceClient) * growBy);
1.1429 + if(!pCL)
1.1430 + {
1.1431 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("No memory to grow client pool"));
1.1432 + return(KErrNoMemory);
1.1433 + }
1.1434 +#ifdef RESOURCE_MANAGER_SIMULATED_PSL
1.1435 + iCleanList.Append(pCL);
1.1436 +#endif
1.1437 + Lock();
1.1438 + TUint16 count;
1.1439 + for(count = 0; count < growBy-1; count++)
1.1440 + LIST_PUSH(iClientPool, &pCL[count], iNextInList);
1.1441 + UnLock();
1.1442 +#ifdef PRM_INSTRUMENTATION_MACRO
1.1443 + TUint size = growBy *sizeof(SPowerResourceClient);
1.1444 + PRM_MEMORY_USAGE_TRACE
1.1445 +#endif
1.1446 + pC = &pCL[count];
1.1447 + }
1.1448 + pC->iClientId = 0;
1.1449 + if(iClientList.Allocd()==iClientList.Count())
1.1450 + {
1.1451 + //Resize the container for holding client list
1.1452 + if(iClientList.ReSize(growBy)!=KErrNone)
1.1453 + {
1.1454 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("No memory for client container allocation"));
1.1455 + return(KErrNoMemory);
1.1456 + }
1.1457 + }
1.1458 + Lock();
1.1459 + iClientList.Add(pC, clientId);
1.1460 + ++iClientCount;
1.1461 + UnLock();
1.1462 + }
1.1463 + else // Request is registration of user side client
1.1464 + {
1.1465 + //Get Next client from FreePool
1.1466 + LIST_POP(iClientPool, pC, iNextInList);
1.1467 + TUint16 growBy = iUserSideClientList.GrowBy();
1.1468 + if(!pC)
1.1469 + {
1.1470 + //Free Pool is empty, so try to grow the pool.
1.1471 + SPowerResourceClient *pCL = (SPowerResourceClient*)Kern::Alloc(sizeof(SPowerResourceClient) * growBy);
1.1472 + if(!pCL)
1.1473 + {
1.1474 + return KErrNoMemory;
1.1475 + }
1.1476 +#ifdef RESOURCE_MANAGER_SIMULATED_PSL
1.1477 + iCleanList.Append(pCL);
1.1478 +#endif
1.1479 + Lock();
1.1480 + TUint16 count;
1.1481 + for(count = 0; count < growBy - 1; count++)
1.1482 + LIST_PUSH(iClientPool, &pCL[count], iNextInList);
1.1483 + UnLock();
1.1484 +#ifdef PRM_INSTRUMENTATION_MACRO
1.1485 + TUint size = growBy * sizeof(SPowerResourceClient);
1.1486 + PRM_MEMORY_USAGE_TRACE
1.1487 +#endif
1.1488 + pC = &pCL[count];
1.1489 + }
1.1490 + pC->iClientId = 0;
1.1491 + //User side clients are always thread relative as they execute in the context of proxy driver.
1.1492 + pC->iClientId = CLIENT_THREAD_RELATIVE_BIT_MASK; //Set 31st bit;
1.1493 + pC->iClientId|=USER_SIDE_CLIENT_BIT_MASK;
1.1494 + if(iUserSideClientList.Allocd()==iUserSideClientList.Count())
1.1495 + {
1.1496 + //Resize the container for holding client list
1.1497 + if(iUserSideClientList.ReSize(growBy)!=KErrNone)
1.1498 + {
1.1499 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("No memory for container class allocation"));
1.1500 + return KErrNoMemory;
1.1501 + }
1.1502 + }
1.1503 + Lock();
1.1504 + iUserSideClientList.Add(pC, clientId);
1.1505 + ++iUserSideClientCount;
1.1506 + UnLock();
1.1507 + }
1.1508 + //Create the unique handle for each client
1.1509 + //Client Handle format
1.1510 + // 31 30 18 16 15 14 13 0
1.1511 + // ¦----¦-----------------------------------¦----¦-----¦-----¦-----------------------------------¦
1.1512 + // ¦ T/P¦ Container's instance count(15 bits¦C/R ¦ PC ¦ K/U ¦ Index into Client array container ¦
1.1513 + // ¦----¦-----------------------------------¦----¦-----¦-----¦-----------------------------------¦
1.1514 + // T/P -> Thread / process relative
1.1515 + // PC -> Power Controller reserved ID.
1.1516 + // K/U -> Kernel / User side clients
1.1517 + // C/R -> Client / Resource Id. This bit will be set for dependency resource Id, zero for clientId.
1.1518 + pC->iLevelList = NULL;
1.1519 + pC->iNotificationList = NULL;
1.1520 + pC->iDynamicResCount = 0;
1.1521 + pC->iReservedCl = 0;
1.1522 + pC->iReservedRm = 0;
1.1523 + pC->iPendingReqCount = 0;
1.1524 + pC->iUnderFlowRmCount = 0;
1.1525 + pC->iUnderFlowClCount = 0;
1.1526 + pC->iClientId |= clientId;
1.1527 + aRequest.ClientId() = pC->iClientId;
1.1528 + return KErrNone;
1.1529 + }
1.1530 +
1.1531 +/** @internalComponent
1.1532 + @prototype 9.5
1.1533 + This is called as the result of client deregistration and takes care of resource state changes
1.1534 + (to appropriate levels) of all the resources the client is holding active requirement. */
1.1535 +void DPowerResourceController::ResourceStateChangeOfClientLevels(SPowerResourceClient* pC)
1.1536 + {
1.1537 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::ResourceStateChangeOfClientLevels"));
1.1538 + TPowerRequest* pReq = (TPowerRequest*)&TPowerRequest::Get();
1.1539 + DStaticPowerResource* pR = NULL;
1.1540 + SPowerResourceClientLevel* pCL = pC->iLevelList;
1.1541 + SPowerResourceClientLevel* pCLL = NULL;
1.1542 + while(pCL != NULL)
1.1543 + {
1.1544 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client 0x%x has requirement on resource %d", pCL->iClientId, pCL->iResourceId));
1.1545 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.1546 + switch((pCL->iResourceId >>RESOURCE_BIT_IN_ID_CHECK) & 0x3)
1.1547 + {
1.1548 + case PRM_STATIC_RESOURCE:
1.1549 + pR = iStaticResourceArray[pCL->iResourceId - 1];
1.1550 + break;
1.1551 + case PRM_DYNAMIC_RESOURCE:
1.1552 + pR = (iDynamicResourceList[(TUint16)(pCL->iResourceId & ID_INDEX_BIT_MASK)]);
1.1553 + break;
1.1554 + case PRM_STATIC_DEPENDENCY_RESOURCE:
1.1555 + pR = (iStaticResDependencyArray[(TUint16)(pCL->iResourceId & ID_INDEX_BIT_MASK) - 1]);
1.1556 + break;
1.1557 + case PRM_DYNAMIC_DEPENDENCY_RESOURCE:
1.1558 + pR = (iDynamicResDependencyList[(TUint16)(pCL->iResourceId & ID_INDEX_BIT_MASK)]);
1.1559 + break;
1.1560 + }
1.1561 +#else
1.1562 + pR = iStaticResourceArray[pCL->iResourceId -1];
1.1563 +#endif
1.1564 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.1565 + if(((pR->Sense() == DStaticPowerResource::ECustom) || ((TInt)pCL->iClientId == pR->iLevelOwnerId)) && (!(pCL->iResourceId & KIdMaskDynamic) ||
1.1566 + ((pCL->iResourceId & KIdMaskDynamic) && (((DDynamicPowerResource*)pR)->LockCount() != 0))))
1.1567 +#else
1.1568 + if((pR->Sense() == DStaticPowerResource::ECustom) || ((TInt)pCL->iClientId == pR->iLevelOwnerId))
1.1569 +#endif
1.1570 + {
1.1571 + pReq->ReqType() = TPowerRequest::ESetDefaultLevel;
1.1572 + pReq->ResourceId() = pCL->iResourceId;
1.1573 + pReq->ClientId() = pCL->iClientId;
1.1574 + pReq->Resource() = pR;
1.1575 + pReq->Level() = pR->iCachedLevel;
1.1576 + pReq->ResourceCb() = NULL;
1.1577 + pReq->ReturnCode() = KErrNone;
1.1578 +#ifdef PRM_INSTRUMENTATION_MACRO
1.1579 + //Setting level to current level as correct level will be known only at the end,
1.1580 + TInt aNewState = pR->iCachedLevel;
1.1581 + TUint aResourceId = pReq->ResourceId();
1.1582 + PRM_CLIENT_CHANGE_STATE_START_TRACE
1.1583 +#endif
1.1584 + TInt r = KErrNone;
1.1585 + if(pR->LatencySet())
1.1586 + {
1.1587 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.1588 + if(pCL->iResourceId & KIdMaskDynamic)
1.1589 + ((DDynamicPowerResource*)pR)->Lock();
1.1590 +#endif
1.1591 + UnLock();
1.1592 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.1593 + if(pR->iResourceId & KIdMaskResourceWithDependencies) //Dependency resource
1.1594 + r = pReq->SendReceive(iMsgQDependency);
1.1595 + else
1.1596 +#endif
1.1597 + r = pReq->SendReceive(iMsgQ);
1.1598 + Lock();
1.1599 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.1600 + if(pCL->iResourceId & KIdMaskDynamic)
1.1601 + ((DDynamicPowerResource*)pR)->UnLock();
1.1602 +#endif
1.1603 + }
1.1604 + else
1.1605 + {
1.1606 + if(pR->Usage())
1.1607 + {
1.1608 + //Not checking return value as there is no memory allocation at this point
1.1609 + CheckLevelAndAddClient(pC, pReq);
1.1610 + }
1.1611 + else
1.1612 + {
1.1613 + pReq->ClientId() = -1;
1.1614 + pReq->Level() = pR->iDefaultLevel;
1.1615 + }
1.1616 +
1.1617 + if((!pR->Usage()) || (pR->Usage() && pReq->RequiresChange()))
1.1618 + {
1.1619 + // NOTE:Not checking error here as no action can be taken based on error.
1.1620 + if(pR->iCachedLevel != pReq->Level())
1.1621 + {
1.1622 + UnLock();
1.1623 + r = pR->DoRequest(*pReq);
1.1624 + Lock();
1.1625 + }
1.1626 + CompleteNotifications(pReq->ClientId(), pReq->Resource(), pReq->Level(),
1.1627 + pReq->ReturnCode(), pReq->ClientId(), EFalse);
1.1628 +#ifdef PRM_INSTRUMENTATION_MACRO
1.1629 + PRM_CLIENT_CHANGE_STATE_END_TRACE
1.1630 +#endif
1.1631 + pR->iLevelOwnerId = pReq->ClientId();
1.1632 + pR->iCachedLevel = pReq->Level();
1.1633 + if(pR->iIdleListEntry)
1.1634 + {
1.1635 + SIdleResourceInfo* pI = (SIdleResourceInfo*)pR->iIdleListEntry;
1.1636 + pI->iLevelOwnerId = pReq->ClientId();
1.1637 + pI->iCurrentLevel = pReq->Level();
1.1638 + }
1.1639 + }
1.1640 + }
1.1641 +
1.1642 + }
1.1643 + /* Deque from resource */
1.1644 + pCLL = pCL;
1.1645 + pCL = pCL->iNextInList;
1.1646 + pCLL->Deque();
1.1647 + iClientLevelPoolCount++;
1.1648 + LIST_PUSH(iClientLevelPool,pCLL,iNextInList); // back to free pool
1.1649 + }
1.1650 + pC->iLevelList = NULL;
1.1651 + //Add reserved client level to free pool
1.1652 + iClientLevelPoolCount = (TUint16)(iClientLevelPoolCount + (TUint16)pC->iReservedCl);
1.1653 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::ResourceStateChangeOfClientLevels"));
1.1654 + }
1.1655 +
1.1656 +/**
1.1657 +@publishedPartner
1.1658 +@prototype 9.5
1.1659 +
1.1660 +Deregister a client with the resource manager
1.1661 +
1.1662 +@param aClientId The ID of the client which is being deregistered
1.1663 +
1.1664 +@return KErrNone if the operation was successful
1.1665 + KErrNotFound if this client ID could not be found in the current
1.1666 + list of clients
1.1667 + KErrArgument if user side client Id is specified or client ID to be used
1.1668 + by Power Controller is specified.
1.1669 + KErrAccessDenied if client was registered to be thread relative and this
1.1670 + API is not called from the same thread.
1.1671 +
1.1672 +@pre Interrupts must be enabled
1.1673 +@pre Kernel must be unlocked
1.1674 +@pre No fast mutex can be held
1.1675 +@pre Call in a thread context but not from null thread or DFC thread1
1.1676 +@pre Can be used in a device driver
1.1677 +*/
1.1678 +TInt DPowerResourceController::DeRegisterClient(TUint aClientId)
1.1679 + {
1.1680 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::DeRegisterClient, ClientId = 0x%x", aClientId));
1.1681 + DThread& thread = Kern::CurrentThread();
1.1682 + CHECK_CONTEXT(thread)
1.1683 + if((aClientId & USER_SIDE_CLIENT_BIT_MASK) || (aClientId == iPowerControllerId))
1.1684 + return KErrArgument;
1.1685 + //Get the index from client ID
1.1686 + Lock();
1.1687 + SPowerResourceClient* pC = iClientList[(TUint16)(aClientId & ID_INDEX_BIT_MASK)];
1.1688 + if(!pC)
1.1689 + {
1.1690 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client ID not Found"));
1.1691 + UNLOCK_RETURN(KErrNotFound);
1.1692 + }
1.1693 + if(pC->iClientId != aClientId)
1.1694 + {
1.1695 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client ID does not match"));
1.1696 + UNLOCK_RETURN(KErrNotFound);
1.1697 + }
1.1698 + if(pC->iClientId & CLIENT_THREAD_RELATIVE_BIT_MASK)
1.1699 + {
1.1700 + if(pC->iThreadId != thread.iId)
1.1701 + {
1.1702 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client not called from thread context(Thread Relative)"));
1.1703 + UNLOCK_RETURN(KErrAccessDenied);
1.1704 + }
1.1705 + }
1.1706 + //Check for any pending request
1.1707 + if(pC->iPendingReqCount)
1.1708 + {
1.1709 + UnLock();
1.1710 + Panic(EClientHasPendingAsyncRequest);
1.1711 + }
1.1712 + //Check for notification request
1.1713 + if(pC->iNotificationList)
1.1714 + {
1.1715 + UnLock();
1.1716 + Panic(EClientHasNotificationObject);
1.1717 + }
1.1718 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.1719 + if(pC->iDynamicResCount)
1.1720 + {
1.1721 + UnLock();
1.1722 + Panic(DPowerResourceController::EClientHasDynamicResourceRegistered);
1.1723 + }
1.1724 +#endif
1.1725 + //Check for registration of dynamic resource
1.1726 + ResourceStateChangeOfClientLevels(pC);
1.1727 + // Add reserved request to pool
1.1728 + iRequestPoolCount = (TUint16)(iRequestPoolCount + (TUint16)pC->iReservedRm);
1.1729 + PRM_CLIENT_DEREGISTER_TRACE
1.1730 + //Increment the free pool count for client level and request level.
1.1731 + iClientList.Remove(pC, (TUint16)(pC->iClientId & ID_INDEX_BIT_MASK));
1.1732 + pC->iName = NULL;
1.1733 + iClientCount--; //Decrement client count
1.1734 + LIST_PUSH(iClientPool, pC, iNextInList);
1.1735 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::DeRegisterClient"));
1.1736 + UNLOCK_RETURN(KErrNone);
1.1737 + }
1.1738 +
1.1739 +/**
1.1740 +@publishedPartner
1.1741 +@prototype 9.5
1.1742 +
1.1743 +Obtain the name of a registered client of the resource manager
1.1744 +
1.1745 +@param aClientId The ID of the client which is requesting the name of
1.1746 + another client whose ID is specified in aTargetClientId.
1.1747 +@param aTargetClientId The ID of the client whose name is being requested.
1.1748 +@param aName Descriptor to be filled with the name of the client. The descriptor
1.1749 + is created by the client in kernel stack or heap.
1.1750 +
1.1751 +@return KErrNone if the operation was successful
1.1752 + KErrNotFound if this client ID (aTargetClientId) could not be
1.1753 + found in the current list of registered clients.
1.1754 + KErrAccessDenied if the client ID (aClientId) could not be found
1.1755 + in the current list of registered clients or if client was registered
1.1756 + to be thread relative and this API is not called from the same thread.
1.1757 + KErrArgument if size of aName is less than 32.
1.1758 +
1.1759 +@pre Interrupts must be enabled
1.1760 +@pre Kernel must be unlocked
1.1761 +@pre No fast mutex can be held
1.1762 +@pre Call in a thread context but not from null thread or DFC thread1
1.1763 +@pre Can be used in a device driver
1.1764 +*/
1.1765 +TInt DPowerResourceController::GetClientName(TUint aClientId, TUint aTargetClientId, TDes8& aName)
1.1766 + {
1.1767 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetClientName, CallingClientId = 0x%x, TargetClientId = 0x%x", aClientId, aTargetClientId));
1.1768 + DThread& thread = Kern::CurrentThread();
1.1769 + CHECK_CONTEXT(thread)
1.1770 + if((aName.MaxLength() - aName.Length()) < KMaxClientNameLength)
1.1771 + return KErrArgument;
1.1772 + SPowerResourceClient* pC = NULL;
1.1773 + Lock();
1.1774 + VALIDATE_CLIENT(thread);
1.1775 + GET_TARGET_CLIENT();
1.1776 + aName.Append(*pC->iName);
1.1777 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetClientName, ClientName = %S", &aName));
1.1778 + UNLOCK_RETURN(KErrNone);
1.1779 + }
1.1780 +
1.1781 +/**
1.1782 +@publishedPartner
1.1783 +@prototype 9.5
1.1784 +
1.1785 +Obtain the Id of registered client of the resource manager
1.1786 +
1.1787 +@param aClientId ID of the client which is requesting the ID of the another
1.1788 + client whose name is specified in aClientName
1.1789 +@param aClientName Descriptor containing the name of the client whose ID is being
1.1790 + requested. The client must create the descriptor in kernel stack
1.1791 + or heap.
1.1792 + NOTE: Resource manager does not check for uniqueness of client
1.1793 + name during registration, so if there are multiple clients registered
1.1794 + to PRM with same name it will return the ID of the first client it encounters.
1.1795 +@param aTargetClientId Updates with ID of the requested client on success
1.1796 +
1.1797 +@return KErrNone if the operation was successful
1.1798 + KErrNotFound if this client name could not be found in the current list of registered
1.1799 + client
1.1800 + KErrAccessDenied if the client ID (aClientId) could not be found in the current
1.1801 + list of registered client or if the client was registered to be
1.1802 + thread relative and this API is not called from the same thread.
1.1803 + KErrTooBig if the length of the descriptor passed is greater than 32.
1.1804 +
1.1805 +@pre Interrupts must be enabled
1.1806 +@pre Kernel must be unlocked
1.1807 +@pre No fast mutex can be held
1.1808 +@pre Call in a thread context but not from null thread or DFC thread1
1.1809 +@pre Can be used in a device driver
1.1810 +*/
1.1811 +TInt DPowerResourceController::GetClientId(TUint aClientId, TDesC8& aClientName, TUint& aTargetClientId)
1.1812 + {
1.1813 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetClientId CallingClientId = 0x%x, ClientName = %S", aClientId, &aClientName));
1.1814 + DThread& thread = Kern::CurrentThread();
1.1815 + CHECK_CONTEXT(thread)
1.1816 + if(aClientName.Length() > KMaxClientNameLength)
1.1817 + return KErrTooBig;
1.1818 + SPowerResourceClient* pC = NULL;
1.1819 + Lock();
1.1820 + VALIDATE_CLIENT(thread);
1.1821 + //Find the client ID with the specified name first from kernel client list & then user side.
1.1822 + if(iClientList.Find(pC, aClientName) && iUserSideClientList.Find(pC, aClientName))
1.1823 + UNLOCK_RETURN(KErrNotFound);
1.1824 + aTargetClientId = pC->iClientId;
1.1825 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetClientId TargetClientId = 0x%x", aTargetClientId));
1.1826 + UNLOCK_RETURN(KErrNone);
1.1827 + }
1.1828 +
1.1829 +/**
1.1830 +@publishedPartner
1.1831 +@prototype 9.5
1.1832 +
1.1833 +Obtain the ID of registered resource of the resource manager.
1.1834 +NOTE: ID of the first matching name found in the resource list will be returned
1.1835 +
1.1836 +@param aClientId ID of the client which is requesting the ID of the
1.1837 + resource, by specifying its name.
1.1838 +@param aResourceName Descriptor containing the name of the resource whose
1.1839 + ID is being requested.
1.1840 +@param aResourceId Updates with ID of the requested resource on success
1.1841 +
1.1842 +@return KErrNone if the operation was successful
1.1843 + KErrAccessDenied if the ID of the client could not be found in the
1.1844 + current list of registered clients or if the client was
1.1845 + registered to be thread relative and this API is not called
1.1846 + from the same thread.
1.1847 + KErrNotFound if this resource name could not be found in the current
1.1848 + list of registered resources.
1.1849 + KErrTooBig if the length of the descriptor passed is greater than maximum
1.1850 + allowable resource name length (32).
1.1851 +@pre Interrupts must be enabled
1.1852 +@pre Kernel must be unlocked
1.1853 +@pre No fast mutex can be held
1.1854 +@pre Call in a thread context but not from null thread or DFC thread1
1.1855 +@pre Can be used in a device driver
1.1856 +*/
1.1857 +TInt DPowerResourceController::GetResourceId(TUint aClientId, TDesC8& aResourceName, TUint& aResourceId)
1.1858 + {
1.1859 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetResourceId"));
1.1860 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("CallingClientId = 0x%x, ResourceName = %S", aClientId, &aResourceName));
1.1861 + DThread& thread = Kern::CurrentThread();
1.1862 + CHECK_CONTEXT(thread)
1.1863 + SPowerResourceClient* pC;
1.1864 + if(aResourceName.Length() > KMaxResourceNameLength)
1.1865 + return KErrTooBig;
1.1866 + Lock();
1.1867 + VALIDATE_CLIENT(thread);
1.1868 + TUint count = 0;
1.1869 + //Search in static resource with no dependencies array for specified resource name.
1.1870 + for(count = 0; count < iStaticResourceArrayEntries; count++)
1.1871 + {
1.1872 + if((iStaticResourceArray[count]) && (!(aResourceName.Compare(*(const TDesC8*)iStaticResourceArray[count]->iName))))
1.1873 + {
1.1874 + aResourceId = ++count;
1.1875 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetResourceId, ResourceId = 0x%x", aResourceId));
1.1876 + UNLOCK_RETURN(KErrNone);
1.1877 + }
1.1878 + }
1.1879 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.1880 + //Search in dynamic resource with no dependencies array for specified resource name.
1.1881 + DDynamicPowerResource* pDR = NULL;
1.1882 + if(PowerResourceController->iDynamicResourceCount &&
1.1883 + !PowerResourceController->iDynamicResourceList.Find(pDR, aResourceName))
1.1884 + {
1.1885 + aResourceId = pDR->iResourceId;
1.1886 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetResourceId, ResourceId = 0x%x", aResourceId));
1.1887 + UNLOCK_RETURN(KErrNone);
1.1888 + }
1.1889 + //Search in static resource with dependencies (if exists) for specified resource name
1.1890 + for(count = 0; count < iStaticResDependencyCount; count++)
1.1891 + {
1.1892 + if(!(aResourceName.Compare(*(const TDesC8*)iStaticResDependencyArray[count]->iName)))
1.1893 + {
1.1894 + aResourceId = iStaticResDependencyArray[count]->iResourceId;
1.1895 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetResourceId, ResourceId = 0x%x", aResourceId));
1.1896 + UNLOCK_RETURN(KErrNone);
1.1897 + }
1.1898 + }
1.1899 + //Search in dynamic resource with dependencies (if exists) for specified resource name
1.1900 + DDynamicPowerResourceD* pDRD;
1.1901 + if(iDynamicResDependencyCount && !iDynamicResDependencyList.Find(pDRD, aResourceName))
1.1902 + {
1.1903 + aResourceId = pDRD->iResourceId;
1.1904 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetResourceId, ResourceId = 0x%x", aResourceId));
1.1905 + UNLOCK_RETURN(KErrNone);
1.1906 + }
1.1907 +#endif
1.1908 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetResourceId, ResourceID not found"));
1.1909 + UNLOCK_RETURN(KErrNotFound);
1.1910 + }
1.1911 +
1.1912 +/**
1.1913 +@publishedPartner
1.1914 +@prototype 9.5
1.1915 +
1.1916 +Request a structure containing information on a resource.
1.1917 +
1.1918 +@param aClientId ID of the client which is requesting the resource information
1.1919 +@param aResourceId ID of the resource whose information is being requested.
1.1920 +@param aInfo A pointer to descriptor containing resource information
1.1921 + structure (TPowerResourceInfoV01) to be filled in
1.1922 + with the requested resource information. The client must
1.1923 + create the descriptor in kernel stack or heap.
1.1924 +
1.1925 +@return KErrNone if the operation was successful
1.1926 + KErrAccessDenied if the client ID could not be found in the current list
1.1927 + of registered clients or if the client was registered to be
1.1928 + thread relative and this API is not called from the same thread.
1.1929 + KErrNotFound if this resource ID could not be found in the current list
1.1930 + of controllable resource.
1.1931 + KErrArgument if aInfo is NULL or size of descriptor passed is less than size of
1.1932 + TPowerResourceInfoV01.
1.1933 +@pre Interrupts must be enabled
1.1934 +@pre Kernel must be unlocked
1.1935 +@pre No fast mutex can be held
1.1936 +@pre Call in a thread context but not from null thread or DFC thread1
1.1937 +@pre Can be used in a device driver
1.1938 +*/
1.1939 +TInt DPowerResourceController::GetResourceInfo(TUint aClientId, TUint aResourceId, TAny* aInfo)
1.1940 + {
1.1941 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetResourceInfo"));
1.1942 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("CallingClientId = 0x%x, ResourceId = %d", aClientId, aResourceId));
1.1943 + DThread& thread = Kern::CurrentThread();
1.1944 + CHECK_CONTEXT(thread)
1.1945 + if(!aInfo)
1.1946 + return KErrArgument;
1.1947 + SPowerResourceClient* pC = NULL;
1.1948 + Lock();
1.1949 + VALIDATE_CLIENT(thread);
1.1950 + TDes8* buf = (TDes8*)aInfo;
1.1951 + TInt r = KErrNone;
1.1952 + DStaticPowerResource *pR = NULL;
1.1953 +
1.1954 + //Validate buffer size
1.1955 + if((TUint)(buf->MaxLength() - buf->Length()) < sizeof(TPowerResourceInfoV01))
1.1956 + UNLOCK_RETURN(KErrArgument);
1.1957 +
1.1958 +#ifndef PRM_ENABLE_EXTENDED_VERSION
1.1959 + if((!aResourceId) || (aResourceId > iStaticResourceArrayEntries))
1.1960 + UNLOCK_RETURN(KErrNotFound);
1.1961 + //Get resource from static resource array. 0(1) operation.
1.1962 + pR = iStaticResourceArray[aResourceId-1];
1.1963 + if(!pR)
1.1964 + {
1.1965 + UNLOCK_RETURN(KErrNotFound);
1.1966 + }
1.1967 +#else
1.1968 + if(!aResourceId)
1.1969 + {
1.1970 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetResourceInfo, return value = %d", KErrNotFound));
1.1971 + UNLOCK_RETURN(KErrNotFound);
1.1972 + }
1.1973 + //Get resource from corresponding container
1.1974 + GET_RESOURCE_FROM_LIST(aResourceId, pR)
1.1975 +#endif
1.1976 + //Update resource info
1.1977 + TPowerResourceInfoBuf01 infoBuf;
1.1978 + r = pR->GetInfo((TDes8*)infoBuf.Ptr());
1.1979 + //Update ResourceId
1.1980 + ((TPowerResourceInfoV01*)infoBuf.Ptr())->iResourceId = aResourceId;
1.1981 + if(r == KErrNone)
1.1982 + buf->Append(infoBuf);
1.1983 + UNLOCK_RETURN(r);
1.1984 + }
1.1985 +
1.1986 +/**
1.1987 +@publishedPartner
1.1988 +@prototype 9.5
1.1989 +
1.1990 +Request number of resources the specified client (aTargetClientId) has
1.1991 +requirement on resource level. Client ID starts from 1, so if 0 is specified in
1.1992 +aTargetClientId, returns the number of controllable resources registered with PRM.
1.1993 +
1.1994 +@param aClientId ID of the client which is requesting the number of resources
1.1995 + the specified client (aTargetClientId) holds requirement on
1.1996 + resource level change.
1.1997 +@param aTargetClientId ID of the client. The number of resources on which it
1.1998 + has requirement on resource level change is requested.
1.1999 +@param aNumResource Updated with the number of resources the specified client
1.2000 + has requirement on resource level change, if valid client
1.2001 + ID is passed. If client ID is 0, updates the total number
1.2002 + of resources registered with resource manager.
1.2003 +
1.2004 +@return KErrNone if the operation was successful.
1.2005 + KErrAccessDenied if the client ID (aClientId) could not be found in the
1.2006 + current list of registered clients or if the client was registered
1.2007 + to be thread relative and this API is not called from the same thread.
1.2008 + KErrNotFound if the client ID (aTargetClientId) could not be found in the
1.2009 + current list of registered clients and is not 0.
1.2010 +
1.2011 +@pre Interrupts must be enabled
1.2012 +@pre Kernel must be unlocked
1.2013 +@pre No fast mutex can be held
1.2014 +@pre Call in a thread context but not from null thread or DFC thread1
1.2015 +@pre Can be used in a device driver
1.2016 +*/
1.2017 +TInt DPowerResourceController::GetNumResourcesInUseByClient(TUint aClientId, TUint aTargetClientId, TUint& aNumResource)
1.2018 + {
1.2019 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetNumResourcesInUseByClient"));
1.2020 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("CallingClientId = 0x%x, TargetClientId = 0x%x", aClientId, aTargetClientId));
1.2021 + DThread& thread = Kern::CurrentThread();
1.2022 + CHECK_CONTEXT(thread)
1.2023 + SPowerResourceClient* pC = NULL;
1.2024 + Lock();
1.2025 + VALIDATE_CLIENT(thread);
1.2026 + //Special case, return number of resources registered resource controller.
1.2027 + if(!aTargetClientId)
1.2028 + {
1.2029 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2030 + aNumResource = iStaticResourceCount + iDynamicResourceCount + iStaticResDependencyCount +
1.2031 + iDynamicResDependencyCount;
1.2032 +#else
1.2033 + aNumResource = iStaticResourceCount;
1.2034 +#endif
1.2035 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetNumResourcesInUseByClient, numResources = %d", aNumResource));
1.2036 + UNLOCK_RETURN(KErrNone);
1.2037 + }
1.2038 + GET_TARGET_CLIENT();
1.2039 + SPowerResourceClientLevel* pCL = pC->iLevelList;
1.2040 + aNumResource = 0;
1.2041 + while(pCL)
1.2042 + {
1.2043 + aNumResource++;
1.2044 + pCL = pCL->iNextInList;
1.2045 + }
1.2046 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetNumResourcesInUseByClient, numResources = %d", aNumResource));
1.2047 + UNLOCK_RETURN(KErrNone);
1.2048 + }
1.2049 +
1.2050 +/**
1.2051 +@publishedPartner
1.2052 +@prototype 9.5
1.2053 +
1.2054 +Request information on resources.
1.2055 +If client ID (aTargetClientId) is valid, aInfo is updated with the information of the resources
1.2056 +this client hold requirement on the resource level.
1.2057 +If client ID (aTargetClientId) is 0, aInfo is updated with the information of the resources
1.2058 +registered with resource controller.
1.2059 +Number of resource information updated will be equal or less than the number specified in aNumResources.
1.2060 +
1.2061 +@param aClientId ID of the client which is requesting the resource information.
1.2062 +@param aTargetClientId ID of the client. The information of all the resources on
1.2063 + which it has requirement on resource level change is requested.
1.2064 + Client ID starts from 1, so calling this API with client ID 0 will
1.2065 + fill the details of all the controllable resource registered with
1.2066 + resource manager.
1.2067 +@param aNumResources Number of resource whose information needs to be filled in aInfo i.e,
1.2068 + it specifies the size of aInfo array.
1.2069 +@param aInfo A pointer to an array of descriptor containing an information structure
1.2070 + (TPowerResourceInfoV01) to be filled in with the information
1.2071 + on the resources. It will be assumed that array allocated will be equal
1.2072 + to the number passed in aNumResources. The client must create the array
1.2073 + in Kernel stack or heap.
1.2074 +
1.2075 +@return KErrNone if the operation was successful
1.2076 + KErrAccessDenied if client ID (aClientId) could not be found in the registered
1.2077 + client list or if the client was registered to be thread relative
1.2078 + and this API is not called from the same thread.
1.2079 + KErrNotFound if client ID (aTargetClientId) could not be found in the current list
1.2080 + of registered client and is also not 0.
1.2081 + KErrArgument if aNumResources is 0 or aInfo is NULL or if size of aInfo is not sufficient
1.2082 + to hold the resource information of number of resources specified in aNumResources.
1.2083 +
1.2084 +@pre Interrupts must be enabled
1.2085 +@pre Kernel must be unlocked
1.2086 +@pre No fast mutex can be held
1.2087 +@pre Call in a thread context but not from null thread or DFC thread1
1.2088 +@pre Can be used in a device driver
1.2089 +*/
1.2090 +TInt DPowerResourceController::GetInfoOnResourcesInUseByClient(TUint aClientId, TUint aTargetClientId,
1.2091 + TUint& aNumResources, TAny* anInfo)
1.2092 + {
1.2093 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetInfoOnResourcesInUseByClient"));
1.2094 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("CallingClientId = 0x%x, TargetClientId = 0x%x, NumResources = %d", \
1.2095 + aClientId, aTargetClientId, aNumResources));
1.2096 + DThread& thread = Kern::CurrentThread();
1.2097 + CHECK_CONTEXT(thread)
1.2098 + if(!anInfo || !aNumResources)
1.2099 + return KErrArgument;
1.2100 + SPowerResourceClient* pC = NULL;
1.2101 + Lock();
1.2102 + VALIDATE_CLIENT(thread);
1.2103 + DStaticPowerResource* pR = NULL;
1.2104 + TDes8 *pInfo = (TDes8*)anInfo;
1.2105 + if((TUint)(pInfo->MaxLength() - pInfo->Length()) < (sizeof(TPowerResourceInfoV01) * aNumResources))
1.2106 + UNLOCK_RETURN(KErrArgument);
1.2107 + TPowerResourceInfoBuf01 buf;
1.2108 +
1.2109 + TUint16 count = 0;
1.2110 + TInt r = KErrNone;
1.2111 + //Special case, if aTargetClientId is 0 fill with all the resource
1.2112 + if(!aTargetClientId)
1.2113 + {
1.2114 + TUint numResources = aNumResources;
1.2115 +#ifndef PRM_ENABLE_EXTENDED_VERSION
1.2116 + aNumResources = iStaticResourceCount;
1.2117 +#else
1.2118 + aNumResources = iStaticResourceCount + iDynamicResourceCount + iStaticResDependencyCount +
1.2119 + iDynamicResDependencyCount;
1.2120 +#endif
1.2121 + UnLock();
1.2122 + while(count < iStaticResourceArrayEntries)
1.2123 + {
1.2124 + if(numResources <=0)
1.2125 + return KErrNone;
1.2126 + pR = iStaticResourceArray[count++];
1.2127 + if(!pR)
1.2128 + continue;
1.2129 + r = pR->GetInfo((TDes8*)buf.Ptr());
1.2130 + if(r != KErrNone)
1.2131 + return r;
1.2132 + //Update Resource Id.
1.2133 + ((TPowerResourceInfoV01*)buf.Ptr())->iResourceId = count;
1.2134 + pInfo->Append(buf);
1.2135 + numResources--;
1.2136 + }
1.2137 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2138 + count = 0;
1.2139 + while(count < iStaticResDependencyCount)
1.2140 + {
1.2141 + if(count >= numResources)
1.2142 + return KErrNone;
1.2143 + pR = iStaticResDependencyArray[count++];
1.2144 + r = pR->GetInfo((TDes8*)buf.Ptr());
1.2145 + //Update Resource Id.
1.2146 + ((TPowerResourceInfoV01*)buf.Ptr())->iResourceId = ((DStaticPowerResourceD*)pR)->iResourceId;
1.2147 + if(r != KErrNone)
1.2148 + return r;
1.2149 + pInfo->Append(buf);
1.2150 + }
1.2151 + numResources -= iStaticResDependencyCount;
1.2152 + if((!numResources) || (!iDynamicResourceCount && !iDynamicResDependencyCount))
1.2153 + return r;
1.2154 + Lock();
1.2155 + TUint resCount = 0;
1.2156 + for(count = 0; count < iDynamicResourceList.Allocd(); count++)
1.2157 + {
1.2158 + pR = iDynamicResourceList[count];
1.2159 + if(!pR)
1.2160 + continue;
1.2161 + if((resCount >= iDynamicResourceCount) || (resCount >= numResources))
1.2162 + UNLOCK_RETURN(KErrNone);
1.2163 + r = pR->GetInfo((TDes8*)buf.Ptr());
1.2164 + if(r != KErrNone)
1.2165 + UNLOCK_RETURN(r);
1.2166 + ((TPowerResourceInfoV01*)buf.Ptr())->iResourceId = ((DDynamicPowerResource*)pR)->iResourceId;
1.2167 + pInfo->Append(buf);
1.2168 + resCount++;
1.2169 + }
1.2170 + numResources -= resCount;
1.2171 + resCount = 0;
1.2172 + for(count = 0; count < iDynamicResDependencyList.Allocd(); count++)
1.2173 + {
1.2174 + pR = iDynamicResDependencyList[count];
1.2175 + if(!pR)
1.2176 + continue;
1.2177 + if((resCount >= iDynamicResDependencyCount) || (resCount >= numResources))
1.2178 + UNLOCK_RETURN(KErrNone);
1.2179 + r = pR->GetInfo((TDes8*)buf.Ptr());
1.2180 + if(r != KErrNone)
1.2181 + UNLOCK_RETURN(r);
1.2182 + ((TPowerResourceInfoV01*)buf.Ptr())->iResourceId = ((DDynamicPowerResourceD*)pR)->iResourceId;
1.2183 + pInfo->Append(buf);
1.2184 + resCount++;
1.2185 + }
1.2186 + UnLock();
1.2187 +#endif
1.2188 + return r;
1.2189 + }
1.2190 + GET_TARGET_CLIENT();
1.2191 + SPowerResourceClientLevel* pCL = pC->iLevelList;
1.2192 + for (count= 0; pCL; count++, pCL = pCL->iNextInList)
1.2193 + {
1.2194 + if(count >= aNumResources)
1.2195 + continue;
1.2196 +#ifndef PRM_ENABLE_EXTENDED_VERSION
1.2197 + pR = iStaticResourceArray[pCL->iResourceId-1];
1.2198 +#else
1.2199 + GET_RESOURCE_FROM_LIST(pCL->iResourceId, pR);
1.2200 +#endif
1.2201 + r = pR->GetInfo((TDes8*)buf.Ptr());
1.2202 + //Update Resource Id.
1.2203 + ((TPowerResourceInfoV01*)buf.Ptr())->iResourceId = pCL->iResourceId;
1.2204 + if(r != KErrNone)
1.2205 + UNLOCK_RETURN(r);
1.2206 + pInfo->Append(buf);
1.2207 + }
1.2208 + aNumResources = count;
1.2209 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetInfoOnResourcesInUseByClient, AcutalNoOfResources = %d", aNumResources));
1.2210 + UNLOCK_RETURN(KErrNone);
1.2211 + }
1.2212 +
1.2213 +/**
1.2214 +@publishedPartner
1.2215 +@prototype 9.5
1.2216 +
1.2217 +Request number of clients which has requirements on the resource level of the specified
1.2218 +resource. Resource ID starts from 1, so 0 can be used to get the number of clients
1.2219 +registered with resource manager.
1.2220 +
1.2221 +@param aClientId ID of the client which is requesting number of clients
1.2222 + holding requirement on specified resource.
1.2223 +@param aResourceId ID of the resource.
1.2224 +@param aNumClient This is updated with number of clients having a requirement
1.2225 + on resource level if valid resource ID is specified.
1.2226 + If resource ID is 0, then it is updated with number of clients
1.2227 + registered with PRM.
1.2228 +
1.2229 +@return KErrNone if the operation was successful
1.2230 + KErrAccessDenied if the client ID could not found in the current list of
1.2231 + registered clients or if the client was registered to be thread
1.2232 + relative and this API is not called from the same thread.
1.2233 + KErrNotFound If this resource ID could not be found in the current list
1.2234 + of registered resource and is also not 0.
1.2235 +
1.2236 +@pre Interrupts must be enabled
1.2237 +@pre Kernel must be unlocked
1.2238 +@pre No fast mutex can be held
1.2239 +@pre Call in a thread context but not from null thread or DFC thread1
1.2240 +@pre Can be used in a device driver
1.2241 +*/
1.2242 +TInt DPowerResourceController::GetNumClientsUsingResource(TUint aClientId, TUint aResourceId, TUint& aNumClients)
1.2243 + {
1.2244 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetNumClientsUsingResource"));
1.2245 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d", aClientId, aResourceId));
1.2246 + DThread& thread = Kern::CurrentThread();
1.2247 + CHECK_CONTEXT(thread)
1.2248 + SPowerResourceClient* pC = NULL;
1.2249 + Lock();
1.2250 + VALIDATE_CLIENT(thread);
1.2251 + if(!aResourceId)
1.2252 + {
1.2253 + //Special case return the number of clients registered with resource controller.
1.2254 + aNumClients = iClientCount + iUserSideClientCount;
1.2255 + UNLOCK_RETURN(KErrNone);
1.2256 + }
1.2257 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2258 + DStaticPowerResource* pR = NULL;
1.2259 + GET_RESOURCE_FROM_LIST(aResourceId, pR)
1.2260 +#else
1.2261 + if(aResourceId > iStaticResourceArrayEntries)
1.2262 + UNLOCK_RETURN(KErrNotFound);
1.2263 + DStaticPowerResource* pR = iStaticResourceArray[aResourceId-1];
1.2264 + if(!pR)
1.2265 + UNLOCK_RETURN(KErrNotFound);
1.2266 +#endif
1.2267 + aNumClients = 0;
1.2268 + for(SDblQueLink*pCL = pR->iClientList.First(); pCL != &pR->iClientList.iA; pCL=pCL->iNext)
1.2269 + aNumClients++;
1.2270 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetNumClientsUsingResource, NumClients = %d", aNumClients));
1.2271 + UNLOCK_RETURN(KErrNone);
1.2272 + }
1.2273 +
1.2274 +/**
1.2275 +@publishedPartner
1.2276 +@prototype 9.5
1.2277 +
1.2278 +Request information on clients
1.2279 +If resource ID is valid, aInfo is updated with the information of the clients
1.2280 +which have a requirement on the resource level for the specified resource
1.2281 +If resource ID is 0, aInfo is updated with the information of the clients registered
1.2282 +with resource manager, starting from client ID 1.
1.2283 +The number of clients for which information will be provided will be equal to or less
1.2284 +than the number specified in aNumClients.
1.2285 +@param aClientId ID of the client which is requesting the information on
1.2286 + the clients which holds requirement on specified
1.2287 + resource's level change.
1.2288 +@param aResourceId Id of the resource.
1.2289 +@param aNumClients Number of clients whose information needs to be filled in aInfo
1.2290 + i.e., it specifies the size of aInfo array.
1.2291 +@param aInfo A pointer to an array of descriptor containing an information
1.2292 + structure (TPowerClientInfoV01) to be filled in with
1.2293 + the information on the client. It will be assumed that array
1.2294 + allocated will be equal to the number passed in aNumClients.
1.2295 + The Client must create the array of descriptors in kernel stack
1.2296 + or heap.
1.2297 +
1.2298 +@return KErrNone if the operation was successful.
1.2299 + KErrNotFound if resource ID could not be found in the registered resource list and is not 0.
1.2300 + KErrAccessDenied if client ID (aClientId) could not be found in the registered client
1.2301 + list or if the client was registered to be thread relative and this API is not
1.2302 + called from the same thread.
1.2303 + KErrArgument if aNumClients is 0 or aInfo is NULL or if size of aInfo is not sufficient to hold
1.2304 + client information of specified client number in aNumClients.
1.2305 +
1.2306 +@pre Interrupts must be enabled
1.2307 +@pre Kernel must be unlocked
1.2308 +@pre No fast mutex can be held
1.2309 +@pre Call in a thread context but not from null thread or DFC thread1
1.2310 +@pre Can be used in a device driver
1.2311 +*/
1.2312 +TInt DPowerResourceController::GetInfoOnClientsUsingResource(TUint aClientId, TUint aResourceId,
1.2313 + TUint& aNumClients, TAny* anInfo)
1.2314 + {
1.2315 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetInfoOnClientsUsingResource"));
1.2316 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d, NumClients = %d", \
1.2317 + aClientId, aResourceId, aNumClients));
1.2318 + DThread& thread = Kern::CurrentThread();
1.2319 + CHECK_CONTEXT(thread)
1.2320 + if(!anInfo || !aNumClients)
1.2321 + return KErrArgument;
1.2322 + SPowerResourceClient* pC = NULL;
1.2323 + Lock();
1.2324 + VALIDATE_CLIENT(thread);
1.2325 + TDes8 *pInfo = (TDes8*)anInfo;
1.2326 + if((TUint)(pInfo->MaxLength() - pInfo->Length()) < (sizeof(TPowerClientInfoV01) * aNumClients))
1.2327 + UNLOCK_RETURN(KErrArgument);
1.2328 + TPowerClientInfoV01 info;
1.2329 + if(aResourceId == 0)
1.2330 + {
1.2331 + TUint16 count = 0, resCount = 0;
1.2332 + for(count = 0; count < iClientList.Allocd(); count++)
1.2333 + {
1.2334 + if((resCount >= iClientCount) || (resCount >= aNumClients))
1.2335 + break;
1.2336 + pC = iClientList[count];
1.2337 + if(!pC)
1.2338 + continue;
1.2339 + resCount++;
1.2340 + info.iClientId = pC->iClientId;
1.2341 + info.iClientName = (TDesC8*)pC->iName;
1.2342 + pInfo->Append(TPckgC<TPowerClientInfoV01>(info));
1.2343 + }
1.2344 + aNumClients -= resCount;
1.2345 + resCount = 0;
1.2346 + for(count = 0; count < iUserSideClientList.Allocd(); count++)
1.2347 + {
1.2348 + if((resCount >= iUserSideClientCount) || (resCount >= aNumClients))
1.2349 + break;
1.2350 + pC = iUserSideClientList[count];
1.2351 + if(!pC)
1.2352 + continue;
1.2353 + resCount++;
1.2354 + info.iClientId = pC->iClientId;
1.2355 + info.iClientName = (TDesC8*)pC->iName;
1.2356 + pInfo->Append(TPckgC<TPowerClientInfoV01>(info));
1.2357 + }
1.2358 + aNumClients = iClientCount + iUserSideClientCount;
1.2359 + UNLOCK_RETURN(KErrNone);
1.2360 + }
1.2361 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2362 + DStaticPowerResource* pR = NULL;
1.2363 + GET_RESOURCE_FROM_LIST(aResourceId, pR)
1.2364 +#else
1.2365 + if(aResourceId > iStaticResourceArrayEntries)
1.2366 + UNLOCK_RETURN(KErrNotFound);
1.2367 + DStaticPowerResource* pR = iStaticResourceArray[aResourceId-1];
1.2368 + if(!pR)
1.2369 + UNLOCK_RETURN(KErrNotFound);
1.2370 +#endif
1.2371 + SPowerResourceClientLevel* pCL = NULL;
1.2372 + TUint c = 0;
1.2373 + for(SDblQueLink* pRC = pR->iClientList.First(); pRC != &pR->iClientList.iA; pRC = pRC->iNext, c++)
1.2374 + {
1.2375 + if(c >= aNumClients)
1.2376 + continue;
1.2377 + pCL = (SPowerResourceClientLevel*)pRC;
1.2378 + if(pCL->iClientId & USER_SIDE_CLIENT_BIT_MASK)
1.2379 + pC = iUserSideClientList[(TUint16)(pCL->iClientId & ID_INDEX_BIT_MASK)];
1.2380 + else
1.2381 + pC = iClientList[(TUint16)(pCL->iClientId & ID_INDEX_BIT_MASK)];
1.2382 + info.iClientId = pC->iClientId;
1.2383 + info.iClientName = (TDesC8*)pC->iName;
1.2384 + pInfo->Append(TPckgC<TPowerClientInfoV01>(info));
1.2385 + }
1.2386 + aNumClients = c;
1.2387 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetInfoOnClientsUsingResource, NumClients = %d", aNumClients));
1.2388 + UNLOCK_RETURN(KErrNone);
1.2389 + }
1.2390 +
1.2391 +/**
1.2392 +@publishedPartner
1.2393 +@prototype 9.5
1.2394 +
1.2395 +Request changing the state of a resource
1.2396 +NOTE: If a resource callback is specified for instantaneous resource, then callback
1.2397 + will be called after resource change and will be executed in the context of the
1.2398 + client thread.
1.2399 + If a resource callback is specified for long latency reosurces, then it will be
1.2400 + executed asynchronously.When the request is accepted the API returns immediately
1.2401 + and the calling thread is unblocked: the callback (called in the client's context)
1.2402 + will be invoked when the resource change finally takes place.
1.2403 + If aCb is not specified (NULL by default) the API executes synchronously and will
1.2404 + only return when the resource change has taken place for long latency resource.
1.2405 + The client thread is blocked throughout
1.2406 + When state change for a shared resource is requested, only minimum state that
1.2407 + satisfy the requirement is guaranteed and it is not guaranteed for the absolute
1.2408 + value change.
1.2409 +
1.2410 +@param aClientId ID of the client which is requesting the resource change.
1.2411 +@param aResourceId ID of the resource whose state is to be changed.
1.2412 +@param aNewState The new state of the resource. This could be a binary value for a
1.2413 + binary resource, an integer level for a multilevel resource or some
1.2414 + platform specific token for a multi-property resource.
1.2415 +@param aCb For Long latency resource
1.2416 + A pointer to a resource callback object which encapsulates a
1.2417 + callback function to be called whenever the resource state change
1.2418 + happens (if left NULL the API will execute synchrounously).
1.2419 + For Instantaneous resource
1.2420 + A pointer to a resource callback object which encapsulates a callback
1.2421 + function to be called after resource change. This executes in the
1.2422 + context of the client thread.
1.2423 +
1.2424 +@return KErrNone If the API is to be executed synchronously it indicates the change was
1.2425 + successful, if the API is to be executed asynchronously it indicates
1.2426 + the request to change the resource state has been accepted.
1.2427 + KErrNotFound if the resource ID could not be found in the current list of
1.2428 + controllable resources.
1.2429 + KErrAccessDenied if the client ID could not be found in the list of
1.2430 + registered clients or if the client was registered to be thread
1.2431 + relative and this API is not called from the same thread or if the
1.2432 + resource is single user resource and another client is already holding
1.2433 + the resource.
1.2434 + KErrNotReady if the request is issued before the resource controller completes its
1.2435 + internal initialisation.
1.2436 + KErrUnderflow if the client has exceeded the reserved number of
1.2437 + SPowerResourceClientLevel and the free pool is empty or if it is
1.2438 + an asynchronous operation on a long latency resource and the client has
1.2439 + exceeded the reserved number of TPowerRequest and the free pool is empty.
1.2440 + KErrArgument if requested level is out of range (outside of min and max levels).
1.2441 + KErrCorrupt if internal data structure is corrupted.
1.2442 + KErrPermissionDenied if the requested state of the resource is not accepted by its dependents.
1.2443 + This error is valid only for dependent resource state change in extended version
1.2444 + of PRM.
1.2445 +
1.2446 +@pre Interrupts must be enabled
1.2447 +@pre Kernel must be unlocked
1.2448 +@pre No fast mutex can be held
1.2449 +@pre Call in a thread context but not from null thread or DFC thread1
1.2450 +@pre Can be used in a device driver
1.2451 +@pre Do not call synchronous version from DFC thread 0 for long latency resource
1.2452 +*/
1.2453 +TInt DPowerResourceController::ChangeResourceState(TUint aClientId, TUint aResourceId, TInt aNewState,
1.2454 + TPowerResourceCb* aCb)
1.2455 + {
1.2456 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::ChangeResourceState"));
1.2457 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d, NewState = %d", aClientId, \
1.2458 + aResourceId, aNewState));
1.2459 + DThread& thread = Kern::CurrentThread();
1.2460 + CHECK_CONTEXT(thread)
1.2461 + if(iInitialised <= EResConCreated)
1.2462 + return KErrNotReady;
1.2463 + if(!aResourceId)
1.2464 + return KErrNotFound;
1.2465 + SPowerResourceClient* pC = NULL;
1.2466 + TInt r = KErrNone;
1.2467 + Lock();
1.2468 + VALIDATE_CLIENT(thread);
1.2469 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2470 + DStaticPowerResource *pR = NULL;
1.2471 + GET_RESOURCE_FROM_LIST(aResourceId, pR)
1.2472 +#else
1.2473 + if(aResourceId > iStaticResourceArrayEntries)
1.2474 + UNLOCK_RETURN(KErrNotFound);
1.2475 + DStaticPowerResource* pR = iStaticResourceArray[aResourceId-1];
1.2476 + if(!pR)
1.2477 + UNLOCK_RETURN(KErrNotFound);
1.2478 +#endif
1.2479 + //Return if the resource is already in that state and client is also the same.
1.2480 + if((aNewState == pR->iCachedLevel) && ((TInt)aClientId == pR->iLevelOwnerId))
1.2481 + UNLOCK_RETURN(KErrNone);
1.2482 +
1.2483 +
1.2484 + PRM_CLIENT_CHANGE_STATE_START_TRACE
1.2485 + //If long latency resource requested synchronously from DFC thread 0 Panic
1.2486 +
1.2487 + const TDesC8* pDfc0 = &KDfcThread0Name;
1.2488 + if((pR->LatencySet() && !aCb) && !(pDfc0->Compare(*(TDesC8*)thread.iName)))
1.2489 + {
1.2490 + UnLock();
1.2491 + Panic(ECalledFromDfcThread0);
1.2492 + }
1.2493 + if(!pR->Usage() && !pR->iClientList.IsEmpty())
1.2494 + {
1.2495 + SPowerResourceClientLevel* pCL = (SPowerResourceClientLevel*)pR->iClientList.First();
1.2496 + if((pCL != NULL) && (pCL->iClientId != pC->iClientId))
1.2497 + {
1.2498 + r = KErrAccessDenied;
1.2499 + PRM_CLIENT_CHANGE_STATE_END_TRACE
1.2500 + UNLOCK_RETURN(r);
1.2501 + }
1.2502 + }
1.2503 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2504 + if(aResourceId & KIdMaskDynamic)
1.2505 + {
1.2506 + //Resource in the process of deregistration
1.2507 + if(((DDynamicPowerResource*)pR)->LockCount() == 0)
1.2508 + {
1.2509 + r = KErrNotFound;
1.2510 + PRM_CLIENT_CHANGE_STATE_END_TRACE
1.2511 + UNLOCK_RETURN(r);
1.2512 + }
1.2513 + }
1.2514 +#endif
1.2515 + //Validate requested level
1.2516 + TPowerResourceInfoBuf01 buf;
1.2517 + r = pR->GetInfo((TDes8*)buf.Ptr());
1.2518 + if(r != KErrNone)
1.2519 + {
1.2520 + PRM_CLIENT_CHANGE_STATE_END_TRACE
1.2521 + UNLOCK_RETURN(r);
1.2522 + }
1.2523 + TPowerResourceInfoV01 *pBuf = (TPowerResourceInfoV01*)buf.Ptr();
1.2524 + if(((pBuf->iMinLevel > pBuf->iMaxLevel) && ((aNewState > pBuf->iMinLevel) || (aNewState < pBuf->iMaxLevel)))
1.2525 + || ((pBuf->iMaxLevel > pBuf->iMinLevel) && ((aNewState > pBuf->iMaxLevel) || (aNewState < pBuf->iMinLevel))))
1.2526 + {
1.2527 + r = KErrArgument;
1.2528 + PRM_CLIENT_CHANGE_STATE_END_TRACE
1.2529 + UNLOCK_RETURN(r);
1.2530 + }
1.2531 +
1.2532 + TPowerRequest* req;
1.2533 + SPowerRequest* pS=NULL;
1.2534 + if(pR->LatencySet() && aCb)
1.2535 + {
1.2536 + // Get request object from free pool, as it is long latency reosurce as client
1.2537 + // will be unblocked once message is sent to controller, so cant use thread message.
1.2538 + if(pC->iReservedRm ==0 && !iRequestPoolCount)
1.2539 + {
1.2540 + r = KErrUnderflow;
1.2541 + PRM_CLIENT_CHANGE_STATE_END_TRACE
1.2542 + UNLOCK_RETURN(r);
1.2543 + }
1.2544 +
1.2545 + LIST_POP(iRequestPool, pS, iNext);
1.2546 + if(!pS)
1.2547 + UNLOCK_RETURN(KErrCorrupt); //This should not happen
1.2548 + if(pC->iReservedRm==0)
1.2549 + {
1.2550 + iRequestPoolCount--;
1.2551 + pC->iUnderFlowRmCount++;
1.2552 + }
1.2553 + else
1.2554 + pC->iReservedRm--;
1.2555 + req=&pS->iRequest;
1.2556 + pC->iPendingReqCount++;
1.2557 + }
1.2558 + else
1.2559 + req=(TPowerRequest*)&TPowerRequest::Get();
1.2560 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2561 + if(aResourceId & KIdMaskDynamic)
1.2562 + ((DDynamicPowerResource*)pR)->Lock();
1.2563 +#endif
1.2564 + req->Level() = aNewState;
1.2565 + req->ResourceId() = aResourceId;
1.2566 + req->ClientId() = aClientId;
1.2567 + req->ReqType() = TPowerRequest::EChange;
1.2568 + req->Resource() = pR;
1.2569 + if(aCb)
1.2570 + {
1.2571 + aCb->iResult = KErrNone;
1.2572 + aCb->iResourceId = aResourceId;
1.2573 + aCb->iClientId = aClientId;
1.2574 + }
1.2575 + req->ResourceCb() = aCb;
1.2576 + if(pR->LatencySet())
1.2577 + {
1.2578 + UnLock();
1.2579 + if(aCb)
1.2580 + {
1.2581 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2582 + if (aCb->iResourceId & KIdMaskResourceWithDependencies) //Dependency resource
1.2583 + {
1.2584 + req->Send(iMsgQDependency); // Send the request to DFC thread.
1.2585 + return KErrNone;
1.2586 + }
1.2587 + else
1.2588 +#endif
1.2589 + {
1.2590 + req->Send(iMsgQ); // Send the request to Resource Controler thread.
1.2591 + return KErrNone;
1.2592 + }
1.2593 + }
1.2594 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2595 + if(aResourceId & KIdMaskResourceWithDependencies) //Dependency resource
1.2596 + {
1.2597 + r = req->SendReceive(iMsgQDependency); // Send the request to DFC thread.
1.2598 + }
1.2599 +#endif
1.2600 + else
1.2601 + {
1.2602 + r = req->SendReceive(iMsgQ); // Block till the controller completes with the request.
1.2603 + }
1.2604 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2605 + Lock();
1.2606 + if(aResourceId & KIdMaskDynamic)
1.2607 + ((DDynamicPowerResource*)pR)->UnLock();
1.2608 + UnLock();
1.2609 +#endif
1.2610 + return r;
1.2611 + }
1.2612 + if(pR->Usage())
1.2613 + {
1.2614 + r = CheckLevelAndAddClient(pC, req);
1.2615 + if((r != KErrNone)|| !req->RequiresChange())
1.2616 + {
1.2617 + req->Level() = pR->iCachedLevel;
1.2618 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2619 + if(aResourceId & KIdMaskDynamic)
1.2620 + ((DDynamicPowerResource*)pR)->UnLock();
1.2621 +#endif
1.2622 + UnLock();
1.2623 + if(aCb)
1.2624 + {
1.2625 + //Invoke callback function
1.2626 + aCb->iCallback(req->ClientId(), aResourceId, req->Level(), pR->iLevelOwnerId, r, aCb->iParam);
1.2627 + //Mark the callback object to act properly during cancellation of this request.
1.2628 + aCb->iResult = KErrCompletion;
1.2629 + }
1.2630 + PRM_CLIENT_CHANGE_STATE_END_TRACE
1.2631 + return(r);
1.2632 + }
1.2633 + }
1.2634 + else if(pR->iLevelOwnerId == -1)
1.2635 + {
1.2636 + /* Add client Level */
1.2637 + if(pC->iReservedCl<=0 && !iClientLevelPoolCount)
1.2638 + {
1.2639 + r = KErrUnderflow;
1.2640 + PRM_CLIENT_CHANGE_STATE_END_TRACE
1.2641 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2642 + if(aResourceId & KIdMaskDynamic)
1.2643 + ((DDynamicPowerResource*)pR)->UnLock();
1.2644 +#endif
1.2645 + UnLock();
1.2646 + return(r);
1.2647 + }
1.2648 + SPowerResourceClientLevel* pSCL=NULL;
1.2649 + LIST_POP(iClientLevelPool, pSCL, iNextInList);
1.2650 + pSCL->iClientId=aClientId;
1.2651 + pSCL->iResourceId=aResourceId;
1.2652 + pSCL->iLevel=aNewState;
1.2653 + LIST_PUSH(pC->iLevelList, pSCL, iNextInList);
1.2654 + pR->iClientList.Add(pSCL);
1.2655 + if(pC->iReservedCl==0)
1.2656 + {
1.2657 + iClientLevelPoolCount--;
1.2658 + pC->iUnderFlowClCount++;
1.2659 + }
1.2660 + else
1.2661 + pC->iReservedCl--;
1.2662 + }
1.2663 + else
1.2664 + {
1.2665 + //Update the level in the client list.
1.2666 + SPowerResourceClientLevel* pSCL = (SPowerResourceClientLevel*)pR->iClientList.First();
1.2667 + pSCL->iLevel = aNewState;
1.2668 + }
1.2669 + UnLock();
1.2670 + r = pR->DoRequest(*req);
1.2671 + Lock();
1.2672 + if(r==KErrNone)
1.2673 + {
1.2674 + //Notification to clients
1.2675 + CompleteNotifications(req->ClientId(), pR, req->Level(), r, aClientId, EFalse);
1.2676 + //Cache the state
1.2677 + pR->iCachedLevel=req->Level();
1.2678 + pR->iLevelOwnerId=req->ClientId();
1.2679 + //Update resource details for Idle
1.2680 + if(pR->iIdleListEntry)
1.2681 + {
1.2682 + pR->iIdleListEntry->iLevelOwnerId=req->ClientId();
1.2683 + pR->iIdleListEntry->iCurrentLevel=req->Level();
1.2684 + }
1.2685 + }
1.2686 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2687 + if(aResourceId & KIdMaskDynamic)
1.2688 + ((DDynamicPowerResource*)pR)->UnLock();
1.2689 +#endif
1.2690 + UnLock();
1.2691 + if(aCb)
1.2692 + {
1.2693 + //Invoke callback function
1.2694 + aCb->iCallback(req->ClientId(), aResourceId, req->Level(), pR->iLevelOwnerId, r, aCb->iParam);
1.2695 + aCb->iResult = KErrCompletion; //Mark the callback object to act properly during cancellation of this request.
1.2696 + }
1.2697 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::ChangeResourceState, Level = %d", req->Level()));
1.2698 + PRM_CLIENT_CHANGE_STATE_END_TRACE
1.2699 + return r;
1.2700 + }
1.2701 +
1.2702 +/**
1.2703 +@publishedPartner
1.2704 +@prototype 9.5
1.2705 +
1.2706 +Request the state of the resource synchronously
1.2707 +
1.2708 +@param aClientId ID of the client which is requesting the resource state.
1.2709 +@param aResourceId ID of the resource whose state is being requested.
1.2710 +@param aCached If ETrue, cached value will be updated in aState.
1.2711 + If EFalse, aState will be updated after the resource
1.2712 + state is read from resource.
1.2713 +@param aState Returns the resource state if operation was successful. This
1.2714 + could be a binary value for a binary resource, an integer level
1.2715 + for a multilevel resource or some platform specific tolen for a
1.2716 + multi-property resource.
1.2717 +@param aLevelOwnerId Returns the Id of the client that is currently holding the resource.
1.2718 + -1 is returned when no client is holding the resource.
1.2719 +
1.2720 +@return KErrNone if operation was successful
1.2721 + KErrAccessDenied if the client ID could not be found in the current list
1.2722 + of registered clients or if the client was registered to be thread
1.2723 + relative and this API is not called from the same thread.
1.2724 + KErrNotFound if this resource ID could not be found in the current list
1.2725 + of controllable resources.
1.2726 + KErrNotReady if the request is issued before the resource controller completes
1.2727 + its internal initialization.
1.2728 +
1.2729 +
1.2730 +@pre Interrupts must be enabled
1.2731 +@pre Kernel must be unlocked
1.2732 +@pre No fast mutex can be held
1.2733 +@pre Call in a thread context but not from null thread or DFC thread1
1.2734 +@pre Can be used in a device driver
1.2735 +@pre Do not call from DFC thread 0 for long latency resource with caching disabled.
1.2736 +*/
1.2737 +TInt DPowerResourceController::GetResourceState(TUint aClientId, TUint aResourceId, TBool aCached, TInt& aState,
1.2738 + TInt& aLevelOwnerId)
1.2739 + {
1.2740 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetResourceState(synchronous)"));
1.2741 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d, Cached = %d", aClientId, aResourceId, aCached));
1.2742 +
1.2743 + DThread& thread = Kern::CurrentThread();
1.2744 + CHECK_CONTEXT(thread)
1.2745 + if(iInitialised <= EResConCreated)
1.2746 + return KErrNotReady;
1.2747 + SPowerResourceClient* pC = NULL;
1.2748 + TInt r = KErrNone;
1.2749 + Lock();
1.2750 + VALIDATE_CLIENT(thread);
1.2751 + if(!aResourceId)
1.2752 + UNLOCK_RETURN(KErrNotFound);
1.2753 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2754 + DStaticPowerResource *pR = NULL;
1.2755 + GET_RESOURCE_FROM_LIST(aResourceId, pR)
1.2756 + if(aResourceId & KIdMaskDynamic)
1.2757 + {
1.2758 + if(((DDynamicPowerResource*)pR)->LockCount() == 0)
1.2759 + UNLOCK_RETURN(KErrNotFound);
1.2760 + }
1.2761 +#else
1.2762 + if(aResourceId > iStaticResourceArrayEntries)
1.2763 + UNLOCK_RETURN(KErrNotFound);
1.2764 + DStaticPowerResource *pR = iStaticResourceArray[aResourceId-1];
1.2765 + if(!pR)
1.2766 + UNLOCK_RETURN(KErrNotFound);
1.2767 +#endif
1.2768 + PRM_RESOURCE_GET_STATE_START_TRACE
1.2769 + //Panic if long latency resource called to execute synchronously from DFC thread0
1.2770 + const TDesC8* pDfc0 = &KDfcThread0Name;
1.2771 + if((!aCached && pR->LatencyGet()) && !(pDfc0->Compare(*(TDesC*)thread.iName)))
1.2772 + {
1.2773 + UnLock();
1.2774 + Panic(ECalledFromDfcThread0);
1.2775 + }
1.2776 + if(aCached)
1.2777 + {
1.2778 + //Return the cached value.
1.2779 + aState = pR->iCachedLevel;
1.2780 + aLevelOwnerId = pR->iLevelOwnerId;
1.2781 + PRM_RESOURCE_GET_STATE_END_TRACE
1.2782 + UNLOCK_RETURN(KErrNone);
1.2783 + }
1.2784 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2785 + if(aResourceId & KIdMaskDynamic)
1.2786 + ((DDynamicPowerResource*)pR)->Lock();
1.2787 +#endif
1.2788 + //Call from thread Id.
1.2789 + TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
1.2790 + req->ResourceId() = aResourceId;
1.2791 + req->ReqType() = TPowerRequest::EGet;
1.2792 + req->ClientId() = aClientId;
1.2793 + req->Resource() = pR;
1.2794 + req->ResourceCb() = NULL;
1.2795 + if(pR->LatencyGet())
1.2796 + {
1.2797 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2798 + if( req->ResourceId() & KIdMaskResourceWithDependencies ) // Dependency Resource
1.2799 + {
1.2800 + UnLock();
1.2801 + req->SendReceive(iMsgQDependency); //Send the request to DFC Thread
1.2802 + Lock();
1.2803 + }
1.2804 + else // Plain resource
1.2805 +#endif
1.2806 + {
1.2807 + UnLock();
1.2808 + req->SendReceive(iMsgQ);
1.2809 + Lock();
1.2810 + }
1.2811 + }
1.2812 + else
1.2813 + {
1.2814 + UnLock();
1.2815 + r = pR->DoRequest(*req); // Call PSL to get the state of resource.
1.2816 + Lock();
1.2817 + if(r==KErrNone)
1.2818 + {
1.2819 + //Update the cache value and cache for idle thread usage if requested for this resource.
1.2820 + pR->iCachedLevel=req->Level();
1.2821 + if(pR->iIdleListEntry)
1.2822 + {
1.2823 + SIdleResourceInfo* pI=pR->iIdleListEntry;
1.2824 + pI->iCurrentLevel=req->Level();
1.2825 + }
1.2826 + }
1.2827 + }
1.2828 + aState = req->Level();
1.2829 + aLevelOwnerId = pR->iLevelOwnerId;
1.2830 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2831 + if(aResourceId & KIdMaskDynamic)
1.2832 + ((DDynamicPowerResource*)pR)->UnLock();
1.2833 +#endif
1.2834 + UnLock();
1.2835 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetResourceState(synchronous), Level = %d", aState));
1.2836 + if(pR->LatencyGet()) //For long latency resource btrace is done in controller thread.
1.2837 + return r;
1.2838 + PRM_RESOURCE_GET_STATE_END_TRACE
1.2839 + return r;
1.2840 + }
1.2841 +
1.2842 +/**
1.2843 +@publishedPartner
1.2844 +@prototype 9.5
1.2845 +
1.2846 +Request the state of the resource asynchrounously for long latency resource and
1.2847 +synchronously for instantaneous resource
1.2848 +
1.2849 +@param aClientId ID of the client which is requesting the resource state.
1.2850 +@param aResourceId ID of the resource whose state is being requested.
1.2851 +@param aCached If ETrue, cached value will be updated in aState
1.2852 + If EFalse, will be updated after the resource state is read from resource
1.2853 +@param aCb For long latency resource:
1.2854 + A pointer to a resource callback object which encapsulates a callback function
1.2855 + to be called whenever the state of the resource is available for the long
1.2856 + latency resource (executes in the context of resource manager)
1.2857 + For instantaneous resource:
1.2858 + A pointer to a resource callback object which encapsulates a callback
1.2859 + function to be called after the resource state is read. This is executed
1.2860 + synchronously in the context of the calling thread.
1.2861 + NOTE: The client must create the callback object in kernel heap or
1.2862 + data section.
1.2863 +
1.2864 +@return KErrNone if the operation was successful
1.2865 + KErrArgument if callback object is NULL
1.2866 + KErrAccessDenied if the client ID could not be found in the current list
1.2867 + of registered clients or if the client was registered to be thread
1.2868 + relative and this API is not called from the same thread.
1.2869 + KErrNotFound if this resource ID could not be found in the current list
1.2870 + of controllable resources.
1.2871 + KErrNotReady if the request is issued before the resource controller completes
1.2872 + its internal initialisation
1.2873 + KErrUnderflow if the client has exceeded the reserved number of TPowerRequest
1.2874 + and the TPowerRequest free pool is empty for long latency resource.
1.2875 + KErrCorrupt if internal data structure is corrupt.
1.2876 +
1.2877 +@pre Interrupts must be enabled
1.2878 +@pre Kernel must be unlocked
1.2879 +@pre No fast mutex can be held
1.2880 +@pre Call in a thread context but not from null thread or DFC thread1
1.2881 +@pre Can be used in a device driver
1.2882 +*/
1.2883 +TInt DPowerResourceController::GetResourceState(TUint aClientId, TUint aResourceId, TBool aCached, TPowerResourceCb& aCb)
1.2884 + {
1.2885 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetResourceState(asynchronous)"));
1.2886 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d, Cached = %d", aClientId, aResourceId, aCached));
1.2887 +
1.2888 + DThread& thread = Kern::CurrentThread();
1.2889 + CHECK_CONTEXT(thread)
1.2890 + if(iInitialised <= EResConCreated)
1.2891 + return KErrNotReady;
1.2892 + SPowerResourceClient* pC = NULL;
1.2893 + TInt r = KErrNone;
1.2894 + Lock();
1.2895 + VALIDATE_CLIENT(thread);
1.2896 + if(!aResourceId)
1.2897 + UNLOCK_RETURN(KErrNotFound);
1.2898 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2899 + DStaticPowerResource *pR = NULL;
1.2900 + GET_RESOURCE_FROM_LIST(aResourceId, pR)
1.2901 + if(aResourceId & KIdMaskDynamic)
1.2902 + {
1.2903 + //Dynamic resource in process of deregistration
1.2904 + if(((DDynamicPowerResource*)pR)->LockCount() == 0)
1.2905 + UNLOCK_RETURN(KErrNotFound);
1.2906 + }
1.2907 +#else
1.2908 + if(aResourceId > iStaticResourceArrayEntries)
1.2909 + UNLOCK_RETURN(KErrNotFound);
1.2910 + DStaticPowerResource *pR = iStaticResourceArray[aResourceId-1];
1.2911 + if(!pR)
1.2912 + UNLOCK_RETURN(KErrNotFound);
1.2913 +#endif
1.2914 + aCb.iResult = KErrNone;
1.2915 + aCb.iResourceId = aResourceId;
1.2916 + aCb.iClientId = aClientId;
1.2917 +
1.2918 + PRM_RESOURCE_GET_STATE_START_TRACE
1.2919 + if(aCached) //Call the callback directly
1.2920 + {
1.2921 + UnLock();
1.2922 + aCb.iCallback(aClientId, aResourceId, pR->iCachedLevel, pR->iLevelOwnerId, KErrNone, aCb.iParam);
1.2923 + aCb.iResult = KErrCompletion; //Mark the callback object to act properly during cancellation of this request.
1.2924 +#ifdef PRM_INSTRUMENTATION_MACRO
1.2925 + TInt aState = pR->iCachedLevel;
1.2926 + PRM_RESOURCE_GET_STATE_END_TRACE
1.2927 +#endif
1.2928 + return(KErrNone);
1.2929 + }
1.2930 + TPowerRequest* req=NULL;
1.2931 + if(pR->LatencyGet())
1.2932 + {
1.2933 + //Check the client quota of requests
1.2934 + if(pC->iReservedRm==0 && !iRequestPoolCount)
1.2935 + UNLOCK_RETURN(KErrUnderflow);
1.2936 + if(pC->iReservedRm ==0)
1.2937 + {
1.2938 + iRequestPoolCount--;
1.2939 + pC->iUnderFlowRmCount++;
1.2940 + }
1.2941 + else
1.2942 + pC->iReservedRm--;
1.2943 + //Get the request from pool
1.2944 + SPowerRequest* pS;
1.2945 + LIST_POP(iRequestPool, pS, iNext);
1.2946 + if(!pS)
1.2947 + UNLOCK_RETURN(KErrCorrupt); //This should not be called
1.2948 + req = &pS->iRequest;
1.2949 + //Increment pending request count of the client
1.2950 + pC->iPendingReqCount++;
1.2951 + }
1.2952 + else
1.2953 + //Asynchronous instantaneous resource execute in the context of client thread.
1.2954 + req = (TPowerRequest*)&TPowerRequest::Get();
1.2955 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2956 + if(aResourceId & KIdMaskDynamic)
1.2957 + ((DDynamicPowerResource*)pR)->Lock();
1.2958 +#endif
1.2959 + UnLock();
1.2960 + req->ReqType() = TPowerRequest::EGet;
1.2961 + req->ResourceId() = aResourceId;
1.2962 + req->ClientId() = aClientId;
1.2963 + req->Resource() = pR;
1.2964 + req->ResourceCb() = &aCb;
1.2965 + if(pR->LatencyGet())
1.2966 + {
1.2967 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2968 + if( req->ResourceId() & KIdMaskResourceWithDependencies ) // Dependency Resource
1.2969 + {
1.2970 + req->Send(iMsgQDependency); // Send the request to DFC thread.
1.2971 + }
1.2972 + else // Plain resource
1.2973 +#endif
1.2974 + {
1.2975 + req->Send(iMsgQ);
1.2976 + }
1.2977 + }
1.2978 + else
1.2979 + {
1.2980 + r = pR->DoRequest(*req);
1.2981 + Lock();
1.2982 + if(r == KErrNone)
1.2983 + {
1.2984 + //Update the cache value and cache for idle thread usage if requested for this resource.
1.2985 + pR->iCachedLevel = req->Level();
1.2986 + if(pR->iIdleListEntry)
1.2987 + pR->iIdleListEntry->iCurrentLevel=req->Level();
1.2988 + }
1.2989 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.2990 + if(aResourceId & KIdMaskDynamic)
1.2991 + ((DDynamicPowerResource*)pR)->UnLock();
1.2992 +#endif
1.2993 + UnLock();
1.2994 + // Call the client callback function directly as it is already executing in the context of client thread.
1.2995 + aCb.iCallback(aClientId, aResourceId, req->Level(), pR->iLevelOwnerId, r, aCb.iParam);
1.2996 + aCb.iResult = KErrCompletion; //Mark the callback object to act properly during cancellation of this request.
1.2997 + }
1.2998 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetResourceState(asynchronous), Level = %d", req->Level()));
1.2999 + if(pR->LatencyGet())
1.3000 + return r;
1.3001 +#ifdef PRM_INSTRUMENTATION_MACRO
1.3002 + TInt aState = req->Level();
1.3003 + PRM_RESOURCE_GET_STATE_END_TRACE
1.3004 +#endif
1.3005 + return r;
1.3006 + }
1.3007 +
1.3008 +
1.3009 +/**
1.3010 +@publishedPartner
1.3011 +@prototype 9.5
1.3012 +
1.3013 +Cancel an asynchronous request(or its callback).
1.3014 +
1.3015 +@param aClientId ID of the client which is requesting the cancellation of the request.
1.3016 +@param aResourceId ID for the resource which the request that is being cancelled operates
1.3017 + upon.
1.3018 +@param aCb A reference to the resource callback object specified with the request
1.3019 + that is being cancelled.
1.3020 +
1.3021 +@return KErrCancel if the request was cancelled.
1.3022 + KErrNotFound if this resource ID could not be found in the current list of controllable
1.3023 + resources.
1.3024 + KErrCompletion if request is no longer pending.
1.3025 + KErrAccessDenied if the client ID could not be found in the current list of registered
1.3026 + clients or if the client was registered to be thread relative and this API is not called
1.3027 + from the same thread or if client is not the same that requested the resource state change.
1.3028 + KErrInUse if the request cannot be cancelled as processing of the request already started
1.3029 + and will run to completion.
1.3030 +
1.3031 +@pre Interrupts must be enabled
1.3032 +@pre Kernel must be unlocked
1.3033 +@pre No fast mutex can be held
1.3034 +@pre Call in a thread context but not from null thread or DFC thread1
1.3035 +@pre Can be used in a device driver
1.3036 +*/
1.3037 +TInt DPowerResourceController::CancelAsyncRequestCallBack(TUint aClientId, TUint aResourceId, TPowerResourceCb& aCb)
1.3038 + {
1.3039 + TInt r = KErrInUse;
1.3040 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::CancelAsyncRequestCallBack"));
1.3041 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d", aClientId, aResourceId));
1.3042 + DThread& thread = Kern::CurrentThread();
1.3043 + CHECK_CONTEXT(thread)
1.3044 + SPowerResourceClient* pC = NULL;
1.3045 + Lock();
1.3046 + VALIDATE_CLIENT(thread);
1.3047 + if((!aResourceId) || (aCb.iResourceId != aResourceId))
1.3048 + UNLOCK_RETURN(KErrNotFound);
1.3049 +#ifdef PRM_INSTRUMENTATION_MACRO
1.3050 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.3051 + DStaticPowerResource *pR = NULL;
1.3052 + GET_RESOURCE_FROM_LIST(aResourceId, pR)
1.3053 +#else
1.3054 + DStaticPowerResource *pR = iStaticResourceArray[aResourceId-1];
1.3055 + if(!pR)
1.3056 + UNLOCK_RETURN(KErrNotFound);
1.3057 +#endif
1.3058 +#endif
1.3059 + if(aCb.iClientId != aClientId)
1.3060 + {
1.3061 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("aCb.iClientId = 0x%x, aClientId = 0x%x", aCb.iClientId, aClientId));
1.3062 + r = KErrAccessDenied;
1.3063 +#ifdef PRM_INSTRUMENTATION_MACRO
1.3064 + PRM_RESOURCE_CANCEL_LONGLATENCY_OPERATION_TRACE
1.3065 +#endif
1.3066 + UNLOCK_RETURN(r);
1.3067 + }
1.3068 + if(aCb.iResult == KErrCompletion)
1.3069 + {
1.3070 + r = KErrCompletion;
1.3071 +#ifdef PRM_INSTRUMENTATION_MACRO
1.3072 + PRM_RESOURCE_CANCEL_LONGLATENCY_OPERATION_TRACE
1.3073 +#endif
1.3074 + UNLOCK_RETURN(r);
1.3075 + }
1.3076 + //Search in the controller message queue for this message
1.3077 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.3078 + if(aResourceId & KIdMaskResourceWithDependencies) //long latency resource with dependency and will be processed in dependency thread.
1.3079 + {
1.3080 + //Search in the controller message queue for this message
1.3081 + for(SDblQueLink* pRM = iMsgQDependency->iQ.First(); pRM != &(iMsgQDependency->iQ.iA); pRM = pRM->iNext)
1.3082 + {
1.3083 + TMessageBase* pMsgQ = (TMessageBase*)pRM;
1.3084 + TPowerRequest* pReq=(TPowerRequest*)pMsgQ;
1.3085 + if(pReq->ResourceCb() == &aCb)
1.3086 + {
1.3087 + r = KErrCancel;
1.3088 + pRM->Deque();
1.3089 + pMsgQ->iState = TMessageBase::EFree; //Reset the state
1.3090 + MoveRequestToFreePool(pReq);
1.3091 +#ifdef PRM_INSTRUMENTATION_MACRO
1.3092 + PRM_RESOURCE_CANCEL_LONGLATENCY_OPERATION_TRACE
1.3093 +#endif
1.3094 + UNLOCK_RETURN(r);
1.3095 + }
1.3096 + }
1.3097 + }
1.3098 + else // long latency resource without dependency and will be processed in RC thread.
1.3099 +#endif
1.3100 + {
1.3101 + for(SDblQueLink* pRM = iMsgQ->iQ.First(); pRM != &(iMsgQ->iQ.iA); pRM = pRM->iNext)
1.3102 + {
1.3103 + TMessageBase* pMsgQ = (TMessageBase*)pRM;
1.3104 + TPowerRequest* pReq=(TPowerRequest*)pMsgQ;
1.3105 + if(pReq->ResourceCb() == &aCb)
1.3106 + {
1.3107 + r = KErrCancel;
1.3108 + pRM->Deque();
1.3109 + pMsgQ->iState = TMessageBase::EFree; //Reset the state
1.3110 + MoveRequestToFreePool(pReq);
1.3111 +#ifdef PRM_INSTRUMENTATION_MACRO
1.3112 + PRM_RESOURCE_CANCEL_LONGLATENCY_OPERATION_TRACE
1.3113 +#endif
1.3114 + UNLOCK_RETURN(r);
1.3115 + }
1.3116 + }
1.3117 + }
1.3118 +#ifdef PRM_INSTRUMENTATION_MACRO
1.3119 + PRM_RESOURCE_CANCEL_LONGLATENCY_OPERATION_TRACE
1.3120 +#endif
1.3121 + UNLOCK_RETURN(r);
1.3122 + }
1.3123 +
1.3124 +/**
1.3125 +@publishedPartner
1.3126 +@prototype 9.5
1.3127 +
1.3128 +Request notification of changes to the state of a resource.
1.3129 +
1.3130 +@param aClientId ID of the client which is requesting the notification.
1.3131 +@param aResourceId ID of the resource for which notification of state changes
1.3132 + is being requested.
1.3133 +@param aN A reference to a notification object which encapsulates a callback
1.3134 + function to be called whenever a resource state change takes place.
1.3135 + NOTE: The client must create the notification object in kernel heap
1.3136 + or data section.
1.3137 +
1.3138 +@return KErrNone if the operation of requesting a notification was successful.
1.3139 + KErrNotFound if this resource ID could not be found in the current list
1.3140 + of controllable resources.
1.3141 + KErrAccessDenied if the client ID could not be found in the current
1.3142 + list of registered clients or if the client was registered to be
1.3143 + thread relative and this API is not called from the same thread.
1.3144 + KErrInUse if the passed notification object is used already.
1.3145 +NOTE: This API should return immediately; however the notification will
1.3146 +only happen when a resource change occurs.Notification request is idempotent,
1.3147 +if the same notification has already been requested for this resource ID,
1.3148 +the API returns with no further action.Notifications remain queued until they are cancelled.
1.3149 +
1.3150 +@pre Interrupts must be enabled
1.3151 +@pre Kernel must be unlocked
1.3152 +@pre No fast mutex can be held
1.3153 +@pre Call in a thread context but not from null thread or DFC thread1
1.3154 +@pre Can be used in a device driver
1.3155 +*/
1.3156 +TInt DPowerResourceController::RequestNotification(TUint aClientId, TUint aResourceId, DPowerResourceNotification& aN)
1.3157 + {
1.3158 + TInt r = KErrNone;
1.3159 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RequestNotification(unconditional)"));
1.3160 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d", aClientId, aResourceId));
1.3161 + DThread& thread = Kern::CurrentThread();
1.3162 + CHECK_CONTEXT(thread)
1.3163 + SPowerResourceClient* pC = NULL;
1.3164 + Lock();
1.3165 + VALIDATE_CLIENT(thread);
1.3166 + if((!aResourceId))
1.3167 + {
1.3168 + r = KErrNotFound;
1.3169 + PRM_POSTNOTIFICATION_REGISTER_TRACE
1.3170 + UNLOCK_RETURN(r);
1.3171 + }
1.3172 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.3173 + DStaticPowerResource *pR = NULL;
1.3174 + GET_RESOURCE_FROM_LIST(aResourceId, pR)
1.3175 +#else
1.3176 + if(aResourceId > iStaticResourceArrayEntries)
1.3177 + {
1.3178 + r = KErrNotFound;
1.3179 + PRM_POSTNOTIFICATION_REGISTER_TRACE
1.3180 + UNLOCK_RETURN(r);
1.3181 + }
1.3182 +
1.3183 + DStaticPowerResource *pR = iStaticResourceArray[aResourceId-1];
1.3184 + if(!pR)
1.3185 + {
1.3186 + r = KErrNotFound;
1.3187 + PRM_POSTNOTIFICATION_REGISTER_TRACE
1.3188 + UNLOCK_RETURN(r);
1.3189 + }
1.3190 +#endif
1.3191 + if(aN.iRegistered) //Check if the same notification object is used already
1.3192 + {
1.3193 + r = KErrInUse;
1.3194 + PRM_POSTNOTIFICATION_REGISTER_TRACE
1.3195 + UNLOCK_RETURN(r);
1.3196 + }
1.3197 + aN.iRegistered++;
1.3198 + aN.iType = DPowerResourceNotification::EUnconditional;
1.3199 + aN.iOwnerId=(TUint16)aClientId;
1.3200 + aN.iCallback.iClientId= aClientId;
1.3201 + aN.iCallback.iResourceId=aResourceId;
1.3202 + //Add to resource notification list
1.3203 + pR->iNotificationList.Add(&(aN.iNotificationLink));
1.3204 + //Add to client notification list
1.3205 + LIST_PUSH(pC->iNotificationList, &aN, iNextInClient);
1.3206 + PRM_POSTNOTIFICATION_REGISTER_TRACE
1.3207 + UNLOCK_RETURN(KErrNone);
1.3208 + }
1.3209 +
1.3210 +/**
1.3211 +@publishedPartner
1.3212 +@prototype 9.5
1.3213 +
1.3214 +Request notification when the state of a resource reaches a specified threshold or
1.3215 +goes above or below that threshold (for multilevel resource only) based on direction.
1.3216 +In other words it is issued when a threshold on the specified resource state is crossed
1.3217 +in the direction specified.
1.3218 +
1.3219 +@param aClientId ID of the client which is requesting the notification.
1.3220 +@param aResourceId ID for the resource whose notification of state changes is
1.3221 + being requested.
1.3222 +@param aN A reference to a notification object which encapsulates a callback
1.3223 + function to be called whenever the conditions to issue the notification
1.3224 + (specified in the API) are met.
1.3225 + NOTE: The client must create the notification object in kernel heap
1.3226 + or data section.
1.3227 +@param aThreshold The level of the resource state that will trigger the notification
1.3228 + when reached.
1.3229 +@param aDirection Specifies the direction of change of the resource state that will
1.3230 + trigger a notification. EFalse means the notification will be issued
1.3231 + when the resource state change to a specified threshold value or below
1.3232 + the specified threshold, ETrue means the notification will be issued
1.3233 + when the resource state change to a specified threshold value or above
1.3234 + the specified threshold.
1.3235 +
1.3236 +
1.3237 +
1.3238 +@return KErrNone if the operation of requesting a notification was successful.
1.3239 + KErrNotFound if this resource ID could not be found in the current list
1.3240 + of controllable reosurces.
1.3241 + KErrAccessDenied if the client ID could not be found in the list of
1.3242 + registered clients or if the client was registered to be thread
1.3243 + relative and this API is not called from the same thread.
1.3244 + KErrInUse if the passed notification object is used already.
1.3245 + KErrArgument if the specified threshold is out of range.
1.3246 +NOTE: This API should return immediately; however the notification will only
1.3247 +happen when a resource change occurs. Notification request is idempotent,
1.3248 +if the same notification has already been requested for this resource ID,
1.3249 +the API returns with no further action. Notification remain queued until they are cancelled.
1.3250 +
1.3251 +@pre Interrupts must be enabled
1.3252 +@pre Kernel must be unlocked
1.3253 +@pre No fast mutex can be held
1.3254 +@pre Call in a thread context but not from null thread or DFC thread1
1.3255 +@pre Can be used in a device driver
1.3256 +*/
1.3257 +TInt DPowerResourceController::RequestNotification(TUint aClientId, TUint aResourceId, DPowerResourceNotification& aN,
1.3258 + TInt aThreshold, TBool aDirection)
1.3259 + {
1.3260 + TInt r = KErrNone;
1.3261 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RequestNotification(conditional)"));
1.3262 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d, Threshold = %d, Direction = %d", \
1.3263 + aClientId, aResourceId, aThreshold, aDirection));
1.3264 + DThread& thread = Kern::CurrentThread();
1.3265 + CHECK_CONTEXT(thread)
1.3266 + Lock();
1.3267 + SPowerResourceClient* pC = NULL;
1.3268 + VALIDATE_CLIENT(thread);
1.3269 + if(!aResourceId)
1.3270 + {
1.3271 + r = KErrNotFound;
1.3272 + PRM_POSTNOTIFICATION_REGISTER_TRACE
1.3273 + UNLOCK_RETURN(r);
1.3274 + }
1.3275 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.3276 + DStaticPowerResource *pR = NULL;
1.3277 + GET_RESOURCE_FROM_LIST(aResourceId, pR)
1.3278 +#else
1.3279 + if(aResourceId > iStaticResourceArrayEntries)
1.3280 + {
1.3281 + r = KErrNotFound;
1.3282 + PRM_POSTNOTIFICATION_REGISTER_TRACE
1.3283 + UNLOCK_RETURN(r);
1.3284 + }
1.3285 +
1.3286 + DStaticPowerResource *pR = iStaticResourceArray[aResourceId-1];
1.3287 + if(!pR)
1.3288 + {
1.3289 + r = KErrNotFound;
1.3290 + PRM_POSTNOTIFICATION_REGISTER_TRACE
1.3291 + UNLOCK_RETURN(r);
1.3292 + }
1.3293 +#endif
1.3294 + if(aN.iRegistered) //Check if the same notification object is used already
1.3295 + {
1.3296 + r = KErrInUse;
1.3297 + PRM_POSTNOTIFICATION_REGISTER_TRACE
1.3298 + UNLOCK_RETURN(r);
1.3299 + }
1.3300 +
1.3301 + //Validate threshold for correctness
1.3302 + TPowerResourceInfoBuf01 buf;
1.3303 + r = pR->GetInfo((TDes8*)buf.Ptr());
1.3304 + if(r != KErrNone)
1.3305 + {
1.3306 + PRM_POSTNOTIFICATION_REGISTER_TRACE
1.3307 + UNLOCK_RETURN(r);
1.3308 + }
1.3309 + TPowerResourceInfoV01 *pBuf = (TPowerResourceInfoV01*)buf.Ptr();
1.3310 + if(((pBuf->iMinLevel > pBuf->iMaxLevel) && ((aThreshold > pBuf->iMinLevel) || (aThreshold < pBuf->iMaxLevel))) ||
1.3311 + ((pBuf->iMaxLevel > pBuf->iMinLevel) && ((aThreshold > pBuf->iMaxLevel) || (aThreshold < pBuf->iMinLevel))))
1.3312 + {
1.3313 + r = KErrArgument;
1.3314 + PRM_POSTNOTIFICATION_REGISTER_TRACE
1.3315 + UNLOCK_RETURN(r);
1.3316 + }
1.3317 + aN.iRegistered++;
1.3318 + aN.iType = DPowerResourceNotification::EConditional;
1.3319 + aN.iThreshold = aThreshold;
1.3320 + aN.iDirection = aDirection;
1.3321 + aN.iOwnerId = (TUint16)aClientId;
1.3322 + aN.iCallback.iClientId = aClientId;
1.3323 + aN.iCallback.iResourceId = aResourceId;
1.3324 + //Store the current level of the resource as will be used for issuing notification
1.3325 + aN.iPreviousLevel = pR->iCachedLevel;
1.3326 + //Add to resource notification list
1.3327 + pR->iNotificationList.Add(&(aN.iNotificationLink));
1.3328 + //Add to client notification list
1.3329 + LIST_PUSH(pC->iNotificationList, &aN, iNextInClient);
1.3330 + PRM_POSTNOTIFICATION_REGISTER_TRACE
1.3331 + UNLOCK_RETURN(KErrNone);
1.3332 + }
1.3333 +
1.3334 +/**
1.3335 +@publishedPartner
1.3336 +@prototype 9.5
1.3337 +
1.3338 +Cancel and remove from queue a previously issued request for notification on a
1.3339 +resource state change.
1.3340 +
1.3341 +@param aClientId ID of the client which is requesting to cancel the notification
1.3342 +@param aResourceId for the resource whose pending notification of state changes
1.3343 + is being cancelled.
1.3344 +@param aN A reference to the notification object that was associated with
1.3345 + the notification request that is being cancelled. This will be
1.3346 + used to identify the notification that is being cancelled.
1.3347 +
1.3348 +@return KErrCancel if the notification request was successfully cancelled.
1.3349 + KErrNotFound if the specified notification object is
1.3350 + not found in the current list of notification objects for the
1.3351 + specified resource.
1.3352 + KErrAccessDenied if the client requesting the cancellation is not the same
1.3353 + which registered the notification or if the resource id does not match or
1.3354 + if the client ID could not be found in the list of registered clients or
1.3355 + if the client was registered to be thread relative and this API is
1.3356 + not called from the same thread.
1.3357 +
1.3358 +@pre Interrupts must be enabled
1.3359 +@pre Kernel must be unlocked
1.3360 +@pre No fast mutex can be held
1.3361 +@pre Call in a thread context but not from null thread or DFC thread1
1.3362 +@pre Can be used in a device driver
1.3363 +*/
1.3364 +TInt DPowerResourceController::CancelNotification(TUint aClientId, TUint aResourceId, DPowerResourceNotification& aN)
1.3365 + {
1.3366 + TInt r = KErrCancel;
1.3367 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::CancelNotification"));
1.3368 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId = %d", aClientId, aResourceId));
1.3369 + DThread& thread = Kern::CurrentThread();
1.3370 + CHECK_CONTEXT(thread)
1.3371 + SPowerResourceClient* pC = NULL;
1.3372 + Lock();
1.3373 + VALIDATE_CLIENT(thread);
1.3374 +
1.3375 + if(!aN.iRegistered)
1.3376 + {
1.3377 + r = KErrNotFound;
1.3378 + PRM_POSTNOTIFICATION_DEREGISTER_TRACE
1.3379 + UNLOCK_RETURN(r);
1.3380 + }
1.3381 + //Remove from the client list
1.3382 + TBool found = EFalse;
1.3383 + DPowerResourceNotification* pCNL = pC->iNotificationList;
1.3384 + DPowerResourceNotification* pCNLNext = pCNL;
1.3385 + if(pCNL == &aN)
1.3386 + {
1.3387 + if(pCNL->iOwnerId != (TUint16)aClientId)
1.3388 + {
1.3389 + r = KErrAccessDenied;
1.3390 + PRM_POSTNOTIFICATION_DEREGISTER_TRACE
1.3391 + UNLOCK_RETURN(r);
1.3392 + }
1.3393 + found = ETrue;
1.3394 + }
1.3395 + else
1.3396 + {
1.3397 + while(pCNLNext)
1.3398 + {
1.3399 + if(pCNLNext == &aN)
1.3400 + {
1.3401 + if(pCNL->iOwnerId != (TUint16)aClientId)
1.3402 + {
1.3403 + r = KErrAccessDenied;
1.3404 + PRM_POSTNOTIFICATION_DEREGISTER_TRACE
1.3405 + UNLOCK_RETURN(r);
1.3406 + }
1.3407 + pCNL->iNextInClient = pCNLNext->iNextInClient;
1.3408 + pCNL = pCNLNext;
1.3409 + found = ETrue;
1.3410 + break;
1.3411 + }
1.3412 + pCNL = pCNLNext;
1.3413 + pCNLNext = pCNLNext->iNextInClient;
1.3414 + }
1.3415 + }
1.3416 + if(!found)
1.3417 + {
1.3418 + r = KErrNotFound;
1.3419 + PRM_POSTNOTIFICATION_DEREGISTER_TRACE
1.3420 + UNLOCK_RETURN(r);
1.3421 + }
1.3422 + if(pCNL->iCallback.iResourceId != aResourceId)
1.3423 + {
1.3424 + r = KErrAccessDenied;
1.3425 + PRM_POSTNOTIFICATION_DEREGISTER_TRACE
1.3426 + UNLOCK_RETURN(r);
1.3427 + }
1.3428 + //Remove from resource list
1.3429 + pCNL->iNotificationLink.Deque();
1.3430 + pCNL->iCallback.Cancel();
1.3431 + //Remove from client list
1.3432 + LIST_REMOVE(pC->iNotificationList, pCNL, iNextInClient, DPowerResourceNotification);
1.3433 + pCNL->iRegistered--;
1.3434 + PRM_POSTNOTIFICATION_DEREGISTER_TRACE
1.3435 + UNLOCK_RETURN(KErrCancel);
1.3436 + }
1.3437 +
1.3438 +/**
1.3439 +@publishedPartner
1.3440 +@prototype 9.5
1.3441 +
1.3442 +Request pre-allocation of specified number of client level and request message objects.
1.3443 +
1.3444 +@param aClientId ID of the client which is requesting the pre-allocation.
1.3445 +@param aNumCl Number of client level objects that needs to be pre-allocated
1.3446 + for this client.
1.3447 +@param aNumRm Number of request message objects that needs to be pre-allocated
1.3448 + for this client.
1.3449 +
1.3450 +@return KErrNone if the allocation was successful
1.3451 + KErrAccessDenied if the client ID could not be found in the list of
1.3452 + registered clients or if the client was registered to be thread
1.3453 + relative and this API is not called from the same thread.
1.3454 + KErrNoMemory if there is no sufficient memory for allocation of requested
1.3455 + number of objects.
1.3456 +
1.3457 +@pre Interrupts must be enabled
1.3458 +@pre Kernel must be unlocked
1.3459 +@pre No fast mutex can be held
1.3460 +@pre Call in a thread context but not from null thread or DFC thread1
1.3461 +@pre Can be used in a device driver
1.3462 +*/
1.3463 +TInt DPowerResourceController::AllocReserve(TUint aClientId, TUint8 aNumCl, TUint8 aNumRm)
1.3464 + {
1.3465 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::AllocReserve"));
1.3466 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, Numclients = %d, NumResource = %d", aClientId, aNumCl, aNumRm));
1.3467 + DThread& thread = Kern::CurrentThread();
1.3468 + CHECK_CONTEXT(thread)
1.3469 + SPowerResourceClient* pC = NULL;
1.3470 + Lock();
1.3471 + VALIDATE_CLIENT(thread);
1.3472 + //Call from thread Id.
1.3473 + TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
1.3474 + req->ReqType() = TPowerRequest::EAllocReserve;
1.3475 + req->ClientId() = aClientId;
1.3476 + req->RequestCount() = aNumRm;
1.3477 + req->ClientLevelCount() = aNumCl;
1.3478 +
1.3479 + UnLock();
1.3480 + req->SendReceive(iMsgQ);
1.3481 + return (req->ReturnCode());
1.3482 + }
1.3483 +/**
1.3484 +@internalComponent
1.3485 +@prototype 9.5
1.3486 +
1.3487 +This function runs in the context of the RC thread and
1.3488 +handles creation of memory pools.
1.3489 +*/
1.3490 +TInt DPowerResourceController::HandleReservationOfObjects(TPowerRequest& aRequest)
1.3491 + {
1.3492 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::AllocReserve"));
1.3493 +
1.3494 + SPowerResourceClientLevel* pCL = NULL;
1.3495 + SPowerRequest* pR = NULL;
1.3496 +
1.3497 + Lock();
1.3498 + TInt clientPoolCount = iClientLevelPoolCount;
1.3499 + TInt requestPoolCount = iRequestPoolCount;
1.3500 + SPowerResourceClient* pC;
1.3501 + if(aRequest.ClientId() & USER_SIDE_CLIENT_BIT_MASK)
1.3502 + pC = iUserSideClientList[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)];
1.3503 + else
1.3504 + pC = iClientList[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)];
1.3505 + UnLock();
1.3506 +
1.3507 + if(clientPoolCount < aRequest.ClientLevelCount())
1.3508 + {
1.3509 + //Grow the client level pool
1.3510 + // coverity[alloc_fn]
1.3511 + pCL = new SPowerResourceClientLevel[iClientLevelPoolGrowBy + aRequest.ClientLevelCount()];
1.3512 + if(!pCL)
1.3513 + return(KErrNoMemory);
1.3514 + }
1.3515 + if(requestPoolCount < aRequest.RequestCount())
1.3516 + {
1.3517 + //Grow the request pool
1.3518 + // coverity[alloc_fn]
1.3519 + pR = new SPowerRequest[iRequestPoolGrowBy + aRequest.RequestCount()];
1.3520 + if(!pR)
1.3521 + {
1.3522 + if(pCL) //If client level is allocated delete the same.
1.3523 + delete []pCL;
1.3524 + return(KErrNoMemory);
1.3525 + }
1.3526 + }
1.3527 + //Push the memory to list and adjust the counter.
1.3528 + Lock();
1.3529 + TUint count;
1.3530 + if(pCL)
1.3531 + {
1.3532 + for(count = 0;count<(TUint)(iClientLevelPoolGrowBy+aRequest.ClientLevelCount());count++)
1.3533 + LIST_PUSH(iClientLevelPool, &pCL[count], iNextInList);
1.3534 + iClientLevelPoolCount= (TUint16)(iClientLevelPoolCount + iClientLevelPoolGrowBy);
1.3535 + pC->iReservedCl= (TUint8)(pC->iReservedCl + aRequest.ClientLevelCount());
1.3536 + }
1.3537 + else
1.3538 + {
1.3539 + //Reserve memory from free pool to this client
1.3540 + iClientLevelPoolCount = (TUint16)(iClientLevelPoolCount - aRequest.ClientLevelCount());
1.3541 + pC->iReservedCl = (TUint8)(pC->iReservedCl + aRequest.ClientLevelCount());
1.3542 + }
1.3543 +
1.3544 + if(pR)
1.3545 + {
1.3546 + for(count=0;count<(TUint)(iRequestPoolGrowBy+aRequest.RequestCount());count++)
1.3547 + LIST_PUSH(iRequestPool, &pR[count], iNext);
1.3548 + iRequestPoolCount = (TUint16)(iRequestPoolCount + iRequestPoolGrowBy);
1.3549 + pC->iReservedRm =(TUint8)(pC->iReservedRm + aRequest.RequestCount());
1.3550 + }
1.3551 + else
1.3552 + {
1.3553 + //Reserve memory from free pool to this client
1.3554 + iRequestPoolCount = (TUint16)(iRequestPoolCount - aRequest.RequestCount());
1.3555 + pC->iReservedRm = (TUint8)(pC->iReservedRm + aRequest.RequestCount());
1.3556 + }
1.3557 + UnLock();
1.3558 +#ifdef PRM_INSTRUMENTATION_MACRO
1.3559 + TUint size =0;
1.3560 + if(pCL)
1.3561 + size = (iClientLevelPoolGrowBy+aRequest.ClientLevelCount())*sizeof(SPowerResourceClientLevel);
1.3562 + if(pR)
1.3563 + size += (iRequestPoolGrowBy+aRequest.RequestCount())*sizeof(SPowerRequest);
1.3564 + if(size)
1.3565 + PRM_MEMORY_USAGE_TRACE
1.3566 +#endif
1.3567 + return(KErrNone);
1.3568 + }
1.3569 +
1.3570 +/* Register the proxy client to resource controller.
1.3571 + This is called as the result of new user side client opening a channel.*/
1.3572 +TInt DPowerResourceController::RegisterProxyClient(TUint& aClientId, const TDesC8& aName)
1.3573 + {
1.3574 + GET_CRITICAL_SECTION_COUNT
1.3575 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterProxyClient"));
1.3576 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("Proxy client name %S", &aName));
1.3577 +
1.3578 + DThread& t = Kern::CurrentThread();
1.3579 + CHECK_CONTEXT(t)
1.3580 + //If number of expected user side clients is set to 0 during initial configuration
1.3581 + //then dont allow to configure user side clients.
1.3582 + if(!iUserSideClientList.GrowBy())
1.3583 + return KErrNotSupported;
1.3584 + //Maximum allowable length of a client's name is 32 characters.
1.3585 + if (aName.Length() > KMaxClientNameLength) return KErrTooBig;
1.3586 +
1.3587 + SPowerResourceClient *pC = NULL;
1.3588 + Lock();
1.3589 +#ifdef DEBUG_VERSION
1.3590 + if(!iUserSideClientList.Find(pC, (TDesC8&)aName))
1.3591 + {
1.3592 + UnLock();
1.3593 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.3594 + return KErrAlreadyExists;
1.3595 + }
1.3596 +#endif
1.3597 + TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
1.3598 + req->ReqType() = TPowerRequest::ERegisterUsersideClient;
1.3599 + UnLock();
1.3600 + req->SendReceive(iMsgQ);
1.3601 + if(req->ReturnCode() == KErrNone)
1.3602 + {
1.3603 + pC = iUserSideClientList[(TUint16)(req->ClientId() & ID_INDEX_BIT_MASK)];
1.3604 + pC->iName=&aName;
1.3605 + //Store the current thread Id;
1.3606 + pC->iThreadId = t.iId;
1.3607 + aClientId = pC->iClientId;
1.3608 + }
1.3609 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterProxyClient, clientId = 0x%x", aClientId));
1.3610 + PRM_CLIENT_REGISTER_TRACE
1.3611 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.3612 + return KErrNone;
1.3613 + }
1.3614 +
1.3615 +/* Deregister the specified user side client from resource controller.
1.3616 + This is called as the result of client closing the channel. */
1.3617 +TInt DPowerResourceController::DeregisterProxyClient(TUint aClientId)
1.3618 + {
1.3619 + GET_CRITICAL_SECTION_COUNT
1.3620 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::DeregisterProxyClient"));
1.3621 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x", aClientId));
1.3622 + DThread& t = Kern::CurrentThread();
1.3623 + CHECK_CONTEXT(t)
1.3624 + //Get the index from client ID
1.3625 + if(!(aClientId & USER_SIDE_CLIENT_BIT_MASK))
1.3626 + return KErrArgument;
1.3627 + Lock();
1.3628 + SPowerResourceClient* pC = iUserSideClientList[(TUint16)(aClientId & ID_INDEX_BIT_MASK)];
1.3629 + if(!pC)
1.3630 + {
1.3631 + UnLock();
1.3632 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.3633 + return KErrNotFound;
1.3634 + }
1.3635 + if(pC->iClientId != aClientId)
1.3636 + {
1.3637 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client ID does not match"));
1.3638 + UNLOCK_RETURN(KErrNotFound);
1.3639 + }
1.3640 + if(pC->iClientId & CLIENT_THREAD_RELATIVE_BIT_MASK)
1.3641 + {
1.3642 + if(pC->iThreadId != t.iId)
1.3643 + {
1.3644 + UnLock();
1.3645 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.3646 + return KErrAccessDenied;
1.3647 + }
1.3648 + }
1.3649 + //Check for any pending request
1.3650 + if(pC->iPendingReqCount)
1.3651 + {
1.3652 + UnLock();
1.3653 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.3654 + Panic(EClientHasPendingAsyncRequest);
1.3655 + }
1.3656 + //Check for notification request
1.3657 + if(pC->iNotificationList)
1.3658 + {
1.3659 + UnLock();
1.3660 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.3661 + Panic(EClientHasNotificationObject);
1.3662 + }
1.3663 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.3664 + if(pC->iDynamicResCount)
1.3665 + {
1.3666 + UnLock();
1.3667 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.3668 + Panic(DPowerResourceController::EClientHasDynamicResourceRegistered);
1.3669 + }
1.3670 +#endif
1.3671 + ResourceStateChangeOfClientLevels(pC);
1.3672 + //Add reserved request to pool
1.3673 + iRequestPoolCount = (TUint16)(iRequestPoolCount + pC->iReservedRm);
1.3674 + PRM_CLIENT_DEREGISTER_TRACE
1.3675 + //Increment the free pool count for client level and request level.
1.3676 + iUserSideClientList.Remove(pC, (TUint16)(pC->iClientId & ID_INDEX_BIT_MASK));
1.3677 + pC->iName = NULL;
1.3678 + iUserSideClientCount--; //Decrement client count
1.3679 + LIST_PUSH(iClientPool, pC, iNextInList);
1.3680 + UnLock();
1.3681 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.3682 + return KErrNone;
1.3683 + }
1.3684 +
1.3685 +/* This is called from power controller to cache the state of resource whose
1.3686 + state information it is interested in for accessing from null thread. This
1.3687 + list needs to be accessed from the Idle thread using direct access. */
1.3688 +TInt DPowerResourceController::RegisterResourcesForIdle(TInt aPowerControllerId, TUint aNumResources, TPtr* aBuf)
1.3689 + {
1.3690 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterResourceForIdle"));
1.3691 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("PowerControllerId = 0x%x, NumResources = %d", aPowerControllerId, aNumResources));
1.3692 +#ifdef DEBUG_VERSION //Surrounding with macro to avoid warnings.
1.3693 + DThread& t = Kern::CurrentThread();
1.3694 + CHECK_CONTEXT(t)
1.3695 +#endif
1.3696 + if(!aBuf)
1.3697 + return KErrArgument;
1.3698 + if((TUint)aPowerControllerId != iPowerControllerId)
1.3699 + return KErrAccessDenied;
1.3700 + if(iListForIdle) //Only one list is allowed.
1.3701 + return KErrInUse;
1.3702 + if((TUint)(aBuf->MaxLength() - aBuf->Length()) < (sizeof(SIdleResourceInfo) * aNumResources))
1.3703 + return KErrArgument;
1.3704 + GET_CRITICAL_SECTION_COUNT
1.3705 + Lock();
1.3706 + SIdleResourceInfo* pS=(SIdleResourceInfo*)aBuf->Ptr();
1.3707 + DStaticPowerResource* pR=NULL;
1.3708 + TUint count=0;
1.3709 + TUint id=0;
1.3710 + for(count=0;count<aNumResources;count++) //Check for valid resource ID.
1.3711 + {
1.3712 +#ifndef PRM_ENABLE_EXTENDED_VERSION
1.3713 + if((!pS->iResourceId) || (pS->iResourceId > iStaticResourceArrayEntries) || (!iStaticResourceArray[pS->iResourceId-1]))
1.3714 + {
1.3715 + UnLock();
1.3716 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.3717 + return KErrNotFound;
1.3718 + }
1.3719 +#else
1.3720 + if(pS->iResourceId & KIdMaskDynamic)
1.3721 + {
1.3722 + UnLock();
1.3723 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.3724 + return KErrNotSupported;
1.3725 + }
1.3726 + if((!pS->iResourceId) || ((pS->iResourceId & KIdMaskResourceWithDependencies) &&
1.3727 + (pS->iResourceId > iStaticResDependencyCount)) || (!(pS->iResourceId & KIdMaskResourceWithDependencies) &&
1.3728 + ((pS->iResourceId > iStaticResourceArrayEntries) || (!iStaticResourceArray[pS->iResourceId-1]))))
1.3729 + {
1.3730 + UnLock();
1.3731 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.3732 + return KErrNotFound;
1.3733 + }
1.3734 +#endif
1.3735 + pS++;
1.3736 + }
1.3737 + pS = (SIdleResourceInfo*)aBuf->Ptr();
1.3738 + for(count=0;count<aNumResources;count++)
1.3739 + {
1.3740 + id=pS->iResourceId;
1.3741 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.3742 + if(id & KIdMaskResourceWithDependencies) //Dependency resource
1.3743 + pR = iStaticResDependencyArray[(id & ID_INDEX_BIT_MASK)-1];
1.3744 + else
1.3745 +#endif
1.3746 + pR=iStaticResourceArray[id-1];
1.3747 + pS->iLevelOwnerId = pR->iLevelOwnerId;
1.3748 + pS->iCurrentLevel = pR->iCachedLevel;
1.3749 + pR->iIdleListEntry=pS;
1.3750 + pS++;
1.3751 + }
1.3752 + iListForIdle=(SIdleResourceInfo*)aBuf->Ptr();
1.3753 + pS = (SIdleResourceInfo*)aBuf->Ptr();
1.3754 + UnLock();
1.3755 + LOCK_AND_CRITICAL_SECTION_COUNT_CHECK
1.3756 + return KErrNone;
1.3757 + }
1.3758 +
1.3759 +/**
1.3760 +@publishedPartner
1.3761 +@prototype 9.6
1.3762 +
1.3763 +Request to deregister client level from the specified resource for the specified client.
1.3764 +
1.3765 +@param aClientId ID of the client which is requesting the deregistration of client level.
1.3766 +@param aResourceId ID of the resource from which to remove the specified client's level.
1.3767 +
1.3768 +@return KErrNone if successful
1.3769 + KErrAccessDenied if the client ID could not be found in the list of registered clients or
1.3770 + if the client was registered to be thread relative and this API is not
1.3771 + called from the same thread.
1.3772 + KErrNotFound if the resource ID could not be found in the current list of controllable
1.3773 + resources or if the client is not holding any level with the specified
1.3774 + resource (no client level found for the specified client).
1.3775 +
1.3776 +@pre Interrupts must be enabled
1.3777 +@pre Kernel must be unlocked
1.3778 +@pre No fast mutex can be held
1.3779 +@pre Call in a thread context but not from null thread or DFC thread1
1.3780 +@pre Can be used in a device driver.
1.3781 +*/
1.3782 +TInt DPowerResourceController::DeRegisterClientLevelFromResource(TUint aClientId, TUint aResourceId)
1.3783 + {
1.3784 + TInt r = KErrNone;
1.3785 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::DeRegisterClientLevelFromResource\n"));
1.3786 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("aClientId = 0x%x, aResourceId = 0x%x\n", aClientId, aResourceId));
1.3787 + DThread& thread = Kern::CurrentThread();
1.3788 + CHECK_CONTEXT(thread)
1.3789 + SPowerResourceClient* pC = NULL;
1.3790 + Lock();
1.3791 + VALIDATE_CLIENT(thread);
1.3792 + //Validate resource
1.3793 + if((!aResourceId))
1.3794 + {
1.3795 + UNLOCK_RETURN(KErrNotFound);
1.3796 + }
1.3797 + DStaticPowerResource *pR = NULL;
1.3798 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.3799 + GET_RESOURCE_FROM_LIST(aResourceId, pR)
1.3800 + if(aResourceId & KIdMaskDynamic)
1.3801 + ((DDynamicPowerResource*)pR)->Lock();
1.3802 +#else
1.3803 + if(aResourceId > iStaticResourceArrayEntries)
1.3804 + {
1.3805 + UNLOCK_RETURN(KErrNotFound);
1.3806 + }
1.3807 + pR = iStaticResourceArray[aResourceId - 1];
1.3808 + if(!pR)
1.3809 + UNLOCK_RETURN(KErrNotFound);
1.3810 +#endif
1.3811 + //Need to change the state of the resource if the client is holding the current resource.
1.3812 + if((pR->iLevelOwnerId == (TInt)aClientId) || (pR->Sense() == DStaticPowerResource::ECustom))
1.3813 + {
1.3814 + //If Longlatency resource then process it in the resource controller thread
1.3815 + TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
1.3816 + req->ResourceId() = aResourceId;
1.3817 + req->ReqType() = TPowerRequest::ESetDefaultLevel;
1.3818 + req->ClientId() = aClientId;
1.3819 + req->Resource() = pR;
1.3820 + req->ResourceCb() = NULL;
1.3821 +#ifdef PRM_INSTRUMENTATION_MACRO
1.3822 + //Setting to current state as exact state will be known only before calling the PSL.
1.3823 + TInt aNewState = pR->iCachedLevel;
1.3824 + PRM_CLIENT_CHANGE_STATE_START_TRACE
1.3825 +#endif
1.3826 + if(pR->LatencySet())
1.3827 + {
1.3828 + UnLock();
1.3829 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.3830 + if(pR->iResourceId & KIdMaskResourceWithDependencies) //Dependency resource
1.3831 + {
1.3832 + r = req->SendReceive(iMsgQDependency); // Send the request to DFC thread.
1.3833 + }
1.3834 + else
1.3835 +#endif
1.3836 + {
1.3837 + r = req->SendReceive(iMsgQ); //Long latency resource request are processed in controller thread.
1.3838 + }
1.3839 + Lock();
1.3840 + }
1.3841 + else if(pR->Usage())
1.3842 + {
1.3843 + //Shared resource
1.3844 + //Not checking the return value here because there is no allocation of client levels.
1.3845 + CheckLevelAndAddClient(pC, req);
1.3846 + }
1.3847 + else
1.3848 + {
1.3849 + //Single user set it to default
1.3850 + req->ClientId() = -1;
1.3851 + req->ReqType() = TPowerRequest::ESetDefaultLevel;
1.3852 + }
1.3853 + //Change the state of resource for instantaneous resource.
1.3854 + if((!pR->LatencySet()) && ((!pR->Usage()) || (pR->Usage() && req->RequiresChange())))
1.3855 + {
1.3856 + UnLock();
1.3857 + r = pR->DoRequest(*req);
1.3858 + Lock();
1.3859 + if(r == KErrNone)
1.3860 + {
1.3861 + //Complete notifications
1.3862 + CompleteNotifications(req->ClientId(), pR, req->Level(), KErrNone, req->ClientId(), EFalse);
1.3863 + //Update the cache
1.3864 + pR->iLevelOwnerId = req->ClientId();
1.3865 + pR->iCachedLevel = req->Level();
1.3866 + if(pR->iIdleListEntry)
1.3867 + {
1.3868 + pR->iIdleListEntry->iLevelOwnerId = req->ClientId();
1.3869 + pR->iIdleListEntry->iCurrentLevel = req->Level();
1.3870 + }
1.3871 + }
1.3872 + }
1.3873 +#ifdef PRM_INSTRUMENTATION_MACRO
1.3874 + if(!pR->LatencySet())
1.3875 + {
1.3876 + aNewState = req->Level();
1.3877 + PRM_CLIENT_CHANGE_STATE_END_TRACE
1.3878 + }
1.3879 +#endif
1.3880 + }
1.3881 + //Remove clientLevel from client
1.3882 + r = KErrNotFound;
1.3883 + for(SPowerResourceClientLevel* pCL = pC->iLevelList; pCL != NULL; pCL= pCL->iNextInList)
1.3884 + {
1.3885 + if(pCL->iResourceId == aResourceId)
1.3886 + {
1.3887 + LIST_REMOVE(pC->iLevelList, pCL, iNextInList, SPowerResourceClientLevel);
1.3888 + //Remove from Resource
1.3889 + pCL->Deque();
1.3890 + LIST_PUSH(iClientLevelPool,pCL,iNextInList); // back to free pool
1.3891 + if(pC->iUnderFlowClCount > 0)
1.3892 + {
1.3893 + pC->iUnderFlowClCount--;
1.3894 + iClientLevelPoolCount++;
1.3895 + }
1.3896 + else
1.3897 + pC->iReservedCl++;
1.3898 + r = KErrNone;
1.3899 + break;
1.3900 + }
1.3901 + }
1.3902 +#ifdef PRM_ENABLE_EXTENDED_VERSION
1.3903 + if(aResourceId & KIdMaskDynamic)
1.3904 + ((DDynamicPowerResource*)pR)->UnLock();
1.3905 +#endif
1.3906 + UNLOCK_RETURN(r);
1.3907 + }
1.3908 +
1.3909 +/**
1.3910 +@publishedPartner
1.3911 +@prototype 9.5
1.3912 +
1.3913 +Interface to provide extended functionality.This provides support
1.3914 +to register and deregister dynamic resources and handling of resource dependency, registering
1.3915 +and deregistering resource dependency.
1.3916 +This is not supported in basic version
1.3917 +
1.3918 +@pre Interrupts must be enabled
1.3919 +@pre Kernel must be unlocked
1.3920 +@pre No fast mutex can be held
1.3921 +@pre Call in a thread context but not from null thread or DFC thread1
1.3922 +@pre Can be used in a device driver.
1.3923 +*/
1.3924 +TInt DPowerResourceController::GetInterface(TUint aClientId, TUint aInterfaceId, TAny* aParam1, TAny* aParam2,
1.3925 + TAny* aParam3)
1.3926 + {
1.3927 + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetInterface"));
1.3928 + DThread& thread = Kern::CurrentThread();
1.3929 + CHECK_CONTEXT(thread)
1.3930 + if((iInitialised != EResConStartupCompleted) && (aInterfaceId != KResManControlIoGetVersion))
1.3931 + return KErrNotSupported;
1.3932 + TInt r = KErrNone;
1.3933 + Lock();
1.3934 + SPowerResourceClient* pC = NULL;
1.3935 + VALIDATE_CLIENT(thread);
1.3936 +#ifndef PRM_ENABLE_EXTENDED_VERSION
1.3937 + if(aInterfaceId == KResManControlIoGetVersion)
1.3938 + {
1.3939 + if(!aParam1)
1.3940 + r = KErrArgument;
1.3941 + else
1.3942 + *(TUint*)aParam1 = KResControllerBasicVersion;
1.3943 + }
1.3944 + else
1.3945 + r = KErrNotSupported;
1.3946 + (void) aParam2;
1.3947 + (void) aParam3;
1.3948 +#else
1.3949 + //User side client is not allowed to register/deregister dynamic resource and dependencies
1.3950 + if((aClientId & USER_SIDE_CLIENT_BIT_MASK) && (aInterfaceId >= KResManControlIoRegisterDynamicResource) &&
1.3951 + (aInterfaceId <= KResManControlIoDeregisterDependency))
1.3952 + return KErrAccessDenied;
1.3953 + switch (aInterfaceId)
1.3954 + {
1.3955 + case KResManControlIoGetVersion:
1.3956 + {
1.3957 + if(!aParam1)
1.3958 + r = KErrArgument;
1.3959 + else
1.3960 + *(TUint*)aParam1 = KResControllerExtendedVersion;
1.3961 + break;
1.3962 + }
1.3963 + case KResManControlIoRegisterDynamicResource:
1.3964 + {
1.3965 + r = RegisterDynamicResource(pC, (DDynamicPowerResource *)aParam1, (TUint*)aParam2);
1.3966 + break;
1.3967 + }
1.3968 + case KResManControlIoDeregisterDynamicResource:
1.3969 + {
1.3970 + r = DeregisterDynamicResource(pC, (TUint)aParam1, (TInt*)aParam2);
1.3971 + break;
1.3972 + }
1.3973 + case KResManControlIoRegisterDependency:
1.3974 + {
1.3975 +
1.3976 + r = RegisterResourceDependency(pC, (SResourceDependencyInfo*)aParam1, (SResourceDependencyInfo*)aParam2);
1.3977 + break;
1.3978 + }
1.3979 + case KResManControlIoDeregisterDependency:
1.3980 + {
1.3981 + r = DeregisterResourceDependency(pC, (TUint)aParam1, (TUint)aParam2);
1.3982 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetInterface"));
1.3983 + return(r);
1.3984 + }
1.3985 + case KResManControlIoGetNumDependents:
1.3986 + {
1.3987 + r = GetNumDependentsForResource((TUint)aParam1, (TUint*)aParam2);
1.3988 + break;
1.3989 + }
1.3990 + case KResManControlIoGetDependentsId:
1.3991 + {
1.3992 + r = GetDependentsIdForResource((TUint)aParam1, (TAny*)aParam2, (TUint*)aParam3);
1.3993 + break;
1.3994 + }
1.3995 + default:
1.3996 + {
1.3997 + r = KErrNotSupported;
1.3998 + break;
1.3999 + }
1.4000 + }
1.4001 +#endif
1.4002 + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetInterface"));
1.4003 + UNLOCK_RETURN(r);
1.4004 + }
1.4005 +