|
1 // Copyright (c) 2002-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 // |
|
15 |
|
16 #include "t_prop_ldd.h" |
|
17 #include <kernel/kernel.h> |
|
18 #include "nk_priv.h" |
|
19 |
|
20 class DPropLDevice : public DLogicalDevice |
|
21 { |
|
22 public: |
|
23 DPropLDevice(); |
|
24 virtual TInt Install(); |
|
25 virtual void GetCaps(TDes8& aDes) const; |
|
26 virtual TInt Create(DLogicalChannelBase*& aChannel); |
|
27 }; |
|
28 |
|
29 class DPropLChannel : public DLogicalChannelBase |
|
30 { |
|
31 public: |
|
32 DPropLChannel(); |
|
33 ~DPropLChannel(); |
|
34 |
|
35 virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); |
|
36 virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2); |
|
37 |
|
38 private: |
|
39 TInt Basic(RPropChannel::TBasicInfo* aInfo); |
|
40 |
|
41 static void CompleteFn(TAny* aPtr, TInt aReason); |
|
42 TInt iReason; |
|
43 NFastSemaphore iSem; |
|
44 |
|
45 }; |
|
46 |
|
47 DECLARE_STANDARD_LDD() |
|
48 // |
|
49 // Create a new device |
|
50 // |
|
51 { |
|
52 return new DPropLDevice; |
|
53 } |
|
54 |
|
55 DPropLDevice::DPropLDevice() |
|
56 // |
|
57 // Constructor |
|
58 // |
|
59 { |
|
60 //iUnitsMask=0; |
|
61 iVersion = TVersion(1,0,1); |
|
62 // iParseMask = 0; |
|
63 } |
|
64 |
|
65 TInt DPropLDevice::Install() |
|
66 // |
|
67 // Install the device driver. |
|
68 // |
|
69 { |
|
70 TInt r = SetName(&KPropLdName); |
|
71 return r; |
|
72 } |
|
73 |
|
74 void DPropLDevice::GetCaps(TDes8&) const |
|
75 // |
|
76 // Return the Comm capabilities. |
|
77 // |
|
78 { |
|
79 } |
|
80 |
|
81 TInt DPropLDevice::Create(DLogicalChannelBase*& aChannel) |
|
82 // |
|
83 // Create a channel on the device. |
|
84 // |
|
85 { |
|
86 aChannel = new DPropLChannel; |
|
87 return aChannel ? KErrNone : KErrNoMemory; |
|
88 } |
|
89 |
|
90 DPropLChannel::DPropLChannel() |
|
91 { |
|
92 NKern::FSSetOwner(&iSem, NKern::CurrentThread()); |
|
93 } |
|
94 |
|
95 TInt DPropLChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /* aInfo*/ , const TVersion& aVer) |
|
96 // |
|
97 // Create the channel from the passed info. |
|
98 // |
|
99 { |
|
100 if (!Kern::QueryVersionSupported(TVersion(1,0,1),aVer)) |
|
101 return KErrNotSupported; |
|
102 return KErrNone; |
|
103 } |
|
104 |
|
105 DPropLChannel::~DPropLChannel() |
|
106 { |
|
107 } |
|
108 |
|
109 |
|
110 #define BASIC_ERROR(aRes, aCond) \ |
|
111 {\ |
|
112 if (!(aCond)) \ |
|
113 { \ |
|
114 Kern::Printf("Test '" #aCond "' fails; r = %d;\n\tfile '" __FILE__ "'; line %d;\n", aRes, __LINE__); \ |
|
115 prop.Close(); \ |
|
116 return EFalse; \ |
|
117 } \ |
|
118 } |
|
119 |
|
120 void DPropLChannel::CompleteFn(TAny* aPtr, TInt aReason) |
|
121 { // static |
|
122 DPropLChannel* self = (DPropLChannel*) aPtr; |
|
123 self->iReason = aReason; |
|
124 NKern::FSSignal(&self->iSem); |
|
125 } |
|
126 |
|
127 TBool DPropLChannel::Basic(RPropChannel::TBasicInfo* aInfo) |
|
128 { |
|
129 |
|
130 TUid category = aInfo->iCategory; |
|
131 TUint key = aInfo->iKey; |
|
132 TUint count = aInfo->iCount; |
|
133 RProperty::TType type = aInfo->iType; |
|
134 |
|
135 for (TUint i = 0; i < count; ++i) |
|
136 { |
|
137 RPropertyRef prop; |
|
138 TInt r = prop.Open(category, key); |
|
139 BASIC_ERROR(r, r == KErrNotFound); |
|
140 r = prop.Attach(category, key); |
|
141 BASIC_ERROR(r, r == KErrNone); |
|
142 |
|
143 // Defines the attributes and access control for a property. This can only be done |
|
144 // once for each property. Subsequent attempts to define the same property will return |
|
145 // KErrAlreadyExists. |
|
146 |
|
147 TSecurityPolicy policy; |
|
148 |
|
149 r = prop.Define(type, policy, policy); |
|
150 BASIC_ERROR(r, r == KErrNone); |
|
151 r = prop.Define(type, policy, policy); |
|
152 BASIC_ERROR(r, r == KErrAlreadyExists); |
|
153 r = prop.Delete(); |
|
154 BASIC_ERROR(r, r == KErrNone); |
|
155 |
|
156 // Define fails with KErrArgument if wrong type or attribute was specified. |
|
157 r = prop.Define(RProperty::ETypeLimit, policy, policy); |
|
158 BASIC_ERROR(r, r == KErrArgument); |
|
159 |
|
160 static _LIT_SECURITY_POLICY_PASS(KPassPolicy); |
|
161 TSecurityPolicy badPolicy; |
|
162 *(TInt*)&badPolicy = -1; |
|
163 |
|
164 r = prop.Define(type, badPolicy, policy); |
|
165 BASIC_ERROR(r, r == KErrArgument); |
|
166 r = prop.Define(type, KPassPolicy, badPolicy); |
|
167 BASIC_ERROR(r, r == KErrArgument); |
|
168 |
|
169 if (type == RProperty::EInt) |
|
170 { |
|
171 // Define fails with KErrArgument if aType is TInt and aPreallocate is not 0 |
|
172 r = prop.Define(type, KPassPolicy, KPassPolicy, 16); |
|
173 BASIC_ERROR(r, r == KErrArgument); |
|
174 |
|
175 // Following defintion the property has a default value, 0 for integer properties |
|
176 r = prop.Define(RProperty::EInt, KPassPolicy, KPassPolicy); |
|
177 BASIC_ERROR(r, r == KErrNone); |
|
178 TInt value; |
|
179 r = prop.Get(value); |
|
180 BASIC_ERROR(r, r == KErrNone); |
|
181 BASIC_ERROR(value, value == 0); |
|
182 r = prop.Delete(); |
|
183 BASIC_ERROR(r, r == KErrNone); |
|
184 } |
|
185 else |
|
186 { |
|
187 // Defne fails with KErrTooBig if aPeallocate is grater than KMaxPropertySize. |
|
188 r = prop.Define(RProperty::EByteArray, KPassPolicy, KPassPolicy, RProperty::KMaxPropertySize); |
|
189 BASIC_ERROR(r, r == KErrNone); |
|
190 r = prop.Delete(); |
|
191 BASIC_ERROR(r, r == KErrNone); |
|
192 r = prop.Define(RProperty::EByteArray, KPassPolicy, KPassPolicy, RProperty::KMaxPropertySize+1); |
|
193 BASIC_ERROR(r, r == KErrTooBig); |
|
194 |
|
195 // Following defintion the property has a default value, zero-length data for byte-array and text |
|
196 // properties. |
|
197 r = prop.Define(RProperty::EByteArray, KPassPolicy, KPassPolicy); |
|
198 BASIC_ERROR(r, r == KErrNone); |
|
199 TBuf8<16> buf; |
|
200 r = prop.Get(buf); |
|
201 BASIC_ERROR(r, r == KErrNone); |
|
202 BASIC_ERROR(buf.Size(), buf.Size() == 0); |
|
203 r = prop.Delete(); |
|
204 BASIC_ERROR(r, r == KErrNone); |
|
205 } |
|
206 |
|
207 // Pending subscriptions for this property will not be completed until a new value is published. |
|
208 TPropertySubsRequest subs(CompleteFn, this); |
|
209 iReason = KRequestPending; |
|
210 r = prop.Subscribe(subs); |
|
211 r = prop.Define(type, KPassPolicy, KPassPolicy); |
|
212 BASIC_ERROR(r, r == KErrNone); |
|
213 BASIC_ERROR(iReason, iReason == KRequestPending); |
|
214 r = prop.Delete(); |
|
215 BASIC_ERROR(r, r == KErrNone); |
|
216 NKern::FSWait(&iSem); |
|
217 BASIC_ERROR(iReason, iReason == KErrNotFound); |
|
218 |
|
219 // If the property has not been defined Delete() fails with KErrNotFound. |
|
220 r = prop.Delete(); |
|
221 BASIC_ERROR(r, r == KErrNotFound); |
|
222 |
|
223 // When deleted any pending subscriptions for the property will be completed with KErrNotFound. |
|
224 r = prop.Define(type, KPassPolicy, KPassPolicy); |
|
225 BASIC_ERROR(r, r == KErrNone); |
|
226 iReason = KRequestPending; |
|
227 r = prop.Subscribe(subs); |
|
228 BASIC_ERROR(r, r == KErrNone); |
|
229 BASIC_ERROR(iReason, iReason == KRequestPending); |
|
230 r = prop.Delete(); |
|
231 BASIC_ERROR(r, r == KErrNone); |
|
232 NKern::FSWait(&iSem); |
|
233 BASIC_ERROR(iReason, iReason == KErrNotFound); |
|
234 |
|
235 // Any new request will not complete until the property is defined and published again. |
|
236 iReason = KRequestPending; |
|
237 r = prop.Subscribe(subs); |
|
238 BASIC_ERROR(r, r == KErrNone); |
|
239 BASIC_ERROR(iReason, iReason == KRequestPending); |
|
240 r = prop.Define(type, KPassPolicy, KPassPolicy); |
|
241 BASIC_ERROR(r, r == KErrNone); |
|
242 BASIC_ERROR(iReason, iReason == KRequestPending); |
|
243 if (type == RProperty::EInt) |
|
244 { |
|
245 r = prop.Set(1); |
|
246 BASIC_ERROR(r, r == KErrNone); |
|
247 } |
|
248 else |
|
249 { |
|
250 TBuf8<16> buf((TUint8*) "Foo"); |
|
251 r = prop.Set(buf); |
|
252 BASIC_ERROR(r, r == KErrNone); |
|
253 } |
|
254 NKern::FSWait(&iSem); |
|
255 BASIC_ERROR(iReason, iReason == KErrNone); |
|
256 r = prop.Delete(); |
|
257 BASIC_ERROR(r, r == KErrNone); |
|
258 |
|
259 // If the property has not been defined Set()/Get() fail with KErrNotFound. |
|
260 { |
|
261 TInt value; |
|
262 TBuf8<16> buf; |
|
263 if (type == RProperty::EInt) |
|
264 { |
|
265 r = prop.Get(value); |
|
266 BASIC_ERROR(r, r == KErrNotFound); |
|
267 r = prop.Set(value); |
|
268 BASIC_ERROR(r, r == KErrNotFound); |
|
269 } |
|
270 else |
|
271 { |
|
272 r = prop.Get(buf); |
|
273 BASIC_ERROR(r, r == KErrNotFound); |
|
274 r = prop.Set(buf); |
|
275 BASIC_ERROR(r, r == KErrNotFound); |
|
276 } |
|
277 } |
|
278 |
|
279 r = prop.Define(type, KPassPolicy, KPassPolicy); |
|
280 BASIC_ERROR(r, r == KErrNone); |
|
281 |
|
282 // If the property is larger than KMaxPropertySize Set() fails with KErrTooBig |
|
283 { |
|
284 if (type == RProperty::EByteArray) |
|
285 { |
|
286 TBuf8<RProperty::KMaxPropertySize + 1> buf(RProperty::KMaxPropertySize + 1); |
|
287 r = prop.Set(buf); |
|
288 BASIC_ERROR(r, r == KErrTooBig); |
|
289 } |
|
290 } |
|
291 |
|
292 // When type of operation mismatch with the property type Set()/Get() fails with KErrArgument. |
|
293 { |
|
294 if (type != RProperty::EInt) |
|
295 { |
|
296 TInt value; |
|
297 r = prop.Get(value); |
|
298 BASIC_ERROR(r, r == KErrArgument); |
|
299 r = prop.Set(value); |
|
300 BASIC_ERROR(r, r == KErrArgument); |
|
301 } |
|
302 else |
|
303 { |
|
304 TBuf8<16> buf; |
|
305 r = prop.Get(buf); |
|
306 BASIC_ERROR(r, r == KErrArgument); |
|
307 r = prop.Set(buf); |
|
308 BASIC_ERROR(r, r == KErrArgument); |
|
309 } |
|
310 } |
|
311 |
|
312 // Get/Set |
|
313 if (type == RProperty::EInt) |
|
314 { |
|
315 r = prop.Set(1); |
|
316 BASIC_ERROR(r, r == KErrNone); |
|
317 TInt value = 0; |
|
318 r = prop.Get(value); |
|
319 BASIC_ERROR(r, r == KErrNone); |
|
320 BASIC_ERROR(value, value == 1); |
|
321 } |
|
322 else |
|
323 { |
|
324 TBuf8<16> ibuf((TUint8*)"Foo"); |
|
325 TBuf8<16> obuf; |
|
326 r = prop.Set(ibuf); |
|
327 BASIC_ERROR(r, r == KErrNone); |
|
328 r = prop.Get(obuf); |
|
329 BASIC_ERROR(r, r == KErrNone); |
|
330 r = obuf.Compare(ibuf); |
|
331 BASIC_ERROR(r, r == 0); |
|
332 } |
|
333 |
|
334 // If the supplied buffer is too small Get() fails with KErrOverflow and the truncated value is reported. |
|
335 if (type == RProperty::EByteArray) |
|
336 { |
|
337 TBuf8<16> ibuf((TUint8*) "0123456789012345"); |
|
338 TBuf8<16> obuf((TUint8*) "abcdefghigklmnop"); |
|
339 TPtr8 optr((TUint8*) obuf.Ptr(), 0, 15); |
|
340 r = prop.Set(ibuf); |
|
341 BASIC_ERROR(r, r == KErrNone); |
|
342 r = prop.Get(optr); |
|
343 BASIC_ERROR(r, r == KErrOverflow); |
|
344 BASIC_ERROR(optr.Length(), optr.Length() == 15); |
|
345 BASIC_ERROR(obuf[14], obuf[14] == '4'); |
|
346 BASIC_ERROR(obuf[15], obuf[15] == 'p'); |
|
347 } |
|
348 |
|
349 // The calling thread will have the specified request status signalled when the property is next updated. |
|
350 iReason = KRequestPending; |
|
351 r = prop.Subscribe(subs); |
|
352 BASIC_ERROR(r, r == KErrNone); |
|
353 BASIC_ERROR(iReason, iReason == KRequestPending); |
|
354 if (type == RProperty::EInt) |
|
355 { |
|
356 r = prop.Set(1); |
|
357 BASIC_ERROR(r, r == KErrNone); |
|
358 } |
|
359 else |
|
360 { |
|
361 TBuf8<16> buf((TUint8*) "Foo"); |
|
362 r = prop.Set(buf); |
|
363 BASIC_ERROR(r, r == KErrNone); |
|
364 } |
|
365 NKern::FSWait(&iSem); |
|
366 BASIC_ERROR(iReason, iReason == KErrNone); |
|
367 |
|
368 r = prop.Delete(); |
|
369 BASIC_ERROR(r, r == KErrNone); |
|
370 |
|
371 // Cancel an outstanding subscription request. |
|
372 // If it has not already completed, the request is completed with KErrCancelled. |
|
373 iReason = KRequestPending; |
|
374 r = prop.Subscribe(subs); |
|
375 BASIC_ERROR(r, r == KErrNone); |
|
376 BASIC_ERROR(iReason, iReason == KRequestPending); |
|
377 prop.Cancel(subs); |
|
378 NKern::FSWait(&iSem); |
|
379 BASIC_ERROR(iReason, iReason == KErrCancel); |
|
380 |
|
381 r = prop.Define(type, KPassPolicy, KPassPolicy); |
|
382 BASIC_ERROR(r, r == KErrNone); |
|
383 |
|
384 iReason = KRequestPending; |
|
385 r = prop.Subscribe(subs); |
|
386 BASIC_ERROR(r, r == KErrNone); |
|
387 BASIC_ERROR(iReason, iReason == KRequestPending); |
|
388 if (type == RProperty::EInt) |
|
389 { |
|
390 r = prop.Set(1); |
|
391 BASIC_ERROR(r, r == KErrNone); |
|
392 } |
|
393 else |
|
394 { |
|
395 TBuf8<16> buf((TUint8*) "Foo"); |
|
396 r = prop.Set(buf); |
|
397 BASIC_ERROR(r, r == KErrNone); |
|
398 } |
|
399 NKern::FSWait(&iSem); |
|
400 BASIC_ERROR(iReason, iReason == KErrNone); |
|
401 prop.Cancel(subs); |
|
402 BASIC_ERROR(iReason, iReason == KErrNone); |
|
403 |
|
404 iReason = KRequestPending; |
|
405 r = prop.Subscribe(subs); |
|
406 BASIC_ERROR(r, r == KErrNone); |
|
407 BASIC_ERROR(iReason, iReason == KRequestPending); |
|
408 prop.Cancel(subs); |
|
409 NKern::FSWait(&iSem); |
|
410 BASIC_ERROR(iReason, iReason == KErrCancel); |
|
411 |
|
412 r = prop.Delete(); |
|
413 BASIC_ERROR(r, r == KErrNone); |
|
414 |
|
415 prop.Close(); |
|
416 } |
|
417 return ETrue; |
|
418 } |
|
419 |
|
420 // |
|
421 // Client requests. |
|
422 // |
|
423 TBool DPropLChannel::Request(TInt aFunction, TAny* a1, TAny*) |
|
424 { |
|
425 TBool r; |
|
426 switch (aFunction) |
|
427 { |
|
428 case RPropChannel::EBasicTests: |
|
429 RPropChannel::TBasicInfo info; |
|
430 kumemget32(&info, a1, sizeof(info)); |
|
431 NKern::ThreadEnterCS(); |
|
432 r = Basic(&info); |
|
433 NKern::ThreadLeaveCS(); |
|
434 break; |
|
435 default: |
|
436 r = EFalse; |
|
437 break; |
|
438 } |
|
439 return r; |
|
440 } |