diff -r 000000000000 -r 7f656887cf89 commands/pubsub/pubsub.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commands/pubsub/pubsub.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,438 @@ +// pubsub.cpp +// +// Copyright (c) 2008 - 2010 Accenture. All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the "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: +// Accenture - Initial contribution +// + +#include +#include + +#ifdef FSHELL_TRACE_SUPPORT +#include +#include +#endif + +#include +#include + +using namespace IoUtils; + +#ifdef FSHELL_TRACE_SUPPORT +class CCmdPubsub : public CMemoryAccessCommandBase, public MBtracePubSubObserver + { +private: // From MBtracePubSubObserver + void HandlePropertyChangedL(const TBtraceTickCount& aTickCount, TUint aCategory, TUint aKey, TInt aNewValue); + void HandlePropertyChangedL(const TBtraceTickCount& aTickCount, TUint aCategory, TUint aKey, const TDesC8& aNewValue); + +#else +class CCmdPubsub : public CMemoryAccessCommandBase + { +#endif +public: + static CCommandBase* NewLC(); + ~CCmdPubsub(); + +private: + CCmdPubsub(); + void PrintKey(TUint aCategory, TUint aKey, TBool aFull=EFalse); + template + void SetKeyL(const KEYTYPE& aVal); + static TInt PropertyChanged(TAny* aSelf); + void GetAllL(TBool aNotify); + TBool IsExcluded(TUint aCat, TUint aKey) const; + +private: // From CCommandBase. + virtual const TDesC& Name() const; + virtual void DoRunL(); + virtual void ArgumentsL(RCommandArgumentList& aArguments); + virtual void OptionsL(RCommandOptionList& aOptions); + void DoCancel(); + void RunL(); + +private: + // Arguments + enum TCmd + { + EGet, ESet, EDefine, ENotify + }; + TCmd iCommand; + TUid iCategory; + TUint iKey; + // Options + HBufC* iStringVal; + TInt iIntVal; + TBool iForce; + + TBool iNotify; + TBool iDefine; + + // Other assorted stuff +#ifdef FSHELL_MEMORY_ACCESS_SUPPORT + TPropNotifyResult iNotifyResult; +#endif +#ifdef FSHELL_TRACE_SUPPORT + CBtraceReader* iReader; + CBtracePubSub* iPubSub; +#endif + TBool iUseBtrace; + CPropertyManager* iPropertyManager; + RBuf8 iValDescription; + }; + +CCommandBase* CCmdPubsub::NewLC() + { + CCmdPubsub* self = new(ELeave) CCmdPubsub(); + CleanupStack::PushL(self); + self->BaseConstructL(); + return self; + } + +CCmdPubsub::~CCmdPubsub() + { + Cancel(); + delete iStringVal; +#ifdef FSHELL_TRACE_SUPPORT + delete iPubSub; + delete iReader; +#endif + delete iPropertyManager; + iValDescription.Close(); + } + +CCmdPubsub::CCmdPubsub() + : CMemoryAccessCommandBase(EManualComplete) + { + } + +const TDesC& CCmdPubsub::Name() const + { + _LIT(KName, "pubsub"); + return KName; + } + +void CCmdPubsub::DoRunL() + { +#if defined (FSHELL_MEMORY_ACCESS_SUPPORT) + if (iForce || iUseBtrace) + { + // In order to implement the --force option, we talk to the memaccess device driver, which uses an RPropertyRef + // that isn't subject to security checks + LoadMemoryAccessL(); + } +#endif + + iValDescription.CreateL(RProperty::KMaxLargePropertySize); + + /* + if (iDelete) + { + if (!iArgList->IsPresent(1)) + { + // Delete all not supported for pubsub + PrintError(KErrArgument, _L("You must specify a key for the delete option")); + User::Leave(KErrArgument); + } + else + { +#ifdef FSHELL_MEMORY_ACCESS_SUPPORT + if (iForce) + { + err = iMemAccess.DeleteProperty(iCategory, iKey); + } + else +#endif + { + err = RProperty::Delete(iCategory, iKey); + } + } + if (err == KErrPermissionDenied) + { + PrintError(err, _L("Delete failed, retry with --force")); + } + User::LeaveIfError(err); + } + */ + if (iCommand == EDefine) iDefine = ETrue; + if (iCommand == ENotify) iNotify = ETrue; + + if ((iCommand == ESet) || iDefine) + { + if (iOptions.IsPresent(&iIntVal)) + { + // Set int + SetKeyL(iIntVal); + } + else if (iOptions.IsPresent(&iStringVal)) + { + // Set string + TPtrC8 data((TUint8*)iStringVal->Ptr(), iStringVal->Size()); + SetKeyL(data); + } + else + { + LeaveIfErr(KErrArgument, _L("set/define command requires --int or --string arguments")); + } + } + else if ((iCommand == EGet) || iNotify) + { + // Get + if (!iArguments.IsPresent(1)) + LeaveIfErr(KErrArgument, _L("get command requires key and category")); + PrintKey(iCategory.iUid, iKey, ETrue); + + if (iNotify) + { +#if defined (FSHELL_MEMORY_ACCESS_SUPPORT) + if (iForce || iUseBtrace) + { + //TPckgBuf key; + //key().iCat = iCategory.iUid; + //key().iKey = iKey; + //LeaveIfErr(iMemAccess.SetupMassPropertyNotify(key), _L("Couldn't set up notification")); + LeaveIfErr(iMemAccess.SubscribeToProperty(iCategory, iKey, iUseBtrace), _L("Couldn't subscribe to property")); +#ifdef FSHELL_TRACE_SUPPORT + if (iUseBtrace) + { + const TInt KFlushInterval = 1000000; // 1s + const TInt KBtraceBufferSize = 1 * 1024 * 1024; + TRAPL(iReader = CBtraceReader::NewL(CBtraceReader::EFlushOnBtraceThreshold, KBtraceBufferSize, KBtraceBufferSize / 2), _L("Couldn't create btrace reader")); + TRAPL(iPubSub = CBtracePubSub::NewL(*iReader), _L("Couldn't create CBtracePubSub")); + TBtraceTickCount now; + now.SetToNow(); + iReader->Start(now, KFlushInterval); + iPubSub->NotifyPropertyChangedL(*this); + return; // iPubSub will take it from here + } + else +#endif + { + iMemAccess.NotifyPropertyChange(iNotifyResult, iStatus); + SetActive(); + } + } + else +#endif + { + iPropertyManager = CPropertyManager::NewL(TCallBack(&PropertyChanged, this)); + iPropertyManager->ChangeProperty(iCategory.iUid, iKey); + } + return; // Don't complete + } + } + Complete(); + } + +template +void CCmdPubsub::SetKeyL(const KEYTYPE& aVal) + { + if (!iArguments.IsPresent(1)) + { + LeaveIfErr(KErrArgument, _L("You must specify a key to set")); + } + TInt err = KErrNone; +#if defined (FSHELL_MEMORY_ACCESS_SUPPORT) + if (iForce) + { + err = iMemAccess.SetProperty(iCategory, iKey, aVal); + } + else +#endif + { + err = RProperty::Set(iCategory, iKey, aVal); + if (err == KErrArgument) + { + LeaveIfErr(err, _L("Key does not appear to be of the right type")); + } + } + +#if defined (FSHELL_MEMORY_ACCESS_SUPPORT) + if (err == KErrNotFound && iDefine) + { + if (!iForce) + { + LeaveIfErr(err, _L("Key does not exist, cannot define it unless --force is also specified")); + } + err = iMemAccess.SetProperty(iCategory, iKey, aVal, ETrue); + } +#endif + if (err) + { + LeaveIfErr(err, _L("Error setting key")); + } + } + +void CCmdPubsub::PrintKey(TUint aCategory, TUint aKey, TBool aFull) + { + TUid cat = { aCategory }; + TInt valInt; + RBuf8& valDes = iValDescription; + valDes.Zero(); + enum TType { EUnknown, EInt, EDes }; + TType type = EUnknown; + TInt reallen = 0; + + TInt err = KErrNotFound; + +#if defined (FSHELL_MEMORY_ACCESS_SUPPORT) + if (iForce) + { + err = iMemAccess.GetProperty(cat, aKey, valInt); + if (err == KErrNone) + { + type = EInt; + } + else + { + err = iMemAccess.GetProperty(cat, aKey, valDes, reallen); + type = EDes; + } + } + else +#endif + { + // Guess the value type + // Int? + if (type == EUnknown) + { + err = RProperty::Get(cat, aKey, valInt); + if (err != KErrArgument) + { + type = EInt; + } + } + + if (type == EUnknown) + { + // Des? + err = RProperty::Get(cat, aKey, valDes); + if (err != KErrArgument) + { + type = EDes; + } + } + } + + switch(err) + { + case KErrNotFound: + PrintError(err, _L("Key 0x%x 0x%x not found"), aCategory, aKey); + break; + case KErrArgument: + PrintError(err, _L("Unknown key type, not int, des8 or des16")); + break; + case KErrPermissionDenied: + PrintError(err, _L("Permission denied on 0x%x 0x%x, retry with --force"), aCategory, aKey); + break; + case KErrNone: + // do nothing + break; + default: + PrintError(err, _L("Unrecognised error returned from RProperty")); + break; + } + + if (err == KErrNone) + { + switch (type) + { + case EInt: + Printf(_L("0x%08x 0x%08x TInt: %d (0x%x)\r\n"), aCategory, aKey, valInt, valInt); + break; + case EDes: + { + TPtrC8 des(valDes); + if (!aFull) des.Set(valDes.Left(32)); // Don't print the whole thing, only 2 lines max + Printf(_L("0x%08x 0x%08x TDesC8 hex dump:\r\n"), aCategory, aKey); + LtkUtils::HexDumpToOutput(des, Stdout()); + if (des.Length() < valDes.Length()) Write(_L("...\r\n")); + break; + } + default: + break; + } + } + } + +void CCmdPubsub::ArgumentsL(RCommandArgumentList& aArguments) + { + aArguments.AppendEnumL((TInt&)iCommand, _L("command")); + aArguments.AppendUintL((TUint&)iCategory.iUid, _L("category")); + aArguments.AppendUintL(iKey, _L("key")); + } + +void CCmdPubsub::OptionsL(RCommandOptionList& aOptions) + { + aOptions.AppendIntL(iIntVal, _L("int")); + aOptions.AppendStringL(iStringVal, _L("string")); +#ifdef FSHELL_MEMORY_ACCESS_SUPPORT + aOptions.AppendBoolL(iForce, _L("force")); +#endif +#ifdef FSHELL_TRACE_SUPPORT + aOptions.AppendBoolL(iUseBtrace, _L("btrace")); +#endif + //aOptions.AppendStringL(iStringVal, '8', _L("set-data"), _L("Sets the specified key to this 8-bit value")); + //aOptions.AppendBoolL(iDelete, 'l', _L("delete"), _L("Deletes the specified property")); + } + +TInt CCmdPubsub::PropertyChanged(TAny* aSelf) + { + CCmdPubsub* self = static_cast(aSelf); + self->PrintKey(self->iCategory.iUid, self->iKey); + return 0; + } + +EXE_BOILER_PLATE(CCmdPubsub) + +void CCmdPubsub::DoCancel() + { +#if defined (FSHELL_MEMORY_ACCESS_SUPPORT) + iMemAccess.CancelPropertyChange(); +#endif + } + +void CCmdPubsub::RunL() + { +#if defined (FSHELL_MEMORY_ACCESS_SUPPORT) + + TPropNotifyResult notifyResult = iNotifyResult; + // rerequest asap + if (iStatus == KErrNone) + { + iMemAccess.NotifyPropertyChange(iNotifyResult, iStatus); + SetActive(); + } + + if (notifyResult.iMissedChanges) + { + PrintWarning(_L("Missed %d publish and subscribe notifications"), notifyResult.iMissedChanges); + } + + if (notifyResult.iError) + { + Printf(_L("NotifyChange for 0x%08x 0x%x completed with error %d\r\n"), notifyResult.iCategory, notifyResult.iKey, notifyResult.iError); + } + else + { + //Printf(_L("P&S Key changed:\r\n")); + PrintKey(notifyResult.iCategory, notifyResult.iKey); + } +#endif + } + +#ifdef FSHELL_TRACE_SUPPORT +void CCmdPubsub::HandlePropertyChangedL(const TBtraceTickCount&, TUint aCategory, TUint aKey, TInt /*aNewValue*/) + { + PrintKey(aCategory, aKey); + } + +void CCmdPubsub::HandlePropertyChangedL(const TBtraceTickCount&, TUint aCategory, TUint aKey, const TDesC8& /*aNewValue*/) + { + PrintKey(aCategory, aKey); + } +#endif