|
1 // pubsub.cpp |
|
2 // |
|
3 // Copyright (c) 2008 - 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "Eclipse Public License v1.0" |
|
6 // which accompanies this distribution, and is available |
|
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 // |
|
9 // Initial Contributors: |
|
10 // Accenture - Initial contribution |
|
11 // |
|
12 |
|
13 #include <fshell/common.mmh> |
|
14 #include <fshell/memoryaccesscmd.h> |
|
15 |
|
16 #ifdef FSHELL_TRACE_SUPPORT |
|
17 #include <fshell/extrabtrace.h> |
|
18 #include <fshell/btrace_parser.h> |
|
19 #endif |
|
20 |
|
21 #include <fshell/ltkutils.h> |
|
22 #include <fshell/qr3dll.h> |
|
23 |
|
24 using namespace IoUtils; |
|
25 |
|
26 #ifdef FSHELL_TRACE_SUPPORT |
|
27 class CCmdPubsub : public CMemoryAccessCommandBase, public MBtracePubSubObserver |
|
28 { |
|
29 private: // From MBtracePubSubObserver |
|
30 void HandlePropertyChangedL(const TBtraceTickCount& aTickCount, TUint aCategory, TUint aKey, TInt aNewValue); |
|
31 void HandlePropertyChangedL(const TBtraceTickCount& aTickCount, TUint aCategory, TUint aKey, const TDesC8& aNewValue); |
|
32 |
|
33 #else |
|
34 class CCmdPubsub : public CMemoryAccessCommandBase |
|
35 { |
|
36 #endif |
|
37 public: |
|
38 static CCommandBase* NewLC(); |
|
39 ~CCmdPubsub(); |
|
40 |
|
41 private: |
|
42 CCmdPubsub(); |
|
43 void PrintKey(TUint aCategory, TUint aKey, TBool aFull=EFalse); |
|
44 template <class KEYTYPE> |
|
45 void SetKeyL(const KEYTYPE& aVal); |
|
46 static TInt PropertyChanged(TAny* aSelf); |
|
47 void GetAllL(TBool aNotify); |
|
48 TBool IsExcluded(TUint aCat, TUint aKey) const; |
|
49 |
|
50 private: // From CCommandBase. |
|
51 virtual const TDesC& Name() const; |
|
52 virtual void DoRunL(); |
|
53 virtual void ArgumentsL(RCommandArgumentList& aArguments); |
|
54 virtual void OptionsL(RCommandOptionList& aOptions); |
|
55 void DoCancel(); |
|
56 void RunL(); |
|
57 |
|
58 private: |
|
59 // Arguments |
|
60 enum TCmd |
|
61 { |
|
62 EGet, ESet, EDefine, ENotify |
|
63 }; |
|
64 TCmd iCommand; |
|
65 TUid iCategory; |
|
66 TUint iKey; |
|
67 // Options |
|
68 HBufC* iStringVal; |
|
69 TInt iIntVal; |
|
70 TBool iForce; |
|
71 |
|
72 TBool iNotify; |
|
73 TBool iDefine; |
|
74 |
|
75 // Other assorted stuff |
|
76 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT |
|
77 TPropNotifyResult iNotifyResult; |
|
78 #endif |
|
79 #ifdef FSHELL_TRACE_SUPPORT |
|
80 CBtraceReader* iReader; |
|
81 CBtracePubSub* iPubSub; |
|
82 #endif |
|
83 TBool iUseBtrace; |
|
84 CPropertyManager* iPropertyManager; |
|
85 RBuf8 iValDescription; |
|
86 }; |
|
87 |
|
88 CCommandBase* CCmdPubsub::NewLC() |
|
89 { |
|
90 CCmdPubsub* self = new(ELeave) CCmdPubsub(); |
|
91 CleanupStack::PushL(self); |
|
92 self->BaseConstructL(); |
|
93 return self; |
|
94 } |
|
95 |
|
96 CCmdPubsub::~CCmdPubsub() |
|
97 { |
|
98 Cancel(); |
|
99 delete iStringVal; |
|
100 #ifdef FSHELL_TRACE_SUPPORT |
|
101 delete iPubSub; |
|
102 delete iReader; |
|
103 #endif |
|
104 delete iPropertyManager; |
|
105 iValDescription.Close(); |
|
106 } |
|
107 |
|
108 CCmdPubsub::CCmdPubsub() |
|
109 : CMemoryAccessCommandBase(EManualComplete) |
|
110 { |
|
111 } |
|
112 |
|
113 const TDesC& CCmdPubsub::Name() const |
|
114 { |
|
115 _LIT(KName, "pubsub"); |
|
116 return KName; |
|
117 } |
|
118 |
|
119 void CCmdPubsub::DoRunL() |
|
120 { |
|
121 #if defined (FSHELL_MEMORY_ACCESS_SUPPORT) |
|
122 if (iForce || iUseBtrace) |
|
123 { |
|
124 // In order to implement the --force option, we talk to the memaccess device driver, which uses an RPropertyRef |
|
125 // that isn't subject to security checks |
|
126 LoadMemoryAccessL(); |
|
127 } |
|
128 #endif |
|
129 |
|
130 iValDescription.CreateL(RProperty::KMaxLargePropertySize); |
|
131 |
|
132 /* |
|
133 if (iDelete) |
|
134 { |
|
135 if (!iArgList->IsPresent(1)) |
|
136 { |
|
137 // Delete all not supported for pubsub |
|
138 PrintError(KErrArgument, _L("You must specify a key for the delete option")); |
|
139 User::Leave(KErrArgument); |
|
140 } |
|
141 else |
|
142 { |
|
143 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT |
|
144 if (iForce) |
|
145 { |
|
146 err = iMemAccess.DeleteProperty(iCategory, iKey); |
|
147 } |
|
148 else |
|
149 #endif |
|
150 { |
|
151 err = RProperty::Delete(iCategory, iKey); |
|
152 } |
|
153 } |
|
154 if (err == KErrPermissionDenied) |
|
155 { |
|
156 PrintError(err, _L("Delete failed, retry with --force")); |
|
157 } |
|
158 User::LeaveIfError(err); |
|
159 } |
|
160 */ |
|
161 if (iCommand == EDefine) iDefine = ETrue; |
|
162 if (iCommand == ENotify) iNotify = ETrue; |
|
163 |
|
164 if ((iCommand == ESet) || iDefine) |
|
165 { |
|
166 if (iOptions.IsPresent(&iIntVal)) |
|
167 { |
|
168 // Set int |
|
169 SetKeyL(iIntVal); |
|
170 } |
|
171 else if (iOptions.IsPresent(&iStringVal)) |
|
172 { |
|
173 // Set string |
|
174 TPtrC8 data((TUint8*)iStringVal->Ptr(), iStringVal->Size()); |
|
175 SetKeyL(data); |
|
176 } |
|
177 else |
|
178 { |
|
179 LeaveIfErr(KErrArgument, _L("set/define command requires --int or --string arguments")); |
|
180 } |
|
181 } |
|
182 else if ((iCommand == EGet) || iNotify) |
|
183 { |
|
184 // Get |
|
185 if (!iArguments.IsPresent(1)) |
|
186 LeaveIfErr(KErrArgument, _L("get command requires key and category")); |
|
187 PrintKey(iCategory.iUid, iKey, ETrue); |
|
188 |
|
189 if (iNotify) |
|
190 { |
|
191 #if defined (FSHELL_MEMORY_ACCESS_SUPPORT) |
|
192 if (iForce || iUseBtrace) |
|
193 { |
|
194 //TPckgBuf<SKeyPair> key; |
|
195 //key().iCat = iCategory.iUid; |
|
196 //key().iKey = iKey; |
|
197 //LeaveIfErr(iMemAccess.SetupMassPropertyNotify(key), _L("Couldn't set up notification")); |
|
198 LeaveIfErr(iMemAccess.SubscribeToProperty(iCategory, iKey, iUseBtrace), _L("Couldn't subscribe to property")); |
|
199 #ifdef FSHELL_TRACE_SUPPORT |
|
200 if (iUseBtrace) |
|
201 { |
|
202 const TInt KFlushInterval = 1000000; // 1s |
|
203 const TInt KBtraceBufferSize = 1 * 1024 * 1024; |
|
204 TRAPL(iReader = CBtraceReader::NewL(CBtraceReader::EFlushOnBtraceThreshold, KBtraceBufferSize, KBtraceBufferSize / 2), _L("Couldn't create btrace reader")); |
|
205 TRAPL(iPubSub = CBtracePubSub::NewL(*iReader), _L("Couldn't create CBtracePubSub")); |
|
206 TBtraceTickCount now; |
|
207 now.SetToNow(); |
|
208 iReader->Start(now, KFlushInterval); |
|
209 iPubSub->NotifyPropertyChangedL(*this); |
|
210 return; // iPubSub will take it from here |
|
211 } |
|
212 else |
|
213 #endif |
|
214 { |
|
215 iMemAccess.NotifyPropertyChange(iNotifyResult, iStatus); |
|
216 SetActive(); |
|
217 } |
|
218 } |
|
219 else |
|
220 #endif |
|
221 { |
|
222 iPropertyManager = CPropertyManager::NewL(TCallBack(&PropertyChanged, this)); |
|
223 iPropertyManager->ChangeProperty(iCategory.iUid, iKey); |
|
224 } |
|
225 return; // Don't complete |
|
226 } |
|
227 } |
|
228 Complete(); |
|
229 } |
|
230 |
|
231 template <class KEYTYPE> |
|
232 void CCmdPubsub::SetKeyL(const KEYTYPE& aVal) |
|
233 { |
|
234 if (!iArguments.IsPresent(1)) |
|
235 { |
|
236 LeaveIfErr(KErrArgument, _L("You must specify a key to set")); |
|
237 } |
|
238 TInt err = KErrNone; |
|
239 #if defined (FSHELL_MEMORY_ACCESS_SUPPORT) |
|
240 if (iForce) |
|
241 { |
|
242 err = iMemAccess.SetProperty(iCategory, iKey, aVal); |
|
243 } |
|
244 else |
|
245 #endif |
|
246 { |
|
247 err = RProperty::Set(iCategory, iKey, aVal); |
|
248 if (err == KErrArgument) |
|
249 { |
|
250 LeaveIfErr(err, _L("Key does not appear to be of the right type")); |
|
251 } |
|
252 } |
|
253 |
|
254 #if defined (FSHELL_MEMORY_ACCESS_SUPPORT) |
|
255 if (err == KErrNotFound && iDefine) |
|
256 { |
|
257 if (!iForce) |
|
258 { |
|
259 LeaveIfErr(err, _L("Key does not exist, cannot define it unless --force is also specified")); |
|
260 } |
|
261 err = iMemAccess.SetProperty(iCategory, iKey, aVal, ETrue); |
|
262 } |
|
263 #endif |
|
264 if (err) |
|
265 { |
|
266 LeaveIfErr(err, _L("Error setting key")); |
|
267 } |
|
268 } |
|
269 |
|
270 void CCmdPubsub::PrintKey(TUint aCategory, TUint aKey, TBool aFull) |
|
271 { |
|
272 TUid cat = { aCategory }; |
|
273 TInt valInt; |
|
274 RBuf8& valDes = iValDescription; |
|
275 valDes.Zero(); |
|
276 enum TType { EUnknown, EInt, EDes }; |
|
277 TType type = EUnknown; |
|
278 TInt reallen = 0; |
|
279 |
|
280 TInt err = KErrNotFound; |
|
281 |
|
282 #if defined (FSHELL_MEMORY_ACCESS_SUPPORT) |
|
283 if (iForce) |
|
284 { |
|
285 err = iMemAccess.GetProperty(cat, aKey, valInt); |
|
286 if (err == KErrNone) |
|
287 { |
|
288 type = EInt; |
|
289 } |
|
290 else |
|
291 { |
|
292 err = iMemAccess.GetProperty(cat, aKey, valDes, reallen); |
|
293 type = EDes; |
|
294 } |
|
295 } |
|
296 else |
|
297 #endif |
|
298 { |
|
299 // Guess the value type |
|
300 // Int? |
|
301 if (type == EUnknown) |
|
302 { |
|
303 err = RProperty::Get(cat, aKey, valInt); |
|
304 if (err != KErrArgument) |
|
305 { |
|
306 type = EInt; |
|
307 } |
|
308 } |
|
309 |
|
310 if (type == EUnknown) |
|
311 { |
|
312 // Des? |
|
313 err = RProperty::Get(cat, aKey, valDes); |
|
314 if (err != KErrArgument) |
|
315 { |
|
316 type = EDes; |
|
317 } |
|
318 } |
|
319 } |
|
320 |
|
321 switch(err) |
|
322 { |
|
323 case KErrNotFound: |
|
324 PrintError(err, _L("Key 0x%x 0x%x not found"), aCategory, aKey); |
|
325 break; |
|
326 case KErrArgument: |
|
327 PrintError(err, _L("Unknown key type, not int, des8 or des16")); |
|
328 break; |
|
329 case KErrPermissionDenied: |
|
330 PrintError(err, _L("Permission denied on 0x%x 0x%x, retry with --force"), aCategory, aKey); |
|
331 break; |
|
332 case KErrNone: |
|
333 // do nothing |
|
334 break; |
|
335 default: |
|
336 PrintError(err, _L("Unrecognised error returned from RProperty")); |
|
337 break; |
|
338 } |
|
339 |
|
340 if (err == KErrNone) |
|
341 { |
|
342 switch (type) |
|
343 { |
|
344 case EInt: |
|
345 Printf(_L("0x%08x 0x%08x TInt: %d (0x%x)\r\n"), aCategory, aKey, valInt, valInt); |
|
346 break; |
|
347 case EDes: |
|
348 { |
|
349 TPtrC8 des(valDes); |
|
350 if (!aFull) des.Set(valDes.Left(32)); // Don't print the whole thing, only 2 lines max |
|
351 Printf(_L("0x%08x 0x%08x TDesC8 hex dump:\r\n"), aCategory, aKey); |
|
352 LtkUtils::HexDumpToOutput(des, Stdout()); |
|
353 if (des.Length() < valDes.Length()) Write(_L("...\r\n")); |
|
354 break; |
|
355 } |
|
356 default: |
|
357 break; |
|
358 } |
|
359 } |
|
360 } |
|
361 |
|
362 void CCmdPubsub::ArgumentsL(RCommandArgumentList& aArguments) |
|
363 { |
|
364 aArguments.AppendEnumL((TInt&)iCommand, _L("command")); |
|
365 aArguments.AppendUintL((TUint&)iCategory.iUid, _L("category")); |
|
366 aArguments.AppendUintL(iKey, _L("key")); |
|
367 } |
|
368 |
|
369 void CCmdPubsub::OptionsL(RCommandOptionList& aOptions) |
|
370 { |
|
371 aOptions.AppendIntL(iIntVal, _L("int")); |
|
372 aOptions.AppendStringL(iStringVal, _L("string")); |
|
373 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT |
|
374 aOptions.AppendBoolL(iForce, _L("force")); |
|
375 #endif |
|
376 #ifdef FSHELL_TRACE_SUPPORT |
|
377 aOptions.AppendBoolL(iUseBtrace, _L("btrace")); |
|
378 #endif |
|
379 //aOptions.AppendStringL(iStringVal, '8', _L("set-data"), _L("Sets the specified key to this 8-bit value")); |
|
380 //aOptions.AppendBoolL(iDelete, 'l', _L("delete"), _L("Deletes the specified property")); |
|
381 } |
|
382 |
|
383 TInt CCmdPubsub::PropertyChanged(TAny* aSelf) |
|
384 { |
|
385 CCmdPubsub* self = static_cast<CCmdPubsub*>(aSelf); |
|
386 self->PrintKey(self->iCategory.iUid, self->iKey); |
|
387 return 0; |
|
388 } |
|
389 |
|
390 EXE_BOILER_PLATE(CCmdPubsub) |
|
391 |
|
392 void CCmdPubsub::DoCancel() |
|
393 { |
|
394 #if defined (FSHELL_MEMORY_ACCESS_SUPPORT) |
|
395 iMemAccess.CancelPropertyChange(); |
|
396 #endif |
|
397 } |
|
398 |
|
399 void CCmdPubsub::RunL() |
|
400 { |
|
401 #if defined (FSHELL_MEMORY_ACCESS_SUPPORT) |
|
402 |
|
403 TPropNotifyResult notifyResult = iNotifyResult; |
|
404 // rerequest asap |
|
405 if (iStatus == KErrNone) |
|
406 { |
|
407 iMemAccess.NotifyPropertyChange(iNotifyResult, iStatus); |
|
408 SetActive(); |
|
409 } |
|
410 |
|
411 if (notifyResult.iMissedChanges) |
|
412 { |
|
413 PrintWarning(_L("Missed %d publish and subscribe notifications"), notifyResult.iMissedChanges); |
|
414 } |
|
415 |
|
416 if (notifyResult.iError) |
|
417 { |
|
418 Printf(_L("NotifyChange for 0x%08x 0x%x completed with error %d\r\n"), notifyResult.iCategory, notifyResult.iKey, notifyResult.iError); |
|
419 } |
|
420 else |
|
421 { |
|
422 //Printf(_L("P&S Key changed:\r\n")); |
|
423 PrintKey(notifyResult.iCategory, notifyResult.iKey); |
|
424 } |
|
425 #endif |
|
426 } |
|
427 |
|
428 #ifdef FSHELL_TRACE_SUPPORT |
|
429 void CCmdPubsub::HandlePropertyChangedL(const TBtraceTickCount&, TUint aCategory, TUint aKey, TInt /*aNewValue*/) |
|
430 { |
|
431 PrintKey(aCategory, aKey); |
|
432 } |
|
433 |
|
434 void CCmdPubsub::HandlePropertyChangedL(const TBtraceTickCount&, TUint aCategory, TUint aKey, const TDesC8& /*aNewValue*/) |
|
435 { |
|
436 PrintKey(aCategory, aKey); |
|
437 } |
|
438 #endif |