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