sl@0: // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32\drivers\resmanus\d_resmanus.cpp sl@0: // sl@0: // sl@0: sl@0: // LDD for Resource Manager user side API sl@0: #include "resmanus.h" sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #ifdef RESOURCE_MANAGER_SIMULATED_PSL sl@0: #include "rescontrol_psl.h" sl@0: #endif sl@0: sl@0: #ifdef PRM_US_INSTRUMENTATION_MACRO sl@0: #include sl@0: #endif sl@0: sl@0: #ifdef PRM_ENABLE_EXTENDED_VERSION2 sl@0: _LIT(KResManUsThreadName,"ResManUsExtendedCoreLddThread"); sl@0: #elif defined (PRM_ENABLE_EXTENDED_VERSION) sl@0: _LIT(KResManUsThreadName,"ResManUsExtendedLddThread"); sl@0: #else sl@0: _LIT(KResManUsThreadName,"ResManUsLddThread"); sl@0: #endif sl@0: sl@0: #define RESMANUS_FAULT() Kern::Fault("RESMANUS",__LINE__) sl@0: sl@0: const TInt KResManUsThreadPriority = 24; sl@0: const TInt KResManUsRegistrationPriority = 5; // Arbitrary! Can be 0-7, 7 is highest sl@0: const TInt KResManCallBackPriority = 5; // Arbitrary! Can be 0-7, 7 is highest sl@0: sl@0: //Macro to return appropriate request type. sl@0: #define GET_USER_REQUEST(request, buffer, type) \ sl@0: { \ sl@0: if(type == EGetState) \ sl@0: request = ((TTrackGetStateBuf*)buffer)->iRequest; \ sl@0: else if(type == ESetState) \ sl@0: request = ((TTrackSetStateBuf*)buffer)->iRequest; \ sl@0: else \ sl@0: request = ((TTrackNotifyBuf*)buffer)->iRequest; \ sl@0: } sl@0: sl@0: /*************************************************************************************** sl@0: class TTrackGetStateBuf sl@0: ***************************************************************************************/ sl@0: TTrackGetStateBuf::TTrackGetStateBuf(TPowerResourceCbFn aFn, TAny* aPtr, sl@0: TDfcQue* aQue, TInt aPriority) sl@0: : iCtrlBlock(aFn, aPtr, aQue, aPriority) sl@0: { sl@0: iRequest = NULL; sl@0: } sl@0: sl@0: /*************************************************************************************** sl@0: class TTrackSetStateBuf sl@0: ***************************************************************************************/ sl@0: TTrackSetStateBuf::TTrackSetStateBuf(TPowerResourceCbFn aFn, TAny* aPtr, sl@0: TDfcQue* aQue, TInt aPriority) sl@0: : iCtrlBlock(aFn, aPtr, aQue, aPriority) sl@0: { sl@0: iRequest = NULL; sl@0: } sl@0: sl@0: /*************************************************************************************** sl@0: class TTrackNotifyBuf sl@0: ***************************************************************************************/ sl@0: TTrackNotifyBuf::TTrackNotifyBuf(TPowerResourceCbFn aFn, TAny* aPtr, sl@0: TDfcQue* aQue, TInt aPriority) sl@0: : iNotifyBlock(aFn, aPtr, aQue, aPriority) sl@0: { sl@0: iRequest = NULL; sl@0: } sl@0: sl@0: TTrackNotifyBuf::~TTrackNotifyBuf() sl@0: { sl@0: if(iRequest) sl@0: Kern::DestroyClientRequest(iRequest); sl@0: } sl@0: sl@0: TTrackSetStateBuf::~TTrackSetStateBuf() sl@0: { sl@0: if(iRequest) sl@0: Kern::DestroyClientRequest(iRequest); sl@0: } sl@0: sl@0: TTrackGetStateBuf::~TTrackGetStateBuf() sl@0: { sl@0: if(iRequest) sl@0: Kern::DestroyClientRequest(iRequest); sl@0: } sl@0: sl@0: /*************************************************************************************** sl@0: class DDeviceResManUs sl@0: ***************************************************************************************/ sl@0: DDeviceResManUs::DDeviceResManUs() sl@0: // Constructor sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceResManUs::DDeviceResManUs()")); sl@0: iParseMask=KDeviceAllowAll&~KDeviceAllowUnit; // Allow info and pdd, but not units sl@0: iUnitsMask=0; sl@0: iVersion=TVersion(KResManUsMajorVersionNumber, sl@0: KResManUsMinorVersionNumber, sl@0: KResManUsBuildVersionNumber); sl@0: } sl@0: sl@0: DDeviceResManUs::~DDeviceResManUs() sl@0: // Destructor sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceResManUs::~DDeviceResManUs()")); sl@0: #ifdef RESOURCE_MANAGER_SIMULATED_PSL sl@0: iSharedDfcQue->Destroy(); sl@0: #else sl@0: delete iSharedDfcQue; sl@0: #endif sl@0: } sl@0: sl@0: TInt DDeviceResManUs::Install() sl@0: // Install the device driver. sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceResManUs::Install()")); sl@0: // Create the message queue and initialise the DFC queue pointer sl@0: #ifndef RESOURCE_MANAGER_SIMULATED_PSL sl@0: TInt r=Kern::DfcQInit(iSharedDfcQue,KResManUsThreadPriority,&KResManUsThreadName); sl@0: #else sl@0: TInt r = Kern::DynamicDfcQCreate(iSharedDfcQue,KResManUsThreadPriority,KResManUsThreadName); sl@0: #endif sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DfcQCreate r = %d", r)); sl@0: if(r!=KErrNone) sl@0: return r; sl@0: sl@0: #ifdef CPU_AFFINITY_ANY sl@0: NKern::ThreadSetCpuAffinity((NThread*)(iSharedDfcQue->iThread), KCpuAffinityAny); sl@0: #endif sl@0: r = SetName(&KLddRootName); sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> SetName, r = %d", r)); sl@0: return r; sl@0: } sl@0: sl@0: sl@0: void DDeviceResManUs::GetCaps(TDes8& aDes) const sl@0: // Return the ResManUs capabilities. sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceResManUs::GetCaps(TDes8& aDes) const")); sl@0: TPckgBuf b; sl@0: b().version=TVersion(KResManUsMajorVersionNumber, sl@0: KResManUsMinorVersionNumber, sl@0: KResManUsBuildVersionNumber); sl@0: Kern::InfoCopy(aDes,b); sl@0: } sl@0: sl@0: sl@0: TInt DDeviceResManUs::Create(DLogicalChannelBase*& aChannel) sl@0: // Create a channel on the device. sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DDeviceResManUs::Create(DLogicalChannelBase*& aChannel)")); sl@0: if(iOpenChannels>=KMaxNumChannels) sl@0: return KErrOverflow; sl@0: aChannel=new DChannelResManUs; sl@0: return aChannel?KErrNone:KErrNoMemory; sl@0: } sl@0: sl@0: sl@0: /*************************************************************************************** sl@0: class DChannelResManUs sl@0: ***************************************************************************************/ sl@0: DChannelResManUs::DChannelResManUs() sl@0: // Constructor sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::DChannelResManUs()")); sl@0: iClient=&Kern::CurrentThread(); sl@0: // Increase the DThread's ref count so that it does not close without us sl@0: iClient->Open(); sl@0: } sl@0: sl@0: sl@0: DChannelResManUs::~DChannelResManUs() sl@0: // Destructor sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::~DChannelResManUs()")); sl@0: sl@0: // Cancel any outstanding requests sl@0: // sl@0: // For each tracker (Get, Set and notify) sl@0: // sl@0: if(iGetStateTracker != NULL) sl@0: { sl@0: CancelTrackerRequests(iGetStateTracker,EFalse,0,NULL); // EFalse,0, to ignore resource IDs sl@0: RemoveTrackingControl(iGetStateTracker); sl@0: } sl@0: if(iSetStateTracker != NULL) sl@0: { sl@0: CancelTrackerRequests(iSetStateTracker,EFalse,0,NULL); // EFalse,0, to ignore resource IDs sl@0: RemoveTrackingControl(iSetStateTracker); sl@0: } sl@0: if(iListenableTracker != NULL) sl@0: { sl@0: CancelTrackerRequests(iListenableTracker,EFalse,0,NULL); // EFalse,0, to ignore resource IDs sl@0: RemoveTrackingControl(iListenableTracker); sl@0: } sl@0: sl@0: delete iUserNameUsed; sl@0: delete iResourceDependencyIds; sl@0: delete iClientNamesResCtrl; sl@0: delete iResourceInfoResCtrl; sl@0: sl@0: // decrement the DThread's reference count sl@0: Kern::SafeClose((DObject*&)iClient, NULL); sl@0: } sl@0: sl@0: sl@0: static void AsyncCallBackFn(TUint aClient, TUint aResourceId, TInt aLevel, TInt aLevelOwnerId, TInt aResult, TAny* aTrackingBuffer) sl@0: { sl@0: // Callback function for asynchronous requests sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> AsyncCallBackFn aClient=0x%x aResourceId=0x%x, aLevel=0x%x, aResult=0x%x, aTrackingBuffer=0x%x\n",aClient, aResourceId, aLevel, aResult, aTrackingBuffer)); sl@0: TTrackingBuffer* buffer = ((TTrackingBuffer*)aTrackingBuffer); sl@0: TTrackingControl* tracker = buffer->GetTrackingControl(); sl@0: __ASSERT_ALWAYS((tracker!=NULL),RESMANUS_FAULT()); sl@0: DChannelResManUs* channel = tracker->iOwningChannel; sl@0: sl@0: #ifdef PRM_US_INSTRUMENTATION_MACRO sl@0: if(tracker->iType==EGetState) sl@0: { sl@0: PRM_US_GET_RESOURCE_STATE_END_TRACE; sl@0: } sl@0: else if(tracker->iType==ESetState) sl@0: { sl@0: PRM_US_SET_RESOURCE_STATE_END_TRACE; sl@0: } sl@0: #endif sl@0: if(tracker->iType == EGetState) sl@0: { sl@0: TTrackGetStateBuf* stateBuf = (TTrackGetStateBuf*)aTrackingBuffer; sl@0: if(aResult==KErrNone) sl@0: { sl@0: // Write the state value to the user-supplied variable sl@0: stateBuf->iRequest->Data1() = aLevel; sl@0: stateBuf->iRequest->Data2() = aLevelOwnerId; sl@0: } sl@0: Kern::QueueRequestComplete(channel->iClient, ((TTrackGetStateBuf*)buffer)->iRequest, aResult); sl@0: } sl@0: else if(tracker->iType == ESetState) sl@0: { sl@0: Kern::QueueRequestComplete(channel->iClient, ((TTrackSetStateBuf*)buffer)->iRequest, aResult); sl@0: } sl@0: // Once notified of a change in a resource state, must cancel the notification sl@0: // request in the Resource Controller to give the client the appearance of a sl@0: // 'one'shot' type of operation. sl@0: else if(tracker->iType==ENotify) sl@0: { sl@0: #ifdef PRM_ENABLE_EXTENDED_VERSION sl@0: if(((TInt)aClient==KDynamicResourceDeRegistering)&&(aResourceId&KIdMaskDynamic)) sl@0: { sl@0: // Resource has de-registered from Resource Controller, so can't expect any more notifications sl@0: // of this type. Cancellation of notifications (i.e. invoke Resource Controller) and transfer of sl@0: // buffers to free queue (for both conditional and unconditional notifications) is already done. sl@0: // To distinguish removal of a dynamic resource, hijack aResult (the value used when completing sl@0: // the user-side TRequestStatus object) and set it to KErrDisconnected. sl@0: aResult = KErrDisconnected; sl@0: } sl@0: sl@0: #endif sl@0: TInt r = (channel->iPddPtr)->CancelNotification(channel->ClientHandle(),aResourceId, sl@0: ((TTrackNotifyBuf*)buffer)->iNotifyBlock); sl@0: __ASSERT_ALWAYS((r == KErrCancel),RESMANUS_FAULT()); sl@0: Kern::QueueRequestComplete(channel->iClient, ((TTrackNotifyBuf*)buffer)->iRequest, aResult); sl@0: } sl@0: sl@0: // Return the tracking buffer to the free queue sl@0: channel->FreeTrackingBuffer(buffer); sl@0: } sl@0: sl@0: TInt DChannelResManUs::GetValidName(const TDesC8* aInfo) sl@0: { sl@0: // Extract a usable name from that supplied by the client sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DChannelResManUs::GetValidName")); sl@0: TInt err=KErrNone; sl@0: if(aInfo) sl@0: { sl@0: DThread* thread = &Kern::CurrentThread(); sl@0: TInt nameLen = Kern::ThreadGetDesLength(thread, aInfo); sl@0: if(nameLen<0) sl@0: return nameLen; // return error code sl@0: iNameProvidedLength = nameLen; sl@0: if(nameLen > MAX_CLIENT_NAME_LENGTH) sl@0: err=KErrBadName; sl@0: else sl@0: { sl@0: nameLen = (nameLen<=MAX_NAME_LENGTH_IN_RESMAN) ? nameLen : MAX_NAME_LENGTH_IN_RESMAN; sl@0: if((iUserNameUsed = HBuf8::New(nameLen))==NULL) sl@0: return KErrNoMemory; sl@0: err = Kern::ThreadDesRead(thread,aInfo,*iUserNameUsed,0); sl@0: if(err!=KErrNone) sl@0: return err; sl@0: } sl@0: } sl@0: else sl@0: err=KErrBadName; sl@0: return err; sl@0: } sl@0: sl@0: TInt DChannelResManUs::RequestUserHandle(DThread* aThread, TOwnerType aType) sl@0: // Called when a user thread requests a handle to this channel sl@0: { sl@0: // Make sure that only our client can get a handle sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DChannelResManUs::RequestUserHandle")); sl@0: if (aType!=EOwnerThread || aThread!=iClient) sl@0: return KErrAccessDenied; sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DChannelResManUs::RegistrationDfcFunc(TAny* aChannel) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DChannelResManUs::RegistrationDfcFunc")); sl@0: // DFC function invoked for registration with Resource Controller sl@0: DChannelResManUs* channel = (DChannelResManUs*)aChannel; sl@0: // RegisterProxyClient(TUint& aProxyId, const TDesC& aName); sl@0: TUint uintVal=0; sl@0: TInt r = KErrNone; sl@0: __ASSERT_ALWAYS((r==KErrNone),RESMANUS_FAULT()); sl@0: sl@0: r=(channel->iPddPtr)->RegisterProxyClient(uintVal,*((TDesC8*)(channel->iUserNameUsed))); sl@0: if(r!=KErrNone) sl@0: { sl@0: // Registration failed sl@0: // Ensure that the client-side flag is cleared in uintVal sl@0: // so the failure can be detected in DoCreate sl@0: uintVal &= ~USER_SIDE_CLIENT_BIT_MASK; // Copied from rescontrol_export sl@0: } sl@0: channel->SetClientHandle((TInt)uintVal); sl@0: NKern::FSSignal(channel->iFastSem); sl@0: } sl@0: sl@0: sl@0: TInt DChannelResManUs::RegisterWithResCtrlr() sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DChannelResManUs::RegisterWithResCtrlr")); sl@0: TInt r = KErrNone; sl@0: // Initialise the channel's fast semaphore sl@0: iFastSem = new NFastSemaphore(); sl@0: if(iFastSem == NULL) sl@0: r = KErrNoMemory; sl@0: else sl@0: { sl@0: iFastSem->iOwningThread = (NThreadBase*)NKern::CurrentThread(); sl@0: sl@0: // Attempt to perform registration with the Resource Controller on behalf of the client. sl@0: SetDfcQ(((DDeviceResManUs*)(iDevice))->iSharedDfcQue); sl@0: TDfc tempDfc(RegistrationDfcFunc, this, iDfcQ, KResManUsRegistrationPriority); sl@0: sl@0: // Block this thread until the DFC has executed sl@0: tempDfc.Enque(); sl@0: NKern::FSWait(iFastSem); sl@0: // Have finished with iFastSem sl@0: delete iFastSem; sl@0: sl@0: // Registration complete - check success sl@0: if(!(USER_SIDE_CLIENT_BIT_MASK & ClientHandle())) sl@0: { sl@0: // Registration failed sl@0: r = KErrCouldNotConnect; sl@0: } sl@0: // Start receiving messages ... sl@0: iMsgQ.Receive(); sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: TInt DChannelResManUs::DoCreate(TInt /*aUnit*/, sl@0: const TDesC8* aInfo, sl@0: const TVersion &aVer) sl@0: // Create the channel from the passed info. sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer)")); sl@0: sl@0: TInt r = KErrNone; sl@0: iPddPtr = ((DUserSideProxyInterface*)iPdd)->iController; sl@0: // Check client has appropriate capabilities sl@0: if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by DDevicePowerRsrc::Create"))) sl@0: return KErrPermissionDenied; sl@0: sl@0: // Check software version sl@0: if (!Kern::QueryVersionSupported(TVersion(KResManUsMajorVersionNumber, sl@0: KResManUsMinorVersionNumber, sl@0: KResManUsBuildVersionNumber), sl@0: aVer)) sl@0: return KErrNotSupported; sl@0: sl@0: // Implementation note: if this method fails, the destructor will be invoked sl@0: // as part of which all successfully-allocated memory will be freed. Therefore, sl@0: // no memory will be explicitly freed in the event of failure in the code which follows. sl@0: sl@0: // Allocate the arrays used for acquiring client, resource and dependency information sl@0: if((iClientNamesResCtrl = HBuf8::New(KNumClientNamesResCtrl * sizeof(TPowerClientInfoV01)))==NULL) sl@0: return KErrNoMemory; sl@0: if((iResourceInfoResCtrl = HBuf8::New(KNumResourceInfoResCtrl * sizeof(TPowerResourceInfoV01)))==NULL) sl@0: return KErrNoMemory; sl@0: if((iResourceDependencyIds = HBuf8::New(KNumResourceDependencies * sizeof(SResourceDependencyInfo)))==NULL) sl@0: return KErrNoMemory; sl@0: // Obtain the channel name to use sl@0: if((r=GetValidName(aInfo))!=KErrNone) sl@0: return r; sl@0: #ifdef PRM_ENABLE_EXTENDED_VERSION sl@0: iResDepsValid = 0; sl@0: #endif sl@0: sl@0: #ifdef PRM_US_INSTRUMENTATION_MACRO sl@0: PRM_US_OPEN_CHANNEL_START_TRACE; sl@0: #endif sl@0: sl@0: // Set up the request tracking support sl@0: iGetStateTracker = new TTrackingControl(); sl@0: iSetStateTracker = new TTrackingControl();; sl@0: iListenableTracker = new TTrackingControl(); sl@0: if((iGetStateTracker==NULL) || (iSetStateTracker==NULL) || (iListenableTracker==NULL)) sl@0: return KErrNoMemory; sl@0: sl@0: // Register with the Resource Controller sl@0: r = RegisterWithResCtrlr(); sl@0: sl@0: #ifdef PRM_US_INSTRUMENTATION_MACRO sl@0: PRM_US_OPEN_CHANNEL_END_TRACE; sl@0: #endif sl@0: sl@0: return r; sl@0: } sl@0: sl@0: //Override sendMsg to allow data copy in the context of client thread for WDP. sl@0: TInt DChannelResManUs::SendMsg(TMessageBase* aMsg) sl@0: { sl@0: TThreadMessage& m = *(TThreadMessage*)aMsg; sl@0: TInt id = m.iValue; sl@0: TInt r = KErrNone; sl@0: if (id != (TInt)ECloseMsg && id != KMaxTInt) sl@0: { sl@0: if (id<0) sl@0: { sl@0: TRequestStatus* pS=(TRequestStatus*)m.Ptr0(); sl@0: r = SendRequest(aMsg); sl@0: if (r != KErrNone) sl@0: Kern::RequestComplete(pS,r); sl@0: } sl@0: else sl@0: r = SendControl(aMsg); sl@0: } sl@0: else sl@0: r = DLogicalChannel::SendMsg(aMsg); sl@0: return r; sl@0: } sl@0: sl@0: TInt DChannelResManUs::SendRequest(TMessageBase* aMsg) sl@0: { sl@0: TThreadMessage& m = *(TThreadMessage*)aMsg; sl@0: TInt id = ~m.iValue; sl@0: TRequestStatus* pS = (TRequestStatus*)m.Ptr0(); sl@0: TInt r = KErrNone; sl@0: TTrackingBuffer *trackBuf = NULL; sl@0: TUint parms[4]; sl@0: TPowerResourceCb *callBack; sl@0: DPowerResourceNotification *prn; sl@0: sl@0: switch(id) sl@0: { sl@0: case RBusDevResManUs::EChangeResourceState: sl@0: { sl@0: __ASSERT_ALWAYS(m.Ptr2() != NULL, RESMANUS_FAULT()); sl@0: #ifdef _DUMP_TRACKERS sl@0: if((r=DumpTracker(iSetStateTracker))!=KErrNone) sl@0: break; sl@0: #endif sl@0: r = GetAndInitTrackingBuffer(iSetStateTracker, trackBuf, (TUint)m.Ptr1(), pS); sl@0: if( r != KErrNone) sl@0: return r; sl@0: callBack = &(((TTrackSetStateBuf*)trackBuf)->iCtrlBlock); sl@0: new (callBack) TPowerResourceCb(&AsyncCallBackFn, (TAny*)trackBuf, iDfcQ, KResManCallBackPriority); sl@0: parms[0] = (TUint)m.Ptr2(); sl@0: parms[1] = (TUint)callBack; sl@0: m.iArg[2] = &(parms[0]); sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetResourceState: sl@0: { sl@0: __ASSERT_ALWAYS(m.Ptr2() != NULL, RESMANUS_FAULT()); sl@0: umemget32(&(parms[0]), m.Ptr2(), 3*sizeof(TInt)); sl@0: #ifdef _DUMP_TRACKERS sl@0: if((r=DumpTracker(iGetStateTracker))!=KErrNone) sl@0: break; sl@0: #endif sl@0: r = GetStateBuffer(iGetStateTracker, trackBuf, (TUint)m.Ptr1(), (TInt*)parms[1], (TInt*)parms[2], callBack, pS); sl@0: if(r != KErrNone) sl@0: return r; sl@0: parms[3] = (TUint)callBack; sl@0: m.iArg[2] = &(parms[0]); sl@0: break; sl@0: } sl@0: case RBusDevResManUs::ERequestChangeNotification: sl@0: { sl@0: __ASSERT_ALWAYS(m.Ptr1() != NULL, RESMANUS_FAULT()); sl@0: r = GetAndInitTrackingBuffer(iListenableTracker, trackBuf, (TUint)m.Ptr1(), pS); sl@0: if(r != KErrNone) sl@0: return r; sl@0: prn = &(((TTrackNotifyBuf*)trackBuf)->iNotifyBlock); sl@0: new (prn) DPowerResourceNotification(&AsyncCallBackFn, (TAny*)trackBuf, iDfcQ, KResManCallBackPriority); sl@0: m.iArg[2] = (TAny*)prn; sl@0: break; sl@0: } sl@0: case RBusDevResManUs::ERequestQualifiedChangeNotification: sl@0: { sl@0: __ASSERT_ALWAYS(m.Ptr1() != NULL, RESMANUS_FAULT()); sl@0: __ASSERT_ALWAYS(m.Ptr2() != NULL, RESMANUS_FAULT()); sl@0: umemget32(&(parms[0]), m.Ptr2(), 2*sizeof(TUint)); sl@0: m.iArg[2] = &parms[0]; sl@0: r = GetAndInitTrackingBuffer(iListenableTracker, trackBuf, (TUint)parms[0], pS); sl@0: if(r != KErrNone) sl@0: return r; sl@0: prn = &(((TTrackNotifyBuf*)trackBuf)->iNotifyBlock); sl@0: new (prn) DPowerResourceNotification(&AsyncCallBackFn, (TAny*)trackBuf, iDfcQ, KResManCallBackPriority); sl@0: parms[2] = (TUint)prn; sl@0: break; sl@0: } sl@0: default: sl@0: { sl@0: return KErrNotSupported; sl@0: } sl@0: } sl@0: sl@0: if(r == KErrNone) sl@0: r = DLogicalChannel::SendMsg(aMsg); sl@0: if(r != KErrNone) sl@0: FreeTrackingBuffer(trackBuf); sl@0: return r; sl@0: } sl@0: sl@0: sl@0: TInt DChannelResManUs::SendControl(TMessageBase* aMsg) sl@0: { sl@0: TThreadMessage& m = *(TThreadMessage*)aMsg; sl@0: TInt id = m.iValue; sl@0: TInt param1 = 0; sl@0: TUint parms[4]; sl@0: TAny* a1 = m.Ptr0(); sl@0: TAny* a2 = m.Ptr1(); sl@0: TAny* ptr1 = NULL; sl@0: switch(id) sl@0: { sl@0: case RBusDevResManUs::EInitialise: sl@0: { sl@0: __ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT()); sl@0: TUint8 stateRes[3]; sl@0: umemget(&(stateRes[0]), a1, 3*sizeof(TUint8)); sl@0: m.iArg[0] = &(stateRes[0]); sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetNoOfResources: sl@0: case RBusDevResManUs::EGetResourceControllerVersion: sl@0: { sl@0: __ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT()); sl@0: m.iArg[0] = ¶m1; sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetNoOfClients: sl@0: case RBusDevResManUs::EGetNumClientsUsingResource: sl@0: { sl@0: __ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT()); sl@0: __ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT()); sl@0: umemget32(&(parms[0]), a2, 3*sizeof(TUint)); sl@0: m.iArg[1] = &(parms[0]); sl@0: m.iArg[0] = ¶m1; sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetNumResourcesInUseByClient: sl@0: { sl@0: __ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT()); sl@0: __ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT()); sl@0: TBuf8 clientName; sl@0: Kern::KUDesGet(clientName, *(TDesC8*)m.Ptr0()); sl@0: m.iArg[0] = (TAny*)&clientName; sl@0: umemget32(&(parms[0]), m.Ptr1(), 2*sizeof(TUint)); sl@0: param1 = parms[1]; sl@0: m.iArg[1] = ¶m1; sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetResourceIdByName: sl@0: { sl@0: __ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT()); sl@0: __ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT()); sl@0: TBuf8 resourceName; sl@0: Kern::KUDesGet(resourceName, *(TDesC8*)m.Ptr0()); sl@0: m.iArg[0] = (TAny*)&resourceName; sl@0: m.iArg[1] = ¶m1; sl@0: break; sl@0: } sl@0: #ifdef RESOURCE_MANAGER_SIMULATED_PSL sl@0: case RBusDevResManUs::EGetNumCandidateAsyncResources: sl@0: case RBusDevResManUs::EGetNumCandidateSharedResources: sl@0: { sl@0: __ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT()); sl@0: m.iArg[0] = ¶m1; sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetCandidateAsyncResourceId: sl@0: case RBusDevResManUs::EGetCandidateSharedResourceId: sl@0: { sl@0: __ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT()); sl@0: m.iArg[1] = ¶m1; sl@0: break; sl@0: } sl@0: #endif sl@0: case RBusDevResManUs::EGetNumDependentsForResource: sl@0: { sl@0: __ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT()); sl@0: __ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT()); sl@0: umemget32(&(parms[0]), m.Ptr1(), 2*sizeof(TUint)); sl@0: m.iArg[1] = &(parms[0]); sl@0: m.iArg[0] = ¶m1; sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetDependentsIdForResource: sl@0: { sl@0: __ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT()); sl@0: __ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT()); sl@0: umemget32(&(parms[0]), m.Ptr1(), 3*sizeof(TUint)); sl@0: TInt len, maxLen; sl@0: ptr1 = (TAny*)parms[1]; sl@0: Kern::KUDesInfo(*(const TDesC8*)parms[1], len, maxLen); sl@0: umemget32(¶m1, m.Ptr0(), sizeof(TUint)); sl@0: if((maxLen - len) < (TInt)(param1 * sizeof(SResourceDependencyInfo))) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: m.iArg[0] = ¶m1; sl@0: m.iArg[1] = &(parms[0]); sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetResourceInfo: sl@0: { sl@0: __ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT()); sl@0: __ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT()); sl@0: TResourceInfoBuf buf; sl@0: m.iArg[1] = &buf; sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetAllResourcesInfo: sl@0: { sl@0: __ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT()); sl@0: __ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT()); sl@0: umemget32(&(parms[0]), m.Ptr1(), 2*sizeof(TUint)); sl@0: ptr1 = (TAny*)parms[0]; sl@0: umemget32(¶m1, (TAny*)parms[0], sizeof(TUint)); sl@0: parms[0] =(TUint)¶m1; sl@0: RSimplePointerArray infoPtrs; sl@0: umemget(&infoPtrs, m.Ptr0(), sizeof(RSimplePointerArray)); sl@0: if((infoPtrs.Count() < 0) || (infoPtrs.Count() < param1)) sl@0: return KErrArgument; sl@0: m.iArg[1] = &(parms[0]); sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetInfoOnClientsUsingResource: sl@0: { sl@0: __ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT()); sl@0: __ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT()); sl@0: umemget32(&parms[0], m.Ptr1(), 4*sizeof(TUint)); sl@0: ptr1 = (TAny*)parms[0]; sl@0: umemget32(¶m1, (TAny*)parms[0], sizeof(TUint)); sl@0: parms[0] = (TUint)¶m1; sl@0: RSimplePointerArrayinfoPtrs; sl@0: umemget(&infoPtrs, m.Ptr0(), sizeof(RSimplePointerArray)); sl@0: if((infoPtrs.Count() < 0) || (infoPtrs.Count() < param1)) sl@0: return KErrArgument; sl@0: m.iArg[1] = &(parms[0]); sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetNamesAllClients: sl@0: { sl@0: __ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT()); sl@0: __ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT()); sl@0: umemget32(&parms[0], m.Ptr1(), 4*sizeof(TUint)); sl@0: ptr1 = (TAny*)parms[0]; sl@0: umemget32(¶m1, (TAny*)parms[0], sizeof(TUint)); sl@0: parms[0] = (TUint)¶m1; sl@0: RSimplePointerArray infoPtrs; sl@0: umemget(&infoPtrs, m.Ptr0(), sizeof(RSimplePointerArray)); sl@0: if((infoPtrs.Count() < 0) || (infoPtrs.Count() < param1)) sl@0: return KErrArgument; sl@0: m.iArg[1] = &(parms[0]); sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetInfoOnResourcesInUseByClient: sl@0: { sl@0: __ASSERT_ALWAYS(a1 != NULL, RESMANUS_FAULT()); sl@0: __ASSERT_ALWAYS(a2 != NULL, RESMANUS_FAULT()); sl@0: TBuf8 clientName; sl@0: Kern::KUDesGet(clientName, *(TDesC8*)m.Ptr0()); sl@0: m.iArg[0] = (TAny*)&clientName; sl@0: umemget32(&parms[0], m.Ptr1(), 3*sizeof(TUint)); sl@0: ptr1 = (TAny*)parms[0]; sl@0: umemget32(¶m1, (TAny*)parms[0], sizeof(TUint)); sl@0: parms[0] = (TUint)¶m1; sl@0: RSimplePointerArray infoPtrs; sl@0: umemget(&infoPtrs, (TAny*)parms[1], sizeof(RSimplePointerArray)); sl@0: if((infoPtrs.Count() < 0) || (infoPtrs.Count() < param1)) sl@0: return KErrArgument; sl@0: m.iArg[1] = &(parms[0]); sl@0: break; sl@0: } sl@0: } sl@0: sl@0: TInt r = DLogicalChannel::SendMsg(aMsg); sl@0: if(r != KErrNone) sl@0: return r; sl@0: sl@0: switch(id) sl@0: { sl@0: case RBusDevResManUs::EGetNoOfResources: sl@0: case RBusDevResManUs::EGetNoOfClients: sl@0: case RBusDevResManUs::EGetNumClientsUsingResource: sl@0: case RBusDevResManUs::EGetResourceControllerVersion: sl@0: case RBusDevResManUs::EGetNumDependentsForResource: sl@0: { sl@0: umemput32(a1, (TAny*)¶m1, sizeof(TUint)); sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetNumResourcesInUseByClient: sl@0: { sl@0: umemput32((TAny*)parms[0], (TAny*)¶m1, sizeof(TUint)); sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetResourceIdByName: sl@0: { sl@0: umemput32(a2, (TAny*)¶m1, sizeof(TUint)); sl@0: break; sl@0: } sl@0: #ifdef RESOURCE_MANAGER_SIMULATED_PSL sl@0: case RBusDevResManUs::EGetNumCandidateAsyncResources: sl@0: case RBusDevResManUs::EGetNumCandidateSharedResources: sl@0: { sl@0: umemput32(a1, (TAny*)¶m1, sizeof(TUint)); sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetCandidateAsyncResourceId: sl@0: case RBusDevResManUs::EGetCandidateSharedResourceId: sl@0: { sl@0: umemput32(a2, (TAny*)¶m1, sizeof(TUint)); sl@0: break; sl@0: } sl@0: #endif sl@0: case RBusDevResManUs::EGetDependentsIdForResource: sl@0: { sl@0: r = Kern::ThreadDesWrite(iClient,(TAny*)ptr1, (const TDesC8&)*(SResourceDependencyInfo*)parms[1], 0); sl@0: if(r == KErrOverflow) //This is done to retain the error as per API spec sl@0: r = KErrArgument; sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetResourceInfo: sl@0: { sl@0: Kern::KUDesPut(*(TDes8*)a2, (const TDesC8&)*(TResourceInfoBuf*)m.Ptr1()); sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetAllResourcesInfo: sl@0: { sl@0: TUint numToCopy; sl@0: RSimplePointerArray infoPtrs; sl@0: umemget(&infoPtrs, a1, sizeof(RSimplePointerArray)); sl@0: numToCopy = (infoPtrs.Count() < param1) ? infoPtrs.Count() : param1; sl@0: umemput32(ptr1, (TAny*)¶m1, sizeof(TUint)); sl@0: TResourceInfoBuf** entriesAddr = infoPtrs.Entries(); sl@0: TInt* entryPtr = (TInt*)entriesAddr; sl@0: TPowerResourceInfoV01 *currRes = (TPowerResourceInfoV01*)iResourceInfoResCtrl->Ptr(); sl@0: TResourceInfoBuf* clientAddr; sl@0: TResourceInfoBuf tempInfo; sl@0: for(TUint index = 0; index < numToCopy; index++) sl@0: { sl@0: umemget32(&clientAddr, entryPtr, sizeof(TResourceInfoBuf*)); sl@0: entryPtr++; sl@0: r = ExtractResourceInfo(currRes, tempInfo); sl@0: if(r != KErrNone) sl@0: return r; sl@0: umemput((TAny*)clientAddr, (TAny*)&(tempInfo), tempInfo.Length()); sl@0: currRes++; sl@0: } sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetInfoOnClientsUsingResource: sl@0: { sl@0: TUint numToCopy; sl@0: RSimplePointerArray infoPtrs; sl@0: umemget(&infoPtrs, a1, sizeof(RSimplePointerArray)); sl@0: numToCopy = infoPtrs.Count(); sl@0: TClientInfoBuf** entriesAddr = infoPtrs.Entries(); sl@0: TInt* entryPtr = (TInt*)entriesAddr; sl@0: TPowerClientInfoV01* rcDataPtr = (TPowerClientInfoV01*)iClientNamesResCtrl->Ptr(); sl@0: TClientInfoBuf* clientAddr; sl@0: TUint userSideClients = 0; sl@0: TClientInfoBuf tempInfo; sl@0: for(TInt index = 0; index < param1; index++) sl@0: { sl@0: if((!parms[1]) && !(rcDataPtr->iClientId & USER_SIDE_CLIENT_BIT_MASK)) sl@0: { sl@0: rcDataPtr++; sl@0: continue; sl@0: } sl@0: if(numToCopy == 0) sl@0: { sl@0: userSideClients++; sl@0: continue; sl@0: } sl@0: umemget32(&clientAddr, entryPtr, sizeof(TClientName*)); sl@0: entryPtr++; sl@0: tempInfo().iId = rcDataPtr->iClientId; sl@0: tempInfo().iName = *rcDataPtr->iClientName; sl@0: Kern::InfoCopy(*clientAddr, tempInfo); sl@0: rcDataPtr++; sl@0: numToCopy--; sl@0: userSideClients++; sl@0: } sl@0: if(parms[1]) sl@0: umemput32(ptr1, (TAny*)¶m1, sizeof(TUint)); sl@0: else sl@0: umemput32(ptr1, (TAny*)&userSideClients, sizeof(TUint)); sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetNamesAllClients: sl@0: { sl@0: TUint numToCopy; sl@0: RSimplePointerArray infoPtrs; sl@0: umemget(&infoPtrs, a1, sizeof(RSimplePointerArray)); sl@0: numToCopy = infoPtrs.Count(); sl@0: TClientName** entriesAddr = infoPtrs.Entries(); sl@0: TInt* entryPtr = (TInt*)entriesAddr; sl@0: TPowerClientInfoV01* rcDataPtr = (TPowerClientInfoV01*)iClientNamesResCtrl->Ptr(); sl@0: TClientName* clientAddr; sl@0: TUint userSideClients = 0; sl@0: for(TInt index = 0; index < param1; index++) sl@0: { sl@0: if((!parms[1]) && !(rcDataPtr->iClientId & USER_SIDE_CLIENT_BIT_MASK)) sl@0: { sl@0: rcDataPtr++; sl@0: continue; sl@0: } sl@0: if(numToCopy == 0) sl@0: { sl@0: userSideClients++; sl@0: continue; sl@0: } sl@0: umemget32(&clientAddr, entryPtr, sizeof(TClientName*)); sl@0: entryPtr++; sl@0: Kern::KUDesPut(*((TDes8*)clientAddr), *(const TDesC8*)rcDataPtr->iClientName); sl@0: rcDataPtr++; sl@0: numToCopy--; sl@0: userSideClients++; sl@0: } sl@0: if(parms[1]) sl@0: umemput32(ptr1, (TAny*)¶m1, sizeof(TUint)); sl@0: else sl@0: umemput32(ptr1, (TAny*)&userSideClients, sizeof(TUint)); sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetInfoOnResourcesInUseByClient: sl@0: { sl@0: TUint numToCopy; sl@0: RSimplePointerArray infoPtrs; sl@0: umemget(&infoPtrs, (TAny*)parms[1], sizeof(RSimplePointerArray)); sl@0: numToCopy = (infoPtrs.Count() < param1) ? infoPtrs.Count() : param1; sl@0: umemput32(ptr1, (TAny*)¶m1, sizeof(TUint)); sl@0: TResourceInfoBuf** entriesAddr = infoPtrs.Entries(); sl@0: TInt* entryPtr = (TInt*)entriesAddr; sl@0: TPowerResourceInfoV01* currRes = (TPowerResourceInfoV01*)iResourceInfoResCtrl->Ptr(); sl@0: TResourceInfoBuf* clientAddr; sl@0: TResourceInfoBuf tempInfo; sl@0: for(TUint index = 0; index < numToCopy; index++) sl@0: { sl@0: umemget32(&clientAddr, entryPtr, sizeof(TResourceInfoBuf*)); sl@0: entryPtr++; sl@0: r = ExtractResourceInfo(currRes, tempInfo); sl@0: if(r != KErrNone) sl@0: return r; sl@0: umemput((TAny*)clientAddr, (TAny*)&(tempInfo), tempInfo.Length()); sl@0: currRes++; sl@0: } sl@0: break; sl@0: } sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: void DChannelResManUs::HandleMsg(TMessageBase* aMsg) sl@0: { sl@0: TThreadMessage& m=*(TThreadMessage*)aMsg; sl@0: TInt id=m.iValue; sl@0: sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf(" >ldd: DChannelResManUs::HandleMsg(TMessageBase* aMsg) id=%d\n", id)); sl@0: sl@0: if (id==(TInt)ECloseMsg) sl@0: { sl@0: // Deregister here to ensure the correct thread ID is read sl@0: if(ClientHandle() != 0) sl@0: { sl@0: // Must de-register from Resource Controller before closing down sl@0: // Not checking return value - still need to delete allocated buffers sl@0: #ifdef PRM_US_INSTRUMENTATION_MACRO sl@0: PRM_US_DEREGISTER_CLIENT_START_TRACE; sl@0: #endif sl@0: ((DPowerResourceController*)iPddPtr)->DeregisterProxyClient(ClientHandle()); sl@0: sl@0: #ifdef PRM_US_INSTRUMENTATION_MACRO sl@0: PRM_US_DEREGISTER_CLIENT_END_TRACE; sl@0: #endif sl@0: SetClientHandle(0); sl@0: } sl@0: iMsgQ.iMessage->Complete(KErrNone,EFalse); sl@0: return; sl@0: } sl@0: else if (id==KMaxTInt) sl@0: { sl@0: // DoCancel sl@0: DoCancel(m.Int0()); sl@0: m.Complete(KErrNone,ETrue); sl@0: return; sl@0: } sl@0: sl@0: if (id<0) sl@0: { sl@0: // DoRequest sl@0: TRequestStatus* pS=(TRequestStatus*)m.Ptr0(); sl@0: TInt r=DoRequest(~id, pS, m.Ptr1(), m.Ptr2()); sl@0: m.Complete(r,ETrue); sl@0: } sl@0: else sl@0: { sl@0: // DoControl sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf(" >ldd: do control id=%d...\n", id)); sl@0: TInt r=DoControl(id,m.Ptr0(),m.Ptr1()); sl@0: m.Complete(r,ETrue); sl@0: } sl@0: } sl@0: sl@0: TInt DChannelResManUs::CancelTrackerRequests(TTrackingControl* aTracker, TBool aSingleRsrc, TUint aResourceId, TRequestStatus* aStatus) sl@0: { sl@0: // Cancel all outstanding requests from this client for a specified operation on sl@0: // a specified resource sl@0: sl@0: // Loop all entries in the iBusyQue of requests to locate a match for the sl@0: // operation type and resource ID sl@0: // sl@0: // For each match, remove the buffer from the busy queue and return to the free queue sl@0: // If the request is already being processed, and so the callback function will be called sl@0: // later, then the callback will exit gracefully. sl@0: // sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf(" > DChannelResManUs::CancelTrackerRequests")); sl@0: TInt returnVal = KErrNone; sl@0: TBool statusMatched=EFalse; sl@0: TTrackingBuffer* firstLink = NULL; sl@0: TTrackingBuffer* lastLink = NULL; sl@0: TInt type = aTracker->iType; sl@0: sl@0: #ifdef PRM_US_INSTRUMENTATION_MACRO sl@0: if(type==EGetState) sl@0: { sl@0: PRM_US_CANCEL_GET_RESOURCE_STATE_START_TRACE; sl@0: } sl@0: else if(type==ESetState) sl@0: { sl@0: PRM_US_CANCEL_SET_RESOURCE_STATE_START_TRACE; sl@0: } sl@0: #endif sl@0: sl@0: if(aTracker->iBusyQue != NULL) sl@0: { sl@0: firstLink = (TTrackingBuffer*)(aTracker->iBusyQue->iA.iNext); sl@0: lastLink = (TTrackingBuffer*)(&(aTracker->iBusyQue->iA)); sl@0: } sl@0: while(( firstLink!=lastLink )&&(!statusMatched)) sl@0: { sl@0: TTrackingBuffer* buffer = firstLink; sl@0: TUint resourceId = buffer->GetResourceId(); sl@0: if(aSingleRsrc) sl@0: if(resourceId != aResourceId) // Required resource? sl@0: { sl@0: firstLink=(TTrackingBuffer*)(firstLink->iNext); sl@0: continue; sl@0: } sl@0: if(aStatus!=NULL) sl@0: { sl@0: TClientRequest *request; sl@0: GET_USER_REQUEST(request, buffer, type) sl@0: if(request->StatusPtr() == aStatus) sl@0: { sl@0: statusMatched = ETrue; sl@0: } sl@0: else sl@0: { sl@0: firstLink=(TTrackingBuffer*)(firstLink->iNext); sl@0: continue; sl@0: } sl@0: } sl@0: TInt r = KErrNone; sl@0: if(type==EGetState) sl@0: { sl@0: TTrackGetStateBuf* stateBuf = (TTrackGetStateBuf*)firstLink; sl@0: r=((DPowerResourceController*)iPddPtr)->CancelAsyncRequestCallBack(ClientHandle(), sl@0: resourceId, (stateBuf->iCtrlBlock)); sl@0: } sl@0: else if(type==ESetState) sl@0: { sl@0: TTrackSetStateBuf* stateBuf = (TTrackSetStateBuf*)firstLink; sl@0: r = ((DPowerResourceController*)iPddPtr)->CancelAsyncRequestCallBack(ClientHandle(), sl@0: resourceId, (stateBuf->iCtrlBlock)); sl@0: } sl@0: else if(type==ENotify) sl@0: { sl@0: TTrackNotifyBuf* notifyBuf = (TTrackNotifyBuf*)firstLink; sl@0: r=((DPowerResourceController*)iPddPtr)->CancelNotification(ClientHandle(), resourceId, sl@0: notifyBuf->iNotifyBlock); sl@0: } sl@0: sl@0: // Process the accumulated return value sl@0: if((r==KErrCompletion)&&((returnVal==KErrNone)||(returnVal==KErrCancel))) sl@0: { sl@0: returnVal=KErrCompletion; sl@0: } sl@0: else if((r==KErrInUse)&& sl@0: ((returnVal==KErrNone)||(returnVal==KErrCompletion)||(returnVal==KErrCancel))) sl@0: { sl@0: returnVal=KErrInUse; sl@0: } sl@0: else if(r!=KErrCancel) sl@0: { sl@0: returnVal=r; sl@0: } sl@0: sl@0: // Return the tracking buffer to the free queue sl@0: TTrackingBuffer* tempLink = (TTrackingBuffer*)(firstLink->iNext); sl@0: FreeTrackingBuffer(firstLink); sl@0: firstLink = tempLink; sl@0: sl@0: #ifdef PRM_US_INSTRUMENTATION_MACRO sl@0: if(type==EGetState) sl@0: { sl@0: PRM_US_CANCEL_GET_RESOURCE_STATE_END_TRACE; sl@0: } sl@0: else if(type==ESetState) sl@0: { sl@0: PRM_US_CANCEL_SET_RESOURCE_STATE_END_TRACE; sl@0: } sl@0: #endif sl@0: // Complete the TRequestStatus object sl@0: if((r!=KErrCompletion)&&(r!=KErrInUse)) sl@0: { sl@0: TClientRequest* request; sl@0: GET_USER_REQUEST(request, buffer, type) sl@0: Kern::QueueRequestComplete(iClient, request, r); sl@0: } sl@0: sl@0: } // while sl@0: return returnVal; sl@0: } sl@0: sl@0: sl@0: TTrackingControl* DChannelResManUs::MapRequestToTracker(TInt aRequestType) sl@0: // Utility function to map identifiers for cancel commands to request types. sl@0: { sl@0: TTrackingControl *tracker=NULL; sl@0: switch(aRequestType) sl@0: { sl@0: case RBusDevResManUs::ECancelChangeResourceStateRequests: sl@0: case RBusDevResManUs::ECancelChangeResourceState: sl@0: { sl@0: tracker=iSetStateTracker; sl@0: break; sl@0: } sl@0: case RBusDevResManUs::ECancelGetResourceStateRequests: sl@0: case RBusDevResManUs::ECancelGetResourceState: sl@0: { sl@0: tracker=iGetStateTracker; sl@0: break; sl@0: } sl@0: case RBusDevResManUs::ECancelChangeNotificationRequests: sl@0: case RBusDevResManUs::ECancelRequestChangeNotification: sl@0: { sl@0: tracker=iListenableTracker; sl@0: break; sl@0: } sl@0: default: sl@0: { sl@0: __ASSERT_ALWAYS(0,RESMANUS_FAULT()); sl@0: } sl@0: } sl@0: return tracker; sl@0: } sl@0: sl@0: sl@0: TInt DChannelResManUs::CancelRequestsOfType(TInt aRequestType, TRequestStatus* aStatus) sl@0: // Cancel a particular request. This may be qualified by the type of operation sl@0: { sl@0: __ASSERT_ALWAYS(((aRequestType==RBusDevResManUs::ECancelChangeResourceState)|| sl@0: (aRequestType==RBusDevResManUs::ECancelGetResourceState)|| sl@0: (aRequestType==RBusDevResManUs::ECancelRequestChangeNotification)|| sl@0: (KMaxTInt)), sl@0: RESMANUS_FAULT()); sl@0: // For the KMaxTInt case, the type of the request is not known and so all trackers sl@0: // must be considered before the request is found. sl@0: // For all other cases, only the relevant tracker is searched. sl@0: TInt r=KErrNone; sl@0: if(aRequestType!=KMaxTInt) sl@0: { sl@0: TTrackingControl*tracker=MapRequestToTracker(aRequestType); sl@0: r=CancelTrackerRequests(tracker, EFalse, 0, aStatus); sl@0: } sl@0: else sl@0: { sl@0: TTrackingControl* tracker[3] = {iGetStateTracker, iSetStateTracker, iListenableTracker}; sl@0: TUint8 index=0; sl@0: while((index<3) && (r==KErrNone)) sl@0: { sl@0: r=CancelTrackerRequests(tracker[index], EFalse, 0, aStatus); sl@0: ++index; sl@0: } sl@0: } sl@0: if(r==KErrCancel) sl@0: r=KErrNone; // All cancellations were successful sl@0: sl@0: return r; sl@0: } sl@0: sl@0: sl@0: void DChannelResManUs::DoCancel(TInt aMask) sl@0: // Cancel an outstanding request. sl@0: { sl@0: TRequestStatus* status = (TRequestStatus*)aMask; sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoCancel, TRequestStatus addr = 0x%x",(TInt)status)); sl@0: sl@0: CancelRequestsOfType(KMaxTInt, status); // Ignore return value sl@0: return; sl@0: } sl@0: sl@0: TInt DChannelResManUs::DoRequest(TInt aReqNo, TRequestStatus* /*aStatus*/, TAny* a1, TAny* a2) sl@0: // Asynchronous requests. sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)")); sl@0: sl@0: TInt r=KErrNone; sl@0: switch (aReqNo) sl@0: { sl@0: case RBusDevResManUs::EChangeResourceState: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoRequest case EChangeResourceState")); sl@0: // a1 specifies the identifier of the required resource sl@0: // a2 specifies the required state for the resource sl@0: // sl@0: TUint *param = (TUint*)a2; sl@0: TUint resourceId = (TUint)a1; sl@0: TInt newState = (TInt)param[0]; sl@0: sl@0: #ifdef PRM_US_INSTRUMENTATION_MACRO sl@0: PRM_US_SET_RESOURCE_STATE_START_TRACE; sl@0: #endif sl@0: // Invoke the API sl@0: r=((DPowerResourceController*)iPddPtr)->ChangeResourceState(ClientHandle(), sl@0: resourceId, newState, (TPowerResourceCb*)param[1]); sl@0: break; sl@0: } sl@0: sl@0: case RBusDevResManUs::EGetResourceState: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoRequest case EGetResourceState")); sl@0: // a1 specifies the resource ID sl@0: // a2 specifies the container stating if a cached value is required, the address of the variable sl@0: // to be update with the state value and the address of the level owner ID sl@0: // sl@0: TUint resourceId = (TUint)a1; sl@0: TUint *parms = (TUint*)a2; sl@0: TBool cached = (TBool)(parms[0]); sl@0: sl@0: #ifdef PRM_US_INSTRUMENTATION_MACRO sl@0: PRM_US_GET_RESOURCE_STATE_START_TRACE; sl@0: #endif sl@0: // Always invoke the asynchronous version of the API sl@0: r=((DPowerResourceController*)iPddPtr)->GetResourceState(ClientHandle(), sl@0: resourceId, cached, *((TPowerResourceCb*)parms[3])); sl@0: break; sl@0: } sl@0: sl@0: sl@0: case RBusDevResManUs::ERequestChangeNotification: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoRequest case ERequestChangeNotification")); sl@0: // a1 specifies the resource ID sl@0: r=((DPowerResourceController*)iPddPtr)->RequestNotification(ClientHandle(), sl@0: (TUint)a1, *((DPowerResourceNotification*)a2)); sl@0: break; sl@0: } sl@0: sl@0: case RBusDevResManUs::ERequestQualifiedChangeNotification: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoRequest case ERequestQualifiedChangeNotification")); sl@0: // a1 specifies the threshold value that the state is to change by sl@0: // a2 specifies the address of the container holding the resourceID and the required direction sl@0: TInt threshold = (TInt)a1; sl@0: TUint *parms = (TUint*)a2; sl@0: TUint resourceId = parms[0]; sl@0: TBool direction = (TBool)(parms[1]); sl@0: r=((DPowerResourceController*)iPddPtr)->RequestNotification(ClientHandle(), sl@0: resourceId, *((DPowerResourceNotification*)parms[2]), threshold, direction); sl@0: break; sl@0: } sl@0: sl@0: default: sl@0: return KErrNotSupported; sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: TInt DChannelResManUs::DoControl(TInt aFunction, TAny* a1, TAny* a2) sl@0: // Synchronous requests. sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::DoControl(TInt aFunction, TAny* a1, TAny* a2)") ); sl@0: sl@0: TInt r=KErrNone; sl@0: switch (aFunction) sl@0: { sl@0: case RBusDevResManUs::EInitialise: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EInitialise")); sl@0: // a1 specifies the array describing the number of 'gettable' and 'settable' state resources sl@0: // and the number of 'listenable' resources sl@0: // sl@0: TUint8 *stateRes = (TUint8*)a1; sl@0: #ifdef PRM_US_INSTRUMENTATION_MACRO sl@0: PRM_US_REGISTER_CLIENT_START_TRACE; sl@0: #endif sl@0: // The call to the Resource Controller's AllocReserve method requires two parameters: sl@0: // the number of client level objects and the number of request message objects sl@0: // Each 'settable' state resource requires a client level object and a request message object sl@0: // Each 'gettable' state resource requires a request message object, only. sl@0: // Call Resource Control to make allocations sl@0: r=((DPowerResourceController*)iPddPtr)->AllocReserve(ClientHandle(), sl@0: stateRes[1], // Number of settable sl@0: (TUint8)(stateRes[1] + stateRes[0])); // Number of (settable + gettable) sl@0: #ifdef PRM_US_INSTRUMENTATION_MACRO sl@0: PRM_US_REGISTER_CLIENT_END_TRACE; sl@0: #endif sl@0: if(r==KErrNone) sl@0: { sl@0: // Require 1 TPowerResourceCb object per gettable resource state sl@0: // Require 1 TPowerResourceCb object per settable resource state sl@0: // Require 1 DPowerResourceNotification object per listenable resource sl@0: // sl@0: if(stateRes[0]>0) sl@0: r=InitTrackingControl(iGetStateTracker,EGetState,stateRes[0]); sl@0: if((r==KErrNone) && (stateRes[1]>0)) sl@0: r=InitTrackingControl(iSetStateTracker,ESetState,stateRes[1]); sl@0: if((r==KErrNone) && (stateRes[2]>0)) sl@0: r=InitTrackingControl(iListenableTracker,ENotify,stateRes[2]); sl@0: #ifdef _DUMP_TRACKERS sl@0: if((r=DumpTracker(iGetStateTracker))!=KErrNone) sl@0: break; sl@0: if((r=DumpTracker(iSetStateTracker))!=KErrNone) sl@0: break; sl@0: #endif sl@0: } sl@0: break; sl@0: } sl@0: sl@0: case RBusDevResManUs::EGetNoOfResources: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetNoOfResources")); sl@0: TUint numResources; sl@0: r=((DPowerResourceController*)iPddPtr)->GetNumResourcesInUseByClient(ClientHandle(),0,numResources); sl@0: iResInfoValid = 0; // New numResources invalidates the iResInfoXXXX information sl@0: iResInfoStoredClientId = 0; sl@0: iResInfoStoredNum = 0; sl@0: if(r!=KErrNone) sl@0: return r; sl@0: // a2 specifies whether the resource information should be loaded sl@0: if((r==KErrNone)&&(a2!=NULL)) sl@0: { sl@0: TUint prevNumRes = 0; sl@0: while((numResources != prevNumRes)&&(r==KErrNone)) sl@0: { sl@0: // if the number of resources is greater than can be accommodated by the array, sl@0: // re-size it sl@0: if((r=EnsureSizeIsSufficient(iResourceInfoResCtrl, (TInt)(numResources*sizeof(TPowerResourceInfoV01))))!=KErrNone) sl@0: break; sl@0: prevNumRes = numResources; sl@0: // Get the resource info from the Resource Controller sl@0: // Specify 'aTargetClientId' as zero to access all resources sl@0: iResourceInfoResCtrl->SetLength(0); sl@0: r=((DPowerResourceController*)iPddPtr)->GetInfoOnResourcesInUseByClient( sl@0: ClientHandle(),0,numResources,iResourceInfoResCtrl); sl@0: } sl@0: if(r==KErrNone) sl@0: { sl@0: iResInfoValid = 1; sl@0: iResInfoStoredClientId = KAllResInfoStored; sl@0: iResInfoStoredNum = numResources; sl@0: } sl@0: } sl@0: if(r==KErrNone) sl@0: *(TUint*)a1 = numResources; sl@0: break; sl@0: } sl@0: sl@0: case RBusDevResManUs::EGetAllResourcesInfo: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetAllResourcesInfo")); sl@0: // Parameters are passed in TUint* parms[2] sl@0: // The address of the number of resources is at element 0 sl@0: // The flag to indicate if the resource info stored is to be refreshed is at element 1 sl@0: TUint* parms = (TUint*)a2; sl@0: TUint numResources = *(TUint*)parms[0]; sl@0: TBool refresh=(TBool)(parms[1]); sl@0: sl@0: // The results are to be written to an RSimplePointerArray, the address is in a1 sl@0: // Check that the array has enough elements sl@0: if(refresh) sl@0: { sl@0: // For the refresh option, invoke Resource Controller API once, only (do not recurse) sl@0: // If the number of requested resources is greater than can be accommodated by the array, sl@0: // re-size it sl@0: if((r=EnsureSizeIsSufficient(iResourceInfoResCtrl, (TInt)(numResources*sizeof(TPowerResourceInfoV01))))!=KErrNone) sl@0: break; sl@0: // Get the resource info from the Resource Controller sl@0: // Specify 'aTargetClientId' as zero to access all resources sl@0: iResourceInfoResCtrl->SetLength(0); sl@0: r=((DPowerResourceController*)iPddPtr)->GetInfoOnResourcesInUseByClient( sl@0: ClientHandle(),0,numResources,iResourceInfoResCtrl); sl@0: if(numResources != iResInfoStoredNum) sl@0: { sl@0: iResInfoValid = 0; // Assume cohesion is now lost sl@0: iResInfoStoredClientId = 0; sl@0: iResInfoStoredNum = 0; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // If the information stored is not valid or is not for all resources return KErrNotReady sl@0: if((iResInfoValid != 1)||(iResInfoStoredClientId != KAllResInfoStored)) sl@0: { sl@0: r=KErrNotReady; sl@0: break; sl@0: } sl@0: // The number of resources for which information is available in this case is iResInfoStoredNum sl@0: numResources = iResInfoStoredNum; sl@0: } sl@0: #ifdef RESOURCE_MANAGER_SIMULATED_PSL sl@0: TPowerResourceInfoV01* currRes = (TPowerResourceInfoV01*)iResourceInfoResCtrl->Ptr(); sl@0: for(TUint index = 0; index < numResources; index++) sl@0: { sl@0: CheckForCandidateAsyncResource(currRes); sl@0: CheckForCandidateSharedResource(currRes); sl@0: currRes++; sl@0: } sl@0: #endif sl@0: *(TUint*)(parms[0]) = numResources; sl@0: sl@0: break; sl@0: } sl@0: sl@0: case RBusDevResManUs::EGetNoOfClients: sl@0: case RBusDevResManUs::EGetNumClientsUsingResource: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetNoOfClients")); sl@0: // Parameters are passed in TUint parms[3] sl@0: // The flag to indicate if kernel-side clients are to be included is at element 0 sl@0: // The ID of the resource of interest (0 is expected for EGetNoOfClients) sl@0: // The flag to indicate if the client info is to be read now is at element 1 sl@0: TUint *parms = (TUint*)a2; sl@0: TUint includeKern = parms[0]; sl@0: TUint resourceId = parms[1]; sl@0: TUint infoRead = parms[2]; sl@0: TUint requiredId = resourceId; sl@0: if(aFunction == RBusDevResManUs::EGetNoOfClients) sl@0: { sl@0: __ASSERT_ALWAYS(resourceId==0,RESMANUS_FAULT()); sl@0: requiredId = KAllClientInfoStored; sl@0: } sl@0: TUint numClients = 0; sl@0: if(includeKern==1) sl@0: { sl@0: // Client must exhibit PlatSec capability ReadDeviceData sl@0: if(!iClient->HasCapability(ECapabilityReadDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Resource Manager user-side API function EGetNoOfClients"))) sl@0: { sl@0: r = KErrPermissionDenied; sl@0: break; sl@0: } sl@0: if(r==KErrNone) sl@0: r=((DPowerResourceController*)iPddPtr)->GetNumClientsUsingResource(ClientHandle(),resourceId,numClients); sl@0: } sl@0: else sl@0: numClients = (TUint)(iDevice->iOpenChannels); sl@0: sl@0: // New numClients invalidates the iClientInfoXXXX information sl@0: iClientInfoValid = 0; sl@0: iClientInfoStoredResId = 0; sl@0: iClientInfoStoredNum= 0; sl@0: sl@0: if((r==KErrNone)&&(infoRead==1)) sl@0: { sl@0: // Capability check already performed, so no need to repeat ... sl@0: TUint prevNumClients = 0; sl@0: while((numClients != prevNumClients)&&(r == KErrNone)) sl@0: { sl@0: // Ensure buffer is large enough to store the information sl@0: if((r=EnsureSizeIsSufficient(iClientNamesResCtrl, (TInt)(numClients*sizeof(TPowerClientInfoV01))))!=KErrNone) sl@0: break; sl@0: prevNumClients = numClients; sl@0: // Invoke the API sl@0: r=((DPowerResourceController*)iPddPtr)->GetInfoOnClientsUsingResource(ClientHandle(), sl@0: resourceId,numClients,iClientNamesResCtrl); sl@0: }; sl@0: sl@0: if(r==KErrNone) sl@0: { sl@0: iClientInfoValid = 1; sl@0: iClientInfoStoredResId = requiredId; sl@0: iClientInfoStoredNum = numClients; sl@0: if(includeKern!=1) sl@0: { sl@0: TUint numAllClients = numClients; sl@0: numClients = 0; sl@0: TPowerClientInfoV01* rcDataPtr = (TPowerClientInfoV01*)(iClientNamesResCtrl->Ptr()); sl@0: for(TUint i=0; iiClientId & USER_SIDE_CLIENT_BIT_MASK) sl@0: ++numClients; sl@0: ++rcDataPtr; sl@0: } sl@0: } sl@0: } sl@0: } sl@0: if(r==KErrNone) sl@0: *(TUint*)a1 = numClients; sl@0: break; sl@0: } sl@0: sl@0: case RBusDevResManUs::EGetNamesAllClients: sl@0: case RBusDevResManUs::EGetInfoOnClientsUsingResource: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetNamesAllClients-EGetInfoOnClientsUsingResource")); sl@0: // Parameters are passed in TUint* parms[4] sl@0: // The address of the number of clients is at element 0 sl@0: // The flag to indicate if kernel-side info is requested is at element 1 sl@0: // The resource ID is at element 2 sl@0: // The flag to indicate if the client information stored is to be refreshed is at element 3 sl@0: TUint* parms = (TUint*)a2; sl@0: TUint numClients = *(TUint*)parms[0]; sl@0: TBool includeKern=(TBool)(parms[1]); sl@0: TUint resourceId=(TUint)(parms[2]); sl@0: TBool refresh=(TBool)(parms[3]); sl@0: sl@0: TUint numClientsAvailable = 0; sl@0: iClientNamesResCtrl->SetLength(0); sl@0: sl@0: if(includeKern) sl@0: { sl@0: // Client must exhibit PlatSec capability ReadDeviceData sl@0: if(!iClient->HasCapability(ECapabilityReadDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Resource Manager user-side API function EGetNamesAllClients-EGetInfoOnClientsUsingResource"))) sl@0: { sl@0: r = KErrPermissionDenied; sl@0: break; // Early exit in event of error sl@0: } sl@0: TUint requiredId = (resourceId==0)?(TUint)KAllClientInfoStored:resourceId; sl@0: if(refresh) sl@0: { sl@0: // For the refresh option, invoke Resource Controller API once, only (do not recurse) sl@0: // If the number of clients is greater than can be accommodated by the array, sl@0: // re-size it sl@0: if((r=EnsureSizeIsSufficient(iClientNamesResCtrl, (TInt)(numClients*sizeof(TPowerClientInfoV01))))!=KErrNone) sl@0: break; sl@0: // Invoke the API sl@0: numClientsAvailable = numClients; // Arbitrary initialisation (to silence compiler warning) sl@0: r=((DPowerResourceController*)iPddPtr)->GetInfoOnClientsUsingResource(ClientHandle(), sl@0: resourceId,numClientsAvailable,iClientNamesResCtrl); sl@0: if((r!=KErrNone)||(numClientsAvailable != iClientInfoStoredNum)||(iClientInfoStoredResId != requiredId)) sl@0: { sl@0: iClientInfoValid = 0; // Assume cohesion is now lost sl@0: iClientInfoStoredResId = 0; sl@0: iClientInfoStoredNum = 0; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // If the information stored is not valid, is not for the required resources return KErrNotReady sl@0: if((iClientInfoValid != 1)||(iClientInfoStoredResId != requiredId)) sl@0: r=KErrNotReady; sl@0: // The number of clients for which information is available in this case is iClientInfoStoredNum sl@0: numClientsAvailable = iClientInfoStoredNum; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // Resource Controller will return information for the number of clients requested, sl@0: // taken in order from its internal storage - but this will be regardless of whether sl@0: // they are kernel-side or user-side; the USER_SIDE_CLIENT_BIT_MASK bit must be sl@0: // interrogated to determine this. sl@0: // sl@0: // Therefore, need to read all the clients - but to do this, must find out how many sl@0: // clients there are first. sl@0: TUint numAllClients; sl@0: r=((DPowerResourceController*)iPddPtr)->GetNumClientsUsingResource(ClientHandle(),resourceId,numAllClients); sl@0: if(r!=KErrNone) sl@0: break; // Early exit in event of error sl@0: if(numAllClients > 0) sl@0: { sl@0: if(refresh) sl@0: { sl@0: // For the refresh option, invoke Resource Controller API once, only (do not recurse) sl@0: // If the number of clients is greater than can be accommodated by the array, sl@0: // re-size it sl@0: if((r=EnsureSizeIsSufficient(iClientNamesResCtrl, (TInt)(numAllClients*sizeof(TPowerClientInfoV01))))!=KErrNone) sl@0: break; sl@0: // Invoke the API sl@0: r=((DPowerResourceController*)iPddPtr)->GetInfoOnClientsUsingResource(ClientHandle(), sl@0: resourceId,numAllClients,iClientNamesResCtrl); sl@0: TUint requiredId = (resourceId==0)?(TUint)KAllClientInfoStored:resourceId; sl@0: if((r!=KErrNone)||(numClientsAvailable != iClientInfoStoredNum)||(iClientInfoStoredResId != requiredId)) sl@0: { sl@0: iClientInfoValid = 0; // Assume cohesion is now lost sl@0: iClientInfoStoredResId = 0; sl@0: iClientInfoStoredNum = 0; sl@0: break; sl@0: } sl@0: else sl@0: { sl@0: iClientInfoValid = 1; sl@0: iClientInfoStoredResId = requiredId; sl@0: iClientInfoStoredNum = numAllClients; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // If the information stored is not valid, is not for the required resources return KErrNotReady sl@0: TUint requiredId = (resourceId==0)?(TUint)KAllClientInfoStored:resourceId; sl@0: if((iClientInfoValid != 1)||(iClientInfoStoredResId != requiredId)) sl@0: { sl@0: r=KErrNotReady; sl@0: break; sl@0: } sl@0: // The number of clients for which information is available in this case is iClientInfoStoredNum sl@0: numAllClients = iClientInfoStoredNum; sl@0: } sl@0: numClientsAvailable = numAllClients; sl@0: } // if(numAllClients > 0) sl@0: } sl@0: // Write the total number of user side cients available sl@0: *(TUint*)parms[0] = numClientsAvailable; sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetNumResourcesInUseByClient: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetNumResourcesInUseByClient")); sl@0: // a1 specifies the container holding the client name sl@0: // sl@0: sl@0: // If client doesn't exist, return KErrNotFound sl@0: // If client has appropriate capabilities, or if the client for which the information is sought sl@0: // is user-side, invoke the Resource Controller API directly sl@0: // Otherwise, return KErrPermissionDenied sl@0: TUint clientId=0; sl@0: r=((DPowerResourceController*)iPddPtr)->GetClientId(ClientHandle(), sl@0: *(TDesC8*)a1,clientId); sl@0: if(r!=KErrNone) sl@0: return KErrNotFound; sl@0: // Perform capability check sl@0: if(!iClient->HasCapability(ECapabilityReadDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Resource Manager user-side API function EGetNoOfClients"))) sl@0: { sl@0: if(!(clientId & USER_SIDE_CLIENT_BIT_MASK)) sl@0: return KErrPermissionDenied; sl@0: } sl@0: TUint numResources=0; sl@0: if(r==KErrNone) sl@0: r=((DPowerResourceController*)iPddPtr)->GetNumResourcesInUseByClient(ClientHandle(), sl@0: clientId,numResources); sl@0: // New numResources invalidates the iResXXXX information sl@0: iResInfoValid = 0; sl@0: iResInfoStoredClientId = 0; sl@0: iResInfoStoredNum= 0; sl@0: sl@0: // parms[1] specifies whether the resource information should be loaded sl@0: if((r==KErrNone)&&(*(TUint*)a2 != NULL)) sl@0: { sl@0: TUint prevNumRes = 0; sl@0: while((numResources != prevNumRes)&&(r==KErrNone)) sl@0: { sl@0: // if the number of resources is greater than can be accommodated by the array, sl@0: // re-size it sl@0: if((r=EnsureSizeIsSufficient(iResourceInfoResCtrl, (TInt)(numResources*sizeof(TPowerResourceInfoV01))))!=KErrNone) sl@0: break; sl@0: prevNumRes = numResources; sl@0: // Get the resource info from the Resource Controller sl@0: // Specify 'aTargetClientId' as zero to access all resources sl@0: iResourceInfoResCtrl->SetLength(0); sl@0: r=((DPowerResourceController*)iPddPtr)->GetInfoOnResourcesInUseByClient( sl@0: ClientHandle(),clientId,numResources,iResourceInfoResCtrl); sl@0: } sl@0: if(r==KErrNone) sl@0: { sl@0: iResInfoValid = 1; sl@0: iResInfoStoredClientId = clientId; sl@0: iResInfoStoredNum = numResources; sl@0: } sl@0: } sl@0: if(r==KErrNone) sl@0: *(TUint*)a2 = numResources; sl@0: break; sl@0: } sl@0: sl@0: case RBusDevResManUs::EGetInfoOnResourcesInUseByClient: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetInfoOnResourcesInUseByClient")); sl@0: // a1 specifies the container holding the client name sl@0: // a2 specifies an array TUint* parms[3] which contains: sl@0: // - the address of the variable to write the number of reasources to sl@0: // - a pointer to the container to hold the resources' information sl@0: // - the flag to indicate whether the resource info should be (re-)read here sl@0: sl@0: TUint clientId=0; sl@0: TUint *parms = (TUint*)a2; sl@0: TUint numResources = *(TUint*)parms[0]; sl@0: // The results are to be written to an RSimplePointerArray, the address is in parms[1] sl@0: // Check that the array has enough elements sl@0: // If client doesn't exist, return KErrNotFound sl@0: // If client has appropriate capabilities, or if the client for which the information is sought sl@0: // is user-side, invoke the Resource Controller API directly sl@0: // Otherwise, return KErrPermissionDenied sl@0: r=((DPowerResourceController*)iPddPtr)->GetClientId(ClientHandle(), sl@0: *(TDesC8*)a1,clientId); sl@0: if(r!=KErrNone) sl@0: return KErrNotFound; sl@0: // Perform capability check sl@0: if(!iClient->HasCapability(ECapabilityReadDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Resource Manager user-side API function EGetNoOfClients"))) sl@0: { sl@0: if(!(clientId & USER_SIDE_CLIENT_BIT_MASK)) sl@0: return KErrPermissionDenied; sl@0: } sl@0: sl@0: TUint updatedNumResources = numResources; sl@0: r=((DPowerResourceController*)iPddPtr)->GetNumResourcesInUseByClient(ClientHandle(),clientId,updatedNumResources); sl@0: if(r!=KErrNone) sl@0: break; sl@0: sl@0: if(updatedNumResources>0) sl@0: { sl@0: if((TUint)(parms[2] != 0)) sl@0: { sl@0: // For the refresh option, invoke Resource Controller API once, only (do not recurse) sl@0: // If the number of requested resources is greater than can be accommodated by the array, sl@0: // re-size it sl@0: if((r=EnsureSizeIsSufficient(iResourceInfoResCtrl, (TInt)(numResources*sizeof(TPowerResourceInfoV01))))!=KErrNone) sl@0: break; sl@0: // Get the resource info from the Resource Controller sl@0: // Specify 'aTargetClientId' as zero to access all resources sl@0: iResourceInfoResCtrl->SetLength(0); sl@0: r=((DPowerResourceController*)iPddPtr)->GetInfoOnResourcesInUseByClient( sl@0: ClientHandle(),clientId,numResources,iResourceInfoResCtrl); sl@0: if((numResources != iResInfoStoredNum)||(iResInfoStoredClientId != clientId)) sl@0: { sl@0: iResInfoValid = 0; // Assume cohesion is now lost sl@0: iResInfoStoredClientId = 0; sl@0: iResInfoStoredNum = 0; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // If the information stored is not valid or is not for the required clientId return KErrNotReady sl@0: if((iResInfoValid != 1)||(iResInfoStoredClientId != clientId)) sl@0: r=KErrNotReady; sl@0: // The number of resources for which information is available in this case is iResInfoStoredNum sl@0: numResources = iResInfoStoredNum; sl@0: } sl@0: } sl@0: if(r==KErrNone) sl@0: *(TUint*)parms[0] = updatedNumResources; sl@0: sl@0: break; sl@0: } sl@0: sl@0: case RBusDevResManUs::EGetResourceIdByName: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetResourceIdByName")); sl@0: // a1 specifies the container holding the resource name sl@0: // a2 specifies the variable to be update with the ID sl@0: TUint resourceId; sl@0: r=((DPowerResourceController*)iPddPtr)->GetResourceId(ClientHandle(), *(TDesC8*)a1, resourceId); sl@0: if(r==KErrNone) sl@0: *(TUint *)a2 = resourceId; sl@0: break; sl@0: } sl@0: sl@0: case RBusDevResManUs::EGetResourceInfo: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetResourceInfo")); sl@0: // a1 specifies the container holding the resource ID sl@0: // a2 specifies the address of the container to be written to sl@0: sl@0: TUint resourceId= (TUint)a1; sl@0: TPowerResourceInfoBuf01 resCtrlInfo; sl@0: resCtrlInfo.SetLength(0); sl@0: TResourceInfoBuf tempInfo; sl@0: r=((DPowerResourceController*)iPddPtr)->GetResourceInfo(ClientHandle(),resourceId,&resCtrlInfo); sl@0: if(r==KErrNone) sl@0: { sl@0: // Copy the client buffer to tempInfo so that its size can be determined sl@0: // by ExtractResourceInfo sl@0: r=ExtractResourceInfo(&(resCtrlInfo()), tempInfo); sl@0: } sl@0: if(r==KErrNone) sl@0: { sl@0: // Write the resources' info to the client thread sl@0: *(TResourceInfoBuf*)a2 = tempInfo; sl@0: } sl@0: break; sl@0: } sl@0: sl@0: sl@0: case RBusDevResManUs::ECancelChangeResourceStateRequests: sl@0: case RBusDevResManUs::ECancelGetResourceStateRequests: sl@0: case RBusDevResManUs::ECancelChangeNotificationRequests: sl@0: { sl@0: TUint resourceId = (TUint)a1; sl@0: TTrackingControl*tracker=MapRequestToTracker(aFunction); sl@0: r=CancelTrackerRequests(tracker, ETrue, resourceId, NULL); sl@0: if(r==KErrCancel) sl@0: r=KErrNone; // All cancellations were successful sl@0: break; sl@0: } sl@0: sl@0: case RBusDevResManUs::ECancelChangeResourceState: sl@0: case RBusDevResManUs::ECancelGetResourceState: sl@0: case RBusDevResManUs::ECancelRequestChangeNotification: sl@0: { sl@0: TRequestStatus* status = (TRequestStatus*)a1; sl@0: r=CancelRequestsOfType(aFunction, status); sl@0: break; sl@0: } sl@0: sl@0: sl@0: #ifdef RESOURCE_MANAGER_SIMULATED_PSL sl@0: case RBusDevResManUs::EGetNumCandidateAsyncResources: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetNumCandidateAsyncResources")); sl@0: TUint numResources; sl@0: GetNumCandidateAsyncResources(numResources); sl@0: // Write the result to the client thread sl@0: *(TUint*)a1 = numResources; sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetCandidateAsyncResourceId: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetCandidateAsyncResourceId")); sl@0: // Get the index to use sl@0: TUint index = (TUint)a1; sl@0: TUint resourceId = 0; sl@0: r=GetCandidateAsyncResourceId(index, resourceId); sl@0: if(r==KErrNone) // Write the result to the client thread sl@0: *(TUint*)a2 = resourceId; sl@0: break; sl@0: } sl@0: sl@0: case RBusDevResManUs::EGetNumCandidateSharedResources: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetNumCandidateSharedResources")); sl@0: TUint numResources; sl@0: GetNumCandidateSharedResources(numResources); sl@0: // Write the result to the client thread sl@0: *(TUint*)a1 = numResources; sl@0: break; sl@0: } sl@0: case RBusDevResManUs::EGetCandidateSharedResourceId: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetCandidateSharedResourceId")); sl@0: // Get the index to use sl@0: TUint index = (TUint)a1; sl@0: TUint resourceId = 0; sl@0: r=GetCandidateSharedResourceId(index, resourceId); sl@0: if(r==KErrNone) // Write the result to the client thread sl@0: *(TUint*)a2 = resourceId; sl@0: break; sl@0: } sl@0: #endif sl@0: sl@0: case RBusDevResManUs::EGetResourceControllerVersion: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetResourceControllerVersion")); sl@0: // a1 specifies the address of the TVersion variable to be written to sl@0: // a2 is not used sl@0: TUint version; sl@0: if((r=((DPowerResourceController*)iPddPtr)->GetInterface(ClientHandle(), sl@0: KResManControlIoGetVersion, sl@0: (TAny*)&version, sl@0: NULL, sl@0: NULL))!=KErrNone) sl@0: return r; sl@0: // Write the required information sl@0: *(TUint*)a1 = version; sl@0: break; sl@0: } sl@0: sl@0: case RBusDevResManUs::EGetNumDependentsForResource: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetNumDependentsForResource")); sl@0: // a1 specifies a pointer to the variable to be written to sl@0: // a2 specifies an array TUint parms[2] which contains: sl@0: // - the resource ID sl@0: // - flag to indicate if dependency information is to be loaded as part of this call sl@0: TUint *parms = (TUint*)a2; sl@0: TUint numDependents = 0; sl@0: r=((DPowerResourceController*)iPddPtr)->GetInterface(ClientHandle(), sl@0: KResManControlIoGetNumDependents, sl@0: (TAny*)(parms[0]), // Resource ID sl@0: &numDependents, sl@0: NULL); sl@0: iResDepsValid=EFalse; // The number of dependents may differ from the dependency information stored sl@0: if(r!=KErrNone) sl@0: return r; sl@0: sl@0: // Load the dependency information, if required. sl@0: if(parms[1]) sl@0: { sl@0: // The dependency information may be updated subsequent to the request for the number of dependents. In order sl@0: // to provide a coherent number and array of dependents, the requests for dependency information will be sl@0: // re-issued if the (new) number of dependents differs from that previously read. sl@0: TUint prevNumDeps = 0; sl@0: TUint newNumDeps = numDependents; sl@0: while((newNumDeps != prevNumDeps)&&(r == KErrNone)) sl@0: { sl@0: if((r=EnsureSizeIsSufficient(iResourceDependencyIds, (TInt)(newNumDeps*sizeof(SResourceDependencyInfo))))!=KErrNone) sl@0: return r; sl@0: prevNumDeps = newNumDeps; sl@0: if((r=((DPowerResourceController*)iPddPtr)->GetInterface(ClientHandle(), sl@0: KResManControlIoGetDependentsId, sl@0: (TAny*)(parms[0]), // Resource ID sl@0: (TAny*)(iResourceDependencyIds), sl@0: (TAny*)&newNumDeps))!=KErrNone) sl@0: return r; sl@0: }; sl@0: // Dependency information now in synch with number reported sl@0: numDependents = newNumDeps; sl@0: iNumResDepsStored = newNumDeps; sl@0: iResDepsValid = ETrue; sl@0: } sl@0: // Write the number of dependents to the client thread sl@0: *(TUint*)a1 = numDependents; sl@0: break; sl@0: } sl@0: sl@0: sl@0: case RBusDevResManUs::EGetDependentsIdForResource: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl case EGetDependentsIdForResource")); sl@0: // a1 specifies a pointer to the variable to hold the number of dependencies sl@0: // a2 specifies an array TUint parms[4] which contains: sl@0: // - the resource ID sl@0: // - the address of the array to write the required IDs to sl@0: // - flag to indicate if dependency information is to be (re-)loaded as part of this call sl@0: TUint *parms = (TUint*)a2; sl@0: TUint numDependents = 0; sl@0: sl@0: // (Re-)Load the dependency information, if required. sl@0: if(parms[2]) sl@0: { sl@0: if((r=((DPowerResourceController*)iPddPtr)->GetInterface(ClientHandle(), sl@0: KResManControlIoGetNumDependents, sl@0: (TAny*)(parms[0]), sl@0: (TAny*)&numDependents, sl@0: NULL))!=KErrNone) sl@0: return r; sl@0: sl@0: iResDepsValid=EFalse; // The number of dependents may differ from the dependency information stored sl@0: // In order to provide a coherent number and array of dependents, the requests for dependency information sl@0: // will be re-issued if the (new) number of dependents differs from that previously read. sl@0: TUint prevNumDeps = 0; sl@0: TUint newNumDeps = numDependents; sl@0: while(newNumDeps != prevNumDeps) sl@0: { sl@0: if((r=EnsureSizeIsSufficient(iResourceDependencyIds, (TInt)(newNumDeps*sizeof(SResourceDependencyInfo))))!=KErrNone) sl@0: return r; sl@0: prevNumDeps = newNumDeps; sl@0: if((r=((DPowerResourceController*)iPddPtr)->GetInterface(ClientHandle(), sl@0: KResManControlIoGetDependentsId, sl@0: (TAny*)(parms[0]), // Resource ID sl@0: (TAny*)(iResourceDependencyIds), sl@0: (TAny*)&newNumDeps))!=KErrNone) sl@0: return r; sl@0: }; sl@0: sl@0: // Dependency information now in synch with number reported sl@0: numDependents = newNumDeps; sl@0: iNumResDepsStored = newNumDeps; sl@0: iResDepsValid = ETrue; sl@0: } sl@0: sl@0: // If iResDepsValid equals zero, the results are invalid - so return KErrNotReady. sl@0: if(iResDepsValid==0) sl@0: return KErrNotReady; sl@0: sl@0: // Write the number of dependencies available to the client sl@0: *(TUint*)a1 = iNumResDepsStored; sl@0: // Write the dependencies to the client array if it is of sufficient size sl@0: // Copy the required dependency information to the user-supplied container. sl@0: parms[1] = (TUint)iResourceDependencyIds; sl@0: break; sl@0: } sl@0: sl@0: default: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::DoControl default 0x%x", aFunction)); sl@0: r=KErrNotSupported; sl@0: } sl@0: } sl@0: return(r); sl@0: } sl@0: sl@0: sl@0: TInt DChannelResManUs::EnsureSizeIsSufficient(HBuf*& aBuffer, TInt aMinSize) sl@0: { sl@0: // Utility function to ensure a buffer is of at least the minimum required size sl@0: // If the buffer is to small, an attempt is made to increase its size. sl@0: // If the re-sizing fails, KErrNoMemory is returned; otherwise KErrNone. sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::EnsureSizeIsSufficient")); sl@0: sl@0: if(aBuffer->MaxLength() < aMinSize) sl@0: { sl@0: aBuffer = aBuffer->ReAlloc(aMinSize); sl@0: if(aBuffer->MaxLength() < aMinSize) sl@0: return KErrNoMemory; // ReAlloc failed - aBuffer is unchanged sl@0: } sl@0: aBuffer->SetLength(0); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DChannelResManUs::FreeTrackingBuffer(TTrackingBuffer*& aBuffer) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DChannelResManUs::FreeTrackingBuffer")); sl@0: // Function invoked for to free tracking buffers from the busy to free queue of a tracking control sl@0: __ASSERT_ALWAYS((aBuffer!=NULL),RESMANUS_FAULT()); sl@0: NKern::FMWait(&iBufferFastMutex); sl@0: TTrackingControl* tracker = aBuffer->GetTrackingControl(); sl@0: SDblQue* bufQue = aBuffer->GetQue(); sl@0: sl@0: __ASSERT_ALWAYS(((tracker!=NULL)&&(bufQue!=NULL)),RESMANUS_FAULT()); sl@0: sl@0: // Check that the buffer is still in the busy queue of the tracker - exit if not sl@0: if(bufQue == tracker->iBusyQue) sl@0: { sl@0: aBuffer->Deque(); sl@0: tracker->iFreeQue->Add(aBuffer); sl@0: aBuffer->SetQue(tracker->iFreeQue); sl@0: } sl@0: NKern::FMSignal(&iBufferFastMutex); sl@0: } sl@0: sl@0: sl@0: TInt DChannelResManUs::GetAndInitTrackingBuffer(TTrackingControl*& aTracker, TTrackingBuffer*& aBuffer, TUint aResourceId, TRequestStatus* aStatus) sl@0: { sl@0: // Utility function - perform the necessary processing to get a buffer to support sl@0: // asynchronous requests to change the state of a resource sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::GetAndInitTrackingBuffer")); sl@0: TInt r=KErrNone; sl@0: NKern::FMWait(&iBufferFastMutex); sl@0: if(aTracker->iFreeQue->IsEmpty()) sl@0: r = KErrUnderflow; sl@0: else sl@0: { sl@0: // Need intermediate cast from SDblQueLink* to TAny* before TTrackingBuffer* sl@0: TAny* ptr = (TAny*)(aTracker->iFreeQue->GetFirst()); sl@0: aBuffer = (TTrackingBuffer*)ptr; sl@0: aTracker->iBusyQue->Add((SDblQueLink*)ptr); sl@0: aBuffer->SetQue(aTracker->iBusyQue); sl@0: aBuffer->SetResourceId(aResourceId); sl@0: TClientRequest* request; sl@0: TTrackingControl* tracker = aBuffer->GetTrackingControl(); sl@0: GET_USER_REQUEST(request, aBuffer, tracker->iType); sl@0: request->Reset(); sl@0: request->SetStatus(aStatus); sl@0: } sl@0: NKern::FMSignal(&iBufferFastMutex); sl@0: return r; sl@0: } sl@0: sl@0: TInt DChannelResManUs::GetStateBuffer(TTrackingControl*& aTracker, TTrackingBuffer*& aBuffer, TUint aResourceId, TInt* aState, TInt* aLevelOwnerPtr, TPowerResourceCb*& aCb, TRequestStatus* aStatus) sl@0: { sl@0: // Utility function - perform the necessary processing to get a buffer and control block sl@0: // to support asynchronous requests to change the state of a resource sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::GetStateBuffer")); sl@0: sl@0: TInt r=GetAndInitTrackingBuffer(aTracker, aBuffer, aResourceId, aStatus); sl@0: if(r==KErrNone) sl@0: { sl@0: TTrackGetStateBuf* stateBuf = (TTrackGetStateBuf*)aBuffer; sl@0: stateBuf->iRequest->SetDestPtr1(aState); sl@0: stateBuf->iRequest->SetDestPtr2(aLevelOwnerPtr); sl@0: // Use placement new to update the content of the TPowerResourceCb sl@0: aCb = &(stateBuf->iCtrlBlock); sl@0: new (aCb) TPowerResourceCb(&AsyncCallBackFn,(TAny*)aBuffer,iDfcQ,KResManCallBackPriority); sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: sl@0: #ifdef _DUMP_TRACKERS sl@0: TInt DChannelResManUs::DumpTracker(TTrackingControl* aTracker) sl@0: { sl@0: Kern::Printf("\nDChannelResManUs::DumpTracker"); sl@0: Kern::Printf("Tracker at 0x%x\n",aTracker); sl@0: if(NULL==aTracker) sl@0: return KErrGeneral; sl@0: Kern::Printf("iType=%d",aTracker->iType); sl@0: switch(aTracker->iType) sl@0: { sl@0: case 0: sl@0: Kern::Printf("= GetState tracker\n"); sl@0: break; sl@0: case 1: sl@0: Kern::Printf("= SetState tracker\n"); sl@0: break; sl@0: case 2: sl@0: Kern::Printf("= Notify tracker\n"); sl@0: break; sl@0: } sl@0: Kern::Printf("iOwningChannel at 0x%x\n",aTracker->iOwningChannel); sl@0: Kern::Printf("iFreeQue at 0x%x\n",aTracker->iFreeQue); sl@0: SDblQueLink* buf; sl@0: if(aTracker->iFreeQue!=NULL) sl@0: { sl@0: buf=aTracker->iFreeQue->First(); sl@0: while(buf!=aTracker->iFreeQue->Last()) sl@0: { sl@0: Kern::Printf("iFreeQue buffer at 0x%x\n",buf); sl@0: TAny* intermediatePtr = (TAny*)buf; sl@0: if((aTracker->iType == EGetState)||(aTracker->iType == ESetState)) sl@0: { sl@0: TTrackStateBuf* tempBuf =(TTrackStateBuf*)intermediatePtr; sl@0: Kern::Printf("buffer control block at 0x%x\n",tempBuf->iCtrlBlock); sl@0: } sl@0: buf= buf->iNext; sl@0: }; sl@0: } sl@0: Kern::Printf("iBusyQue at 0x%x\n",aTracker->iBusyQue); sl@0: if(aTracker->iBusyQue!=NULL) sl@0: { sl@0: buf=aTracker->iBusyQue->First(); sl@0: while(buf!=aTracker->iBusyQue->Last()) sl@0: { sl@0: Kern::Printf("iBusyQue buffer at 0x%x\n",buf); sl@0: TAny* intermediatePtr = (TAny*)buf; sl@0: if((aTracker->iType == EGetState)||(aTracker->iType == ESetState)) sl@0: { sl@0: TTrackStateBuf* tempBuf =(TTrackStateBuf*)intermediatePtr; sl@0: Kern::Printf("buffer control block at 0x%x\n",tempBuf->iCtrlBlock); sl@0: } sl@0: buf= buf->iNext; sl@0: }; sl@0: } sl@0: sl@0: return KErrNone; sl@0: } sl@0: #endif sl@0: sl@0: TInt DChannelResManUs::InitTrackingControl(TTrackingControl*& aTracker, TUint8 aType, TUint8 aNumBuffers) sl@0: { sl@0: // Set the tracker type, create the tracking queues and required tracking buffers. sl@0: // Assign all the tracking buffers to the free queue. sl@0: // sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::InitTrackingControl()")); sl@0: sl@0: TInt r = KErrNone; sl@0: aTracker->iType = (TAsyncOpType)aType; sl@0: aTracker->iOwningChannel = this; sl@0: aTracker->iFreeQue = new SDblQue(); sl@0: __ASSERT_DEBUG(aTracker->iFreeQue != NULL, RESMANUS_FAULT()); sl@0: if(aTracker->iFreeQue == NULL) sl@0: r = KErrNoMemory; sl@0: if(r==KErrNone) sl@0: { sl@0: aTracker->iBusyQue = new SDblQue(); sl@0: __ASSERT_DEBUG(aTracker->iBusyQue != NULL, RESMANUS_FAULT()); sl@0: if(aTracker->iBusyQue == NULL) sl@0: { sl@0: delete aTracker->iFreeQue; sl@0: r = KErrNoMemory; sl@0: } sl@0: } sl@0: if(r==KErrNone) sl@0: { sl@0: for(TUint8 i=0; (iiType) sl@0: { sl@0: case EGetState: sl@0: { sl@0: buf = (TAny*)(new TTrackGetStateBuf(&AsyncCallBackFn,ptr,iDfcQ,KResManCallBackPriority)); sl@0: r = Kern::CreateClientDataRequest2(((TTrackGetStateBuf*)buf)->iRequest); sl@0: break; sl@0: } sl@0: case ESetState: sl@0: { sl@0: buf = (TAny*)(new TTrackSetStateBuf(&AsyncCallBackFn, ptr, iDfcQ, KResManCallBackPriority)); sl@0: r = Kern::CreateClientRequest(((TTrackSetStateBuf*)buf)->iRequest); sl@0: break; sl@0: } sl@0: case ENotify: sl@0: { sl@0: buf = (TAny*)(new TTrackNotifyBuf(&AsyncCallBackFn,ptr,iDfcQ,KResManCallBackPriority)); sl@0: r = Kern::CreateClientRequest(((TTrackNotifyBuf*)buf)->iRequest); sl@0: break; sl@0: } sl@0: default: sl@0: __ASSERT_ALWAYS(0,RESMANUS_FAULT()); sl@0: } sl@0: __ASSERT_DEBUG(buf!=NULL, RESMANUS_FAULT()); sl@0: if((buf == NULL) || (r == KErrNoMemory)) sl@0: { sl@0: r = KErrNoMemory; sl@0: break; sl@0: } sl@0: else sl@0: { sl@0: ((TTrackingBuffer*)buf)->SetTrackingControl(aTracker); sl@0: (aTracker->iFreeQue)->Add((SDblQueLink*)buf); sl@0: ((TTrackingBuffer*)buf)->SetQue(aTracker->iFreeQue); sl@0: } sl@0: } sl@0: // If buffer allocation failed, need to remove all previously-allocated buffers and the queues sl@0: if(r!=KErrNone) sl@0: { sl@0: SDblQueLink* ptr = (aTracker->iFreeQue)->First(); sl@0: do sl@0: { sl@0: SDblQueLink* next = NULL; sl@0: if(ptr !=NULL) sl@0: next = ptr->iNext; sl@0: delete ptr; sl@0: ptr = next; sl@0: } while ((ptr!=NULL)&&(ptr!=(aTracker->iFreeQue)->Last())); sl@0: delete aTracker->iFreeQue; sl@0: delete aTracker->iBusyQue; sl@0: } sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: sl@0: void DChannelResManUs::RemoveTrackingControl(TTrackingControl*& aTracker) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DChannelResManUs::RemoveTrackingControl()")); sl@0: sl@0: // Free the resource-tracking links and their respective queues sl@0: TAny* buf; sl@0: if(aTracker->iFreeQue!=NULL) sl@0: { sl@0: while(!aTracker->iFreeQue->IsEmpty()) sl@0: { sl@0: buf = (TAny*)(aTracker->iFreeQue->GetFirst()); // Dequeues the element sl@0: delete buf; sl@0: } sl@0: delete aTracker->iFreeQue; sl@0: } sl@0: sl@0: if(aTracker->iBusyQue!=NULL) sl@0: { sl@0: while(!aTracker->iBusyQue->IsEmpty()) sl@0: { sl@0: buf = (TAny*)(aTracker->iBusyQue->GetFirst()); // Dequeues the element sl@0: delete buf; sl@0: } sl@0: delete aTracker->iBusyQue; sl@0: } sl@0: delete aTracker; sl@0: } sl@0: sl@0: sl@0: #ifdef RESOURCE_MANAGER_SIMULATED_PSL sl@0: void DChannelResManUs::CheckForCandidateAsyncResource(TPowerResourceInfoV01* aResource) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::CheckForCandidateAsyncResource")); sl@0: // Proceed only if we already have less that the maximum number of candidate resources sl@0: if(iNoCandidateAsyncRes >= MAX_NUM_CANDIDATE_RESOURCES) sl@0: return; sl@0: // For the purposes of asynchronous testing, we need a long latency resource sl@0: if(((TInt)(aResource->iLatencyGet)==(TInt)(EResLongLatency)) && sl@0: ((TInt)(aResource->iLatencySet)==(TInt)(EResLongLatency))) sl@0: { sl@0: // An additional requirement is that the level of the resource can be sl@0: // updated a sufficient amount of times to support the required testing. sl@0: if(((aResource->iMaxLevel - aResource->iMinLevel) > LEVEL_GAP_REQUIRED_FOR_ASYNC_TESTING) && sl@0: ((TInt)(aResource->iSense) == (TInt)(EResPositive)) ) sl@0: { sl@0: TInt r=((DPowerResourceController*)iPddPtr)->GetResourceId(ClientHandle(), *(aResource->iResourceName), iCandidateAsyncResIds[iNoCandidateAsyncRes]); sl@0: if(r!=KErrNone) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("Failed to identify long latency resource\n")); sl@0: } sl@0: else sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("Potential async resource ID = %d\n",iCandidateAsyncResIds[iNoCandidateAsyncRes])); sl@0: iHaveLongLatencyResource = ETrue; sl@0: ++iNoCandidateAsyncRes; sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: void DChannelResManUs::GetNumCandidateAsyncResources(TUint& aNumResources) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::GetNumCandidateAsyncResources")); sl@0: sl@0: aNumResources = iNoCandidateAsyncRes; sl@0: } sl@0: sl@0: TInt DChannelResManUs::GetCandidateAsyncResourceId(TUint aIndex, TUint& aResourceId) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::GetCandidateAsyncResourceId")); sl@0: TInt r = KErrNone; sl@0: if(aIndex>=iNoCandidateAsyncRes) sl@0: r = KErrNotFound; sl@0: else sl@0: aResourceId = iCandidateAsyncResIds[aIndex]; sl@0: return r; sl@0: } sl@0: sl@0: void DChannelResManUs::CheckForCandidateSharedResource(TPowerResourceInfoV01* aResource) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::CheckForCandidateSharedResource")); sl@0: sl@0: // Proceed only if we already have less that the maximum number of candidate resources sl@0: if(iNoCandidateSharedRes >= MAX_NUM_CANDIDATE_RESOURCES) sl@0: return; sl@0: sl@0: // For the purposes of testing shared usgae of resources, we need a shareable resource sl@0: if((TInt)(aResource->iUsage)==(TInt)(EResShared)) sl@0: { sl@0: // An additional requirement is that the level of the resource can be sl@0: // updated a sufficient amount of times to support the required testing. sl@0: if(((aResource->iMaxLevel - aResource->iMinLevel) > LEVEL_GAP_REQUIRED_FOR_SHARED_TESTING) && sl@0: ((TInt)(aResource->iSense) == (TInt)(EResPositive)) ) sl@0: { sl@0: TInt r=((DPowerResourceController*)iPddPtr)->GetResourceId(ClientHandle(), *(aResource->iResourceName), iCandidateSharedResIds[iNoCandidateSharedRes]); sl@0: if(r!=KErrNone) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("Failed to identify shared resource\n")); sl@0: } sl@0: else sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("Potential shared resource ID = %d\n",iCandidateSharedResIds[iNoCandidateAsyncRes])); sl@0: iHaveLongLatencyResource = ETrue; sl@0: ++iNoCandidateSharedRes; sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: void DChannelResManUs::GetNumCandidateSharedResources(TUint& aNumResources) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::GetNumCandidateSharedResources")); sl@0: sl@0: aNumResources = iNoCandidateSharedRes; sl@0: } sl@0: sl@0: TInt DChannelResManUs::GetCandidateSharedResourceId(TUint aIndex, TUint& aResourceId) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::GetCandidateSharedResourceId")); sl@0: TInt r = KErrNone; sl@0: if(aIndex>=iNoCandidateSharedRes) sl@0: r = KErrNotFound; sl@0: else sl@0: aResourceId = iCandidateSharedResIds[aIndex]; sl@0: return r; sl@0: } sl@0: sl@0: #endif sl@0: sl@0: TInt DChannelResManUs::ExtractResourceInfo(const TPowerResourceInfoV01* aPwrResInfo, TResourceInfoBuf& aInfo) sl@0: { sl@0: // Extract data from a TPowerResourceInfoV01 object to a TResourceInfo instance sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::ExtractResourceInfo")); sl@0: sl@0: TInt r=KErrNone; sl@0: TInt copyLength=(((aInfo().iName).MaxLength())<((aPwrResInfo->iResourceName)->Length()))? sl@0: (aInfo().iName).MaxLength(): sl@0: (aPwrResInfo->iResourceName)->Length(); sl@0: (aInfo().iName).Copy((aPwrResInfo->iResourceName)->Ptr(),copyLength); sl@0: aInfo().iId = aPwrResInfo->iResourceId; sl@0: aInfo().iClass = (TResourceClass)aPwrResInfo->iClass; sl@0: aInfo().iType = (TResourceType)aPwrResInfo->iType; sl@0: aInfo().iUsage = (TResourceUsage)aPwrResInfo->iUsage; sl@0: aInfo().iSense = (TResourceSense)aPwrResInfo->iSense; sl@0: aInfo().iMinLevel = aPwrResInfo->iMinLevel; sl@0: aInfo().iMaxLevel = aPwrResInfo->iMaxLevel; sl@0: sl@0: #ifdef _DUMP_TRACKERS sl@0: r=DumpResource(aPwrResInfo); sl@0: #endif sl@0: return r; sl@0: } sl@0: sl@0: #ifdef _DUMP_TRACKERS sl@0: TInt DChannelResManUs::DumpResource(const TPowerResourceInfoV01* aResource) sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("> DChannelResManUs::DumpResource")); sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("Resource name = %S \n",aResource->iResourceName)); sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("Resource ID = 0x%d \n",aResource->iResourceId)); sl@0: switch(aResource->iClass) sl@0: { sl@0: case DStaticPowerResource::EPhysical: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("class = EPhysical\n")); sl@0: break; sl@0: } sl@0: case DStaticPowerResource::ELogical: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("class = ELogical\n")); sl@0: break; sl@0: } sl@0: default: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("class = % is UNKNOWN!\n")); sl@0: return KErrGeneral; sl@0: } sl@0: } sl@0: switch(aResource->iType) sl@0: { sl@0: case DStaticPowerResource::EBinary: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("type = EBinary\n")); sl@0: break; sl@0: } sl@0: case DStaticPowerResource::EMultilevel: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("type = EMultilevel\n")); sl@0: break; sl@0: } sl@0: case DStaticPowerResource::EMultiProperty: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("type = EMultiProperty\n")); sl@0: break; sl@0: } sl@0: default: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("type = % is UNKNOWN!\n")); sl@0: return KErrGeneral; sl@0: } sl@0: } sl@0: switch(aResource->iUsage) sl@0: { sl@0: case DStaticPowerResource::ESingleUse: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("usage = ESingleUse\n")); sl@0: break; sl@0: } sl@0: case DStaticPowerResource::EShared: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("usage = EShared\n")); sl@0: break; sl@0: } sl@0: default: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("usage = % is UNKNOWN!\n")); sl@0: return KErrGeneral; sl@0: } sl@0: } sl@0: switch(aResource->iSense) sl@0: { sl@0: case DStaticPowerResource::EPositive: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("sense = EPositive\n")); sl@0: break; sl@0: } sl@0: case DStaticPowerResource::ENegative: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("sense = ENegative\n")); sl@0: break; sl@0: } sl@0: case DStaticPowerResource::ECustom: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("sense = ECustom\n")); sl@0: break; sl@0: } sl@0: default: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("sense = % is UNKNOWN!\n")); sl@0: return KErrGeneral; sl@0: } sl@0: } sl@0: switch(aResource->iLatencyGet) sl@0: { sl@0: case DStaticPowerResource::EInstantaneous: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("latency get = EInstantaneous\n")); sl@0: break; sl@0: } sl@0: case DStaticPowerResource::ENegative: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("latency get = ELongLatency\n")); sl@0: break; sl@0: } sl@0: default: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("latency get = % is UNKNOWN!\n")); sl@0: return KErrGeneral; sl@0: } sl@0: } sl@0: switch(aResource->iLatencySet) sl@0: { sl@0: case DStaticPowerResource::EInstantaneous: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("latency set = EInstantaneous\n")); sl@0: break; sl@0: } sl@0: case DStaticPowerResource::ENegative: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("latency set = ELongLatency\n")); sl@0: break; sl@0: } sl@0: default: sl@0: { sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("latency set = % is UNKNOWN!\n")); sl@0: return KErrGeneral; sl@0: } sl@0: } sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DefaultLevel = %d\n",aResource->iDefaultLevel)); sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("MinLevel = %d\n",aResource->iMinLevel)); sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("MaxLevel = %d\n",aResource->iMaxLevel)); sl@0: sl@0: return KErrNone; sl@0: } sl@0: #endif sl@0: sl@0: #ifndef RESOURCE_MANAGER_SIMULATED_PSL sl@0: DECLARE_EXTENSION_LDD() sl@0: { sl@0: return new DDeviceResManUs; sl@0: } sl@0: sl@0: sl@0: DECLARE_STANDARD_EXTENSION() sl@0: { sl@0: DDeviceResManUs* device = new DDeviceResManUs; sl@0: __KTRACE_OPT(KBOOT, Kern::Printf("DECLARE_STANDARD_EXTENSION, device = 0x%x\n",device)); sl@0: sl@0: if(device == NULL) sl@0: return KErrNoMemory; sl@0: else sl@0: { sl@0: device->iSharedDfcQue = new TDfcQue(); sl@0: if(device->iSharedDfcQue==NULL) sl@0: return KErrNoMemory; sl@0: sl@0: return (Kern::InstallLogicalDevice(device)); sl@0: } sl@0: } sl@0: #else sl@0: DECLARE_STANDARD_LDD() sl@0: { sl@0: TInt r = DSimulatedPowerResourceController::CompleteResourceControllerInitialisation(); sl@0: if(r != KErrNone) sl@0: { sl@0: // Unconditionally print message sl@0: __KTRACE_OPT(KRESMANAGER, Kern::Printf("DECLARE_STANDARD_LDD: initialise Resource Controller failed with %d\n",r)); sl@0: return NULL; sl@0: } sl@0: DDeviceResManUs* device = new DDeviceResManUs; sl@0: return device; sl@0: } sl@0: #endif