0
|
1 |
// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
2 |
// All rights reserved.
|
|
3 |
// This component and the accompanying materials are made available
|
|
4 |
// under the terms of the License "Eclipse Public License v1.0"
|
|
5 |
// which accompanies this distribution, and is available
|
|
6 |
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
|
7 |
//
|
|
8 |
// Initial Contributors:
|
|
9 |
// Nokia Corporation - initial contribution.
|
|
10 |
//
|
|
11 |
// Contributors:
|
|
12 |
//
|
|
13 |
// Description:
|
|
14 |
// e32\drivers\resourceman\rescontrol_export.cpp
|
244
|
15 |
//
|
0
|
16 |
//
|
|
17 |
|
|
18 |
#include <drivers/resourcecontrol.h>
|
|
19 |
|
|
20 |
#ifdef DEBUG_VERSION
|
|
21 |
#define GET_CRITICAL_SECTION_COUNT(thread) \
|
|
22 |
TInt CsCount = thread.iNThread.iCsCount;
|
|
23 |
|
|
24 |
#define LOCK_AND_CRITICAL_SECTION_COUNT_CHECK(thread) \
|
|
25 |
if(thread.iNThread.iCsCount != CsCount) \
|
|
26 |
Kern::Fault("PowerResourceController", __LINE__); \
|
|
27 |
if(pRC->iResourceMutex->iHoldCount != 0) \
|
|
28 |
Kern::Fault("PowerResourceController", __LINE__);
|
|
29 |
#else
|
|
30 |
#define GET_CRITICAL_SECTION_COUNT(thread)
|
|
31 |
#define LOCK_AND_CRITICAL_SECTION_COUNT_CHECK(thread)
|
|
32 |
#endif
|
|
33 |
|
|
34 |
/**
|
|
35 |
@publishedPartner
|
|
36 |
@prototype 9.5
|
|
37 |
Kernel extension or variants can call this API to set the post bool value without registering
|
|
38 |
as client with the resource controller. This can be used by the resource controller PSL to set the
|
|
39 |
specified static resources to appropriate value before resource controller is fully initialized.
|
|
40 |
@param aResId ID of the resource whose level should be set after initialisation
|
|
41 |
@param aLevel Resource level to set
|
|
42 |
@return KErrNone, if operation is success
|
|
43 |
KErrNotFound, if resource ID could not be found in the static resource array.
|
|
44 |
KErrNotSupported, if this API is called after resource controller is fully initialized
|
|
45 |
*/
|
|
46 |
EXPORT_C TInt DPowerResourceController::PostBootLevel(TUint aResId, TInt aLevel)
|
|
47 |
{
|
|
48 |
#ifdef DEBUG_VERSION
|
|
49 |
DThread& thread = Kern::CurrentThread();
|
|
50 |
GET_CRITICAL_SECTION_COUNT(thread)
|
|
51 |
#endif
|
|
52 |
__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::PostBootLevel, aResId = 0x%x, aLevel = %d",
|
|
53 |
aResId, aLevel));
|
|
54 |
DPowerResourceController* pRC = TInterface::GetPowerResourceController();
|
|
55 |
if(!pRC)
|
|
56 |
return KErrNotFound;
|
|
57 |
pRC->Lock();
|
244
|
58 |
CHECK_CONTEXT(thread);
|
0
|
59 |
//Accept the postboot level only if issued before controller is fully initialised.
|
|
60 |
if(pRC->iInitialised == EResConStartupCompleted)
|
|
61 |
{
|
|
62 |
pRC->UnLock();
|
|
63 |
LOCK_AND_CRITICAL_SECTION_COUNT_CHECK(thread)
|
|
64 |
return KErrNotSupported;
|
|
65 |
}
|
|
66 |
#ifndef PRM_ENABLE_EXTENDED_VERSION
|
|
67 |
// coverity[deref_ptr]
|
|
68 |
// aResId is checked to be more than the array entries before dereferencing pRC->iStaticResourceArray
|
244
|
69 |
if((!aResId) || (aResId > (TUint)pRC->iStaticResourceArray.Count()) || (!pRC->iStaticResourceArray[aResId-1]))
|
0
|
70 |
{
|
|
71 |
pRC->UnLock();
|
|
72 |
LOCK_AND_CRITICAL_SECTION_COUNT_CHECK(thread)
|
|
73 |
return KErrNotFound;
|
|
74 |
}
|
|
75 |
#else
|
244
|
76 |
if(!aResId || ((aResId & KIdMaskResourceWithDependencies) && ((aResId & ID_INDEX_BIT_MASK) > (TUint)pRC->iStaticResDependencyArray.Count()))
|
|
77 |
|| (!(aResId & KIdMaskResourceWithDependencies) && ((aResId > (TUint)pRC->iStaticResourceArray.Count())
|
0
|
78 |
|| (!pRC->iStaticResourceArray[aResId-1]))))
|
|
79 |
{
|
|
80 |
pRC->UnLock();
|
|
81 |
LOCK_AND_CRITICAL_SECTION_COUNT_CHECK(thread)
|
|
82 |
return KErrNotFound;
|
|
83 |
}
|
|
84 |
if(aResId & KIdMaskResourceWithDependencies)
|
|
85 |
{
|
|
86 |
aResId &= ID_INDEX_BIT_MASK;
|
|
87 |
DStaticPowerResource* pR = pRC->iStaticResDependencyArray[--aResId];
|
|
88 |
pR->iPostBootLevel=aLevel;
|
|
89 |
pR->iFlags |= SET_VALID_POST_BOOT_LEVEL;
|
|
90 |
}
|
|
91 |
else
|
|
92 |
#endif
|
244
|
93 |
if((TUint)pRC->iStaticResourceArray.Count() > aResId - 1)
|
0
|
94 |
{
|
|
95 |
DStaticPowerResource* pR=pRC->iStaticResourceArray[--aResId];
|
|
96 |
pR->iPostBootLevel=aLevel;
|
|
97 |
pR->iFlags |= SET_VALID_POST_BOOT_LEVEL; // To indicate valid post boot level is set.
|
|
98 |
}
|
|
99 |
pRC->UnLock();
|
|
100 |
LOCK_AND_CRITICAL_SECTION_COUNT_CHECK(thread)
|
|
101 |
return KErrNone;
|
|
102 |
}
|
|
103 |
|
|
104 |
/**
|
|
105 |
@publishedPartner
|
|
106 |
@prototype 9.5
|
|
107 |
Kernel extensions or variants can call this API to register the static resources before resource controller
|
|
108 |
is fully initialised.
|
|
109 |
@Param aClientId ID of the client that is requesting resource registration
|
244
|
110 |
@Param aStaticResourceArray Static resources to register with RC.
|
|
111 |
Note, that in the special case, when aResCount equals to one, this parameter is treated as a pointer to the
|
|
112 |
DStaticPowerResource (DStaticPowerResource*). Otherwise - is the pointer to array of such pointers (DStaticPowerResource*).
|
0
|
113 |
@Param aResCount Number of static resources to register with RC. This equals the size of the passed array.
|
|
114 |
@return KErrNone, if operation is success
|
|
115 |
KErrAccessDenied if clientId could not be found in the current list of registered clients or if this
|
|
116 |
client was registered as thread relative and was not called from the same thread.
|
|
117 |
KErrNotSupported if called after resource controller is fully initialised or if called from user side proxy
|
|
118 |
or if the resource is dynamic or dependency resource.
|
|
119 |
KErrNoMemory if there is insufficient memory.
|
|
120 |
KErrArgument if passed array is null or passed number of resources count is 0.
|
|
121 |
*/
|
|
122 |
EXPORT_C TInt DPowerResourceController::RegisterArrayOfStaticResources(TUint aClientId, DStaticPowerResource**& aStaticResourceArray, TUint aResCount)
|
|
123 |
{
|
|
124 |
DThread& thread = Kern::CurrentThread();
|
|
125 |
__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterStaticResource"));
|
|
126 |
DPowerResourceController* pRC = TInterface::GetPowerResourceController();
|
|
127 |
if(!pRC)
|
|
128 |
return KErrNotFound;
|
|
129 |
|
|
130 |
if(!aStaticResourceArray || (aResCount == 0))
|
|
131 |
return KErrArgument;
|
244
|
132 |
CHECK_CONTEXT(thread);
|
0
|
133 |
//Accept the registration of static resource only if issued before controller is fully initialised.
|
|
134 |
if(pRC->iInitialised == EResConStartupCompleted)
|
|
135 |
{
|
|
136 |
return KErrNotSupported;
|
|
137 |
}
|
|
138 |
//User side clients and resource with dependency are not supported.
|
|
139 |
if(aClientId & USER_SIDE_CLIENT_BIT_MASK)
|
|
140 |
{
|
|
141 |
return KErrNotSupported;
|
|
142 |
}
|
|
143 |
#ifdef PRM_ENABLE_EXTENDED_VERSION
|
244
|
144 |
// if aResCount equals to 1 aStaticResourceArray contains not an array, but simply a pointer to the resource.
|
0
|
145 |
if(aResCount == 1)
|
|
146 |
{
|
244
|
147 |
if(((DStaticPowerResource*)aStaticResourceArray)->iResourceId & (KIdMaskResourceWithDependencies | KIdMaskDynamic))
|
0
|
148 |
{
|
|
149 |
return KErrNotSupported;
|
|
150 |
}
|
|
151 |
}
|
|
152 |
else
|
|
153 |
{
|
|
154 |
for(TUint rescount = 0; rescount < aResCount; rescount++)
|
|
155 |
{
|
244
|
156 |
if(aStaticResourceArray[rescount] &&
|
|
157 |
(aStaticResourceArray[rescount]->iResourceId & (KIdMaskResourceWithDependencies | KIdMaskDynamic)))
|
0
|
158 |
{
|
|
159 |
return KErrNotSupported;
|
|
160 |
}
|
|
161 |
}
|
|
162 |
}
|
|
163 |
#endif
|
244
|
164 |
SPowerResourceClient* pC = pRC->iClientList[(TUint16)(aClientId & ID_INDEX_BIT_MASK)];
|
|
165 |
if(!pC)
|
|
166 |
{
|
|
167 |
__KTRACE_OPT(KRESMANAGER, Kern::Printf("Client ID not Found"));
|
|
168 |
return KErrAccessDenied;
|
|
169 |
}
|
|
170 |
if(pC->iClientId != aClientId)
|
|
171 |
{
|
|
172 |
__KTRACE_OPT(KRESMANAGER, Kern::Printf("Client ID instance count does not match"));
|
|
173 |
return KErrAccessDenied;
|
0
|
174 |
}
|
244
|
175 |
if(pC->iClientId & CLIENT_THREAD_RELATIVE_BIT_MASK)
|
0
|
176 |
{
|
244
|
177 |
if(pC->iThreadId != thread.iId)
|
|
178 |
{
|
|
179 |
__KTRACE_OPT(KRESMANAGER, Kern::Printf("Client not called from thread context(Thread Relative)"));
|
|
180 |
return KErrAccessDenied;
|
|
181 |
}
|
0
|
182 |
}
|
244
|
183 |
|
|
184 |
TInt r = KErrNone;
|
0
|
185 |
if(aResCount == 1)
|
|
186 |
{
|
244
|
187 |
// if aResCount equals to one, threat the pointer as a pointer to resource
|
|
188 |
r = pRC->iStaticResourceArray.Append((DStaticPowerResource*)aStaticResourceArray);
|
|
189 |
// increment count of valid resources
|
|
190 |
if(r == KErrNone && aStaticResourceArray)
|
0
|
191 |
pRC->iStaticResourceCount++;
|
|
192 |
}
|
|
193 |
else
|
|
194 |
{
|
|
195 |
for(TUint count = 0; count < aResCount; count++)
|
|
196 |
{
|
244
|
197 |
r = pRC->iStaticResourceArray.Append(aStaticResourceArray[count]);
|
|
198 |
if(r != KErrNone)
|
|
199 |
{
|
|
200 |
__KTRACE_OPT(KRESMANAGER, Kern::Printf("Could not add new static resources, r = %d", r));
|
|
201 |
break;
|
|
202 |
}
|
|
203 |
// increment count of valid resources
|
0
|
204 |
if(aStaticResourceArray[count])
|
|
205 |
pRC->iStaticResourceCount++;
|
|
206 |
}
|
|
207 |
}
|
244
|
208 |
|
|
209 |
return r;
|
0
|
210 |
}
|
|
211 |
|
|
212 |
/**
|
|
213 |
@publishedPartner
|
|
214 |
@prototype 9.5
|
|
215 |
Kernel extensions or variants can call this API to register the static resources before resource controller
|
|
216 |
is fully initialized.
|
|
217 |
@Param aClientId ID of the client that is requesting resource registration
|
|
218 |
@Param pR Static resource to register with RC.
|
|
219 |
@return KErrNone, if operation is success
|
|
220 |
KErrAccessDenied if clientId could not be found in the current list of registered clients or if this
|
|
221 |
client was registered as thread relative and was not called from the same thread.
|
|
222 |
KErrNotSupported if called after resource controller is fully initialized or if called from user side proxy
|
|
223 |
or if the resource is dynamic or dependency resource
|
|
224 |
KErrNoMemory if there is insufficient memory.
|
|
225 |
KErrArgument if passed array is null
|
|
226 |
*/
|
|
227 |
EXPORT_C TInt DPowerResourceController::RegisterStaticResource(TUint aClientId, DStaticPowerResource* pR)
|
|
228 |
{
|
|
229 |
return RegisterArrayOfStaticResources(aClientId, (DStaticPowerResource**&)pR, 1);
|
|
230 |
}
|
|
231 |
|
|
232 |
/**
|
|
233 |
@publishedPartner
|
|
234 |
@prototype 9.5
|
|
235 |
This function initialises the controller.
|
|
236 |
@return KErrNone, if operation is success or one of the system wide errors.
|
|
237 |
*/
|
244
|
238 |
RPointerArray <DStaticPowerResource> *StaticResourceArrayPtr;
|
|
239 |
#ifdef PRM_ENABLE_EXTENDED_VERSION
|
|
240 |
RPointerArray <DStaticPowerResourceD> *StaticResourceDependencyArrayPtr;
|
|
241 |
#endif
|
0
|
242 |
EXPORT_C TInt DPowerResourceController::InitController()
|
|
243 |
{
|
|
244 |
__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::InitController()"));
|
|
245 |
DPowerResourceController* pRC = TInterface::GetPowerResourceController();
|
|
246 |
if(!pRC)
|
|
247 |
return KErrNotFound;
|
|
248 |
if(pRC->iInitialised >= EResConInitialised)
|
|
249 |
{
|
|
250 |
__KTRACE_OPT(KRESMANAGER, Kern::Printf("InitController already initialised %d\n", pRC->iInitialised));
|
|
251 |
return KErrNone;
|
|
252 |
}
|
|
253 |
_LIT(KResMutexName, "RESCTRL");
|
|
254 |
TInt r=KErrNone;
|
|
255 |
//Create the message queue
|
|
256 |
pRC->iMsgQ = new TMessageQue(DPowerResourceController::MsgQFunc, pRC, NULL, 2);
|
|
257 |
if(!pRC->iMsgQ)
|
|
258 |
return KErrNoMemory;
|
|
259 |
#ifdef PRM_ENABLE_EXTENDED_VERSION
|
|
260 |
//Create the message queue for dependency resource processing.
|
|
261 |
pRC->iMsgQDependency = new TMessageQue(DPowerResourceController::MsgQDependencyFunc, pRC, NULL, 1);
|
|
262 |
if(!pRC->iMsgQDependency)
|
|
263 |
return KErrNoMemory;
|
|
264 |
#endif
|
244
|
265 |
// This method can be called in two situations - before the constructor of DPowerResourceController was called
|
|
266 |
// for the second time (placement new in the extension psl entry macro) e.g. as a result of the call to InitResources()
|
|
267 |
// from the variant::Init3() method) or after that.
|
|
268 |
|
|
269 |
// In order not to make any assumption on number of constructor invocations, a copy (binary) of the iStaticResourceArray object
|
|
270 |
// is created below, so that it could be used to later restore the original iStaticResoureceArray object if the constructor
|
|
271 |
// was called after this method. The reason for that is, that in this destructor calls the default RPointerArrayBase()
|
|
272 |
// which resets the array, i.e. it looses the information, but allocated area and pointers still exist in the memory.
|
|
273 |
// It is then valid to restore the object directly (which will copy all members, including iSize and iEntries pointers).
|
|
274 |
// This temporary object will be deleted in DPowerResourceController::InitResources() at the last stage of initialization.
|
|
275 |
// (see also comments in DPowerResourceController::DPowerResourceController())
|
|
276 |
|
|
277 |
StaticResourceArrayPtr = new RPointerArray <DStaticPowerResource>;
|
|
278 |
if(!StaticResourceArrayPtr)
|
|
279 |
return KErrNoMemory;
|
|
280 |
|
|
281 |
r = pRC->DoRegisterStaticResources(pRC->iStaticResourceArray);
|
|
282 |
if(r != KErrNone)
|
0
|
283 |
return r;
|
244
|
284 |
|
|
285 |
// make a copy (see above comment)
|
|
286 |
*StaticResourceArrayPtr = pRC->iStaticResourceArray;
|
|
287 |
|
|
288 |
// Get the actual number of static resource registered count
|
|
289 |
for(TInt resCnt = 0; resCnt < pRC->iStaticResourceArray.Count(); resCnt++)
|
0
|
290 |
{
|
|
291 |
if(pRC->iStaticResourceArray[resCnt])
|
|
292 |
pRC->iStaticResourceCount++;
|
|
293 |
}
|
|
294 |
__KTRACE_OPT(KRESMANAGER, Kern::Printf("Actual number of static resource registered = %d\n", pRC->iStaticResourceCount));
|
|
295 |
#ifdef PRM_INSTRUMENTATION_MACRO
|
|
296 |
// Btrace output of resource information of each resource.
|
|
297 |
DStaticPowerResource* pR = NULL;
|
|
298 |
TPowerResourceInfoBuf01 resInfo;
|
|
299 |
TPowerResourceInfoV01 *pResInfo;
|
244
|
300 |
for(TInt resCount = 0; resCount < pRC->iStaticResourceArray.Count(); resCount++)
|
0
|
301 |
{
|
|
302 |
pR = pRC->iStaticResourceArray[resCount];
|
|
303 |
if(!pR)
|
|
304 |
continue;
|
|
305 |
pR->GetInfo((TDes8*)resInfo.Ptr());
|
|
306 |
pResInfo = (TPowerResourceInfoV01*)resInfo.Ptr();
|
|
307 |
PRM_REGISTER_RESOURCE_TRACE
|
|
308 |
}
|
|
309 |
#endif
|
|
310 |
|
|
311 |
#ifdef PRM_ENABLE_EXTENDED_VERSION
|
244
|
312 |
StaticResourceDependencyArrayPtr = new RPointerArray <DStaticPowerResourceD>;
|
|
313 |
if(!StaticResourceDependencyArrayPtr)
|
|
314 |
return KErrNoMemory;
|
|
315 |
|
|
316 |
// Call PSL to register static resources with dependency if any exists
|
|
317 |
r = pRC->DoRegisterStaticResourcesDependency(pRC->iStaticResDependencyArray);
|
|
318 |
|
0
|
319 |
if(r != KErrNone)
|
|
320 |
return r;
|
244
|
321 |
|
|
322 |
// make a copy (see above comments for StaticResourceArrayPtr)
|
|
323 |
*StaticResourceDependencyArrayPtr = pRC->iStaticResDependencyArray;
|
|
324 |
|
|
325 |
if(pRC->iStaticResDependencyArray.Count())
|
0
|
326 |
{
|
|
327 |
DStaticPowerResourceD* pRD = NULL;
|
|
328 |
TUint count;
|
|
329 |
//Assign resource index in resource id
|
244
|
330 |
for(count = 0; count < (TUint)pRC->iStaticResDependencyArray.Count(); count++)
|
0
|
331 |
{
|
|
332 |
pRD = pRC->iStaticResDependencyArray[count];
|
|
333 |
if(!pRD)
|
|
334 |
Panic(DPowerResourceController::ERegisteringDependentStaticResourceWithHoles);
|
|
335 |
pRD->iResourceId |= ((count + 1) & ID_INDEX_BIT_MASK);
|
|
336 |
}
|
|
337 |
//Check for dependency closed loops
|
244
|
338 |
for(count = 0; count < (TUint)pRC->iStaticResDependencyArray.Count(); count++)
|
0
|
339 |
{
|
|
340 |
pRD = pRC->iStaticResDependencyArray[count];
|
|
341 |
if(!(pRD->iResourceId & KIdMaskStaticWithDependencies))
|
|
342 |
Panic(DPowerResourceController::ERegisteringNonDependentStaticResource);
|
|
343 |
//Upgrade latency state change from instantaneous to long latency
|
|
344 |
if(!pRD->LatencySet())
|
|
345 |
pRD->iFlags |= KLongLatencySet;
|
|
346 |
pRC->CheckForDependencyLoop(pRD, pRD->iResourceId, pRD->iResourceId);
|
|
347 |
}
|
|
348 |
#ifdef PRM_INSTRUMENTATION_MACRO
|
244
|
349 |
for(count = 0; count < (TUint)pRC->iStaticResDependencyArray.Count(); count++)
|
0
|
350 |
{
|
|
351 |
pR = pRC->iStaticResDependencyArray[count];
|
|
352 |
pR->GetInfo((TDes8*)resInfo.Ptr());
|
|
353 |
pResInfo = (TPowerResourceInfoV01*)resInfo.Ptr();
|
|
354 |
PRM_REGISTER_STATIC_RESOURCE_WITH_DEPENDENCY_TRACE
|
|
355 |
}
|
|
356 |
#endif
|
|
357 |
}
|
|
358 |
#endif // PRM_ENABLE_EXTENDED_VERSION
|
|
359 |
// Create mutex object
|
|
360 |
r=Kern::MutexCreate(pRC->iResourceMutex, KResMutexName, KMutexOrdResourceManager);
|
|
361 |
if(r==KErrNone) // Call PSL to create DFC queue and creation of pools with the help API's provided by generic layer.
|
|
362 |
r=pRC->DoInitController();
|
|
363 |
__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::InitController()"));
|
|
364 |
if(r == KErrNone)
|
|
365 |
{
|
|
366 |
pRC->iInitialised = EResConInitialised;
|
|
367 |
if(pRC->iDfcQ)
|
|
368 |
pRC->iMsgQ->Receive();
|
|
369 |
#ifdef PRM_ENABLE_EXTENDED_VERSION
|
|
370 |
if(pRC->iDfcQDependency)
|
|
371 |
pRC->iMsgQDependency->Receive();
|
|
372 |
#endif
|
|
373 |
}
|
|
374 |
return r;
|
|
375 |
}
|