--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mtpfws/mtpfw/src/cmtpdataprovider.cpp Tue Feb 02 01:11:40 2010 +0200
@@ -0,0 +1,811 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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:
+//
+
+#include <mtp/cmtpdataproviderplugin.h>
+#include <mtp/mtpdataproviderconfig.hrh>
+#include <mtp/mtpprotocolconstants.h>
+#include <mtp/tmtptyperesponse.h>
+
+#include "cmtpsession.h"
+#include "cmtpconnection.h"
+#include "cmtpconnectionmgr.h"
+#include "cmtpdataprovider.h"
+#include "cmtpdataproviderconfig.h"
+#include "cmtpframeworkconfig.h"
+#include "cmtpobjectmgr.h"
+#include "cmtpparserrouter.h"
+#include "cmtpreferencemgr.h"
+#include "cmtpstoragemgr.h"
+#include "mmtptransactionproxy.h"
+#include "rmtpframework.h"
+#include "cdummydp.h"
+#include "cmtpdatacodegenerator.h"
+
+// Class constants.
+__FLOG_STMT(_LIT8(KComponent,"DataProvider");)
+
+const TInt KWaitForEnumeration = 1000000 * 3;
+
+#define KMTPDummyDataProvider 0x0000
+
+/**
+CMTPDataProvider factory method.
+@param aId The data provider identifier.
+@param aUid The data provider implementation UID.
+@param aConfig The data provider configurability parameter data. Ownership IS
+transfered.
+@return A pointer to a new CMTPDataProvider instance. Ownership IS transfered.
+@leave One of the system wide error codes if a processing failure occurs.
+*/
+CMTPDataProvider* CMTPDataProvider::NewL(TUint aId, TUid aUid, CMTPDataProviderConfig* aConfig)
+ {
+ CMTPDataProvider* self = CMTPDataProvider::NewLC(aId, aUid, aConfig);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/**
+CMTPDataProvider factory method. A pointer to the CMTPDataProvider instance is
+placed on the cleanup stack.
+@param aUid The data provider implementation UID.
+@param aConfig The data provider configurability parameter data. Ownership IS
+transfered.
+@return A pointer to a new CMTPDataProvider instance. Ownership IS transfered.
+@leave One of the system wide error codes if a processing failure occurs.
+*/
+CMTPDataProvider* CMTPDataProvider::NewLC(TUint aId, TUid aUid, CMTPDataProviderConfig* aConfig)
+ {
+ CMTPDataProvider* self = new (ELeave) CMTPDataProvider(aId, aUid, aConfig);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+/**
+Destructor.
+*/
+CMTPDataProvider::~CMTPDataProvider()
+ {
+ __FLOG_VA((_L8("~CMTPDataProvider - Entry, data provider %d "), iId));
+ Cancel();
+ iSupported.ResetAndDestroy();
+ delete iImplementation;
+ iSingletons.Close();
+
+ // Only delete passed objects when fully constructed.
+ if (iConstructed)
+ {
+ delete iConfig;
+ }
+
+ iTimer.Close();
+ __FLOG_VA((_L8("~CMTPDataProvider - Exit, data provider %d "), iId));
+ __FLOG_CLOSE;
+ }
+
+void CMTPDataProvider::ExecuteEventL(const TMTPTypeEvent& aEvent, MMTPConnection& aConnection)
+ {
+ __FLOG_VA((_L8("ExecuteEventL - Entry, data provider %d "), iId));
+ __ASSERT_DEBUG(iImplementation, User::Invariant());
+
+ if (iTimerActive && aEvent.Uint16(TMTPTypeEvent::EEventCode) == EMTPEventCodeCancelTransaction)
+ {
+ Cancel();
+ }
+
+ // Pass this event notification directly to the plugin...
+ // In reality we will only ever see one event canceltransaction.
+ iImplementation->ProcessEventL(aEvent, aConnection);
+ __FLOG_VA((_L8("ExecuteEventL - Exit, data provider %d "), iId));
+ }
+
+void CMTPDataProvider::ExecuteRequestL(const TMTPTypeRequest& aRequest, MMTPConnection& aConnection)
+ {
+ __FLOG_VA((_L8("ExecuteRequestL - Entry, data provider %d "), iId));
+ __ASSERT_DEBUG(iImplementation, User::Invariant());
+
+ iCurrentRequest = &aRequest;
+ iCurrentConnection = &iSingletons.ConnectionMgr().ConnectionL(aConnection.ConnectionId());
+ // Schedule data provider to process this request.
+ Schedule();
+
+ __FLOG_VA((_L8("ExecuteRequestL - Exit, data provider %d "), iId));
+ }
+
+EXPORT_C void CMTPDataProvider::ExecuteProxyRequestL(const TMTPTypeRequest& aRequest, MMTPConnection& aConnection, MMTPTransactionProxy& aProxy)
+ {
+ __FLOG_VA((_L8("ExecuteProxyRequestL - Entry, data provider %d "), iId));
+ iProxy = &aProxy;
+ iCurrentRequest = &aRequest;
+ iCurrentConnection = static_cast<CMTPConnection*>(&aConnection);
+ Schedule();
+ __FLOG_VA((_L8("ExecuteProxyRequestL - Exit, data provider %d "), iId));
+ }
+
+void CMTPDataProvider::EnumerateObjectsL(TUint32 aStorageId)
+ {
+ __FLOG_VA((_L8("EnumerateObjectsL - Entry, data provider %d "), iId));
+ iEnumerationState = ((iEnumerationState & ~EObjectsEnumerationState) | EObjectsEnumerating);
+ TBool abnormaldown = EFalse;
+ iSingletons.FrameworkConfig().GetValueL(CMTPFrameworkConfig::EAbnormalDown, abnormaldown);
+ iImplementation->StartObjectEnumerationL(aStorageId, abnormaldown);
+ __FLOG_VA((_L8("EnumerateObjectsL - Exit, data provider %d "), iId));
+ }
+
+void CMTPDataProvider::EnumerateStoragesL()
+ {
+ __FLOG_VA((_L8("EnumerateStoragesL - Entry, data provider %d "), iId));
+ iEnumerationState = ((iEnumerationState & ~EStoragesEnumerationState) | EStoragesEnumerating);
+ iImplementation->StartStorageEnumerationL();
+ __FLOG_VA((_L8("EnumerateStoragesL - Exit, data provider %d "), iId));
+ }
+
+/**
+Provides the data provider's enumeration state.
+@return The data provider's enumeration state.
+*/
+EXPORT_C TUint CMTPDataProvider::EnumerationState() const
+ {
+ return iEnumerationState;
+ }
+
+/**
+Provides the data provider's implementation UID
+@return The data provider's implementation UID.
+*/
+EXPORT_C TUid CMTPDataProvider::ImplementationUid() const
+ {
+ return iImplementationUid;
+ }
+
+/**
+Provides the handle of the bound data provider plug-in.
+@return The data provider plug-in.
+*/
+EXPORT_C CMTPDataProviderPlugin& CMTPDataProvider::Plugin() const
+ {
+ __ASSERT_DEBUG(iImplementation, User::Invariant());
+ return *iImplementation;
+ }
+
+EXPORT_C TBool CMTPDataProvider::Supported(TMTPSupportCategory aCategory, TUint aCode) const
+ {
+ return iSupported[aCategory]->Supported(aCode);
+ }
+
+EXPORT_C const RArray<TUint>& CMTPDataProvider::SupportedCodes(TMTPSupportCategory aCategory) const
+ {
+ return iSupported[aCategory]->Codes();
+ }
+
+/**
+Sets the
+*/
+void CMTPDataProvider::SetDataProviderId(TUint aId)
+ {
+ __FLOG_VA((_L8("~CMTPDataProvider - Entry, data provider %d "), iId));
+ iId = aId;
+ __FLOG_VA((_L8("~CMTPDataProvider - Entry, data provider %d "), iId));
+ }
+
+/**
+Implements a linear order relation for @see CMTPDataProvider
+objects based on relative @see CMTPDataProvider::ImplementationUid.
+@param aUid The implementation UID object to match.
+@param aObject The object instance to match.
+@return Zero, if the two objects are equal; A negative value, if the first
+object is less than the second, or; A positive value, if the first object is
+greater than the second.
+*/
+TInt CMTPDataProvider::LinearOrderUid(const TUid* aUid, const CMTPDataProvider& aObject)
+ {
+ return (aUid->iUid - aObject.ImplementationUid().iUid);
+ }
+
+/**
+Implements a @see TLinearOrder for @see CMTPDataProvider objects based on
+relative @see CMTPDataProvider::ImplementationUid.
+@param aL The first object instance.
+@param aR The second object instance.
+@return Zero, if the two objects are equal; A negative value, if the first
+object is less than the second, or; A positive value, if the first object is
+greater than the second.
+*/
+TInt CMTPDataProvider::LinearOrderUid(const CMTPDataProvider& aL, const CMTPDataProvider& aR)
+ {
+ return (aL.iImplementationUid.iUid - aR.iImplementationUid.iUid);
+ }
+
+/**
+Implements a @see TLinearOrder for @see CMTPDataProvider objects based on
+relative @see CMTPDataProvider::DataProviderId.
+@param aDPId The Dataprovider ID to match.
+@param aR The second object instance.
+@return Zero, if the two objects are equal; A negative value, if the first
+object is less than the second, or; A positive value, if the first object is
+greater than the second.
+*/
+TInt CMTPDataProvider::LinearOrderDPId(const TUint* aDPId, const CMTPDataProvider& aObject)
+ {
+ return (*aDPId - aObject.DataProviderId());
+ }
+
+/**
+Implements a @see TLinearOrder for @see CMTPDataProvider objects based on
+relative @see CMTPDataProvider::DataProviderId.
+@param aL The first object instance.
+@param aR The second object instance.
+@return Zero, if the two objects are equal; A negative value, if the first
+object is less than the second, or; A positive value, if the first object is
+greater than the second.
+*/
+TInt CMTPDataProvider::LinearOrderDPId(const CMTPDataProvider& aL, const CMTPDataProvider& aR)
+ {
+ return (aL.DataProviderId() - aR.DataProviderId());
+ }
+
+/**
+Implements a @see TLinearOrder for @see CMTPDataProvider objects based on
+relative enumeration phase
+@param aL The first object instance.
+@param aR The second object instance.
+@return Zero, if the two objects are equal; A negative value, if the first
+object is less than the second, or; A positive value, if the first object is
+greater than the second.
+*/
+TInt CMTPDataProvider::LinearOrderEnumerationPhase(const CMTPDataProvider& aL, const CMTPDataProvider& aR)
+ {
+ return (aL.DataProviderConfig().UintValue(MMTPDataProviderConfig::EEnumerationPhase)
+ - aR.DataProviderConfig().UintValue(MMTPDataProviderConfig::EEnumerationPhase));
+ }
+
+
+TUint CMTPDataProvider::DataProviderId() const
+ {
+ return iId;
+ }
+
+TMTPOperationalMode CMTPDataProvider::Mode() const
+ {
+ return (iSingletons.DpController().Mode());
+ }
+
+void CMTPDataProvider::ReceiveDataL(MMTPType& aData, const TMTPTypeRequest& aRequest, MMTPConnection& aConnection)
+ {
+ __FLOG_VA((_L8("ReceiveDataL - Entry, data provider %d "), iId));
+ __ASSERT_DEBUG(iImplementation, User::Invariant());
+ __ASSERT_DEBUG(!IsActive(), User::Invariant());
+
+ if (iProxy)
+ {
+ // Pass to proxy plugin for processing
+ iProxy->ProxyReceiveDataL(aData, aRequest, aConnection, iStatus);
+ SetActive();
+
+ // Running under proxy mode so manually set the next transaction phase to be processed by the plugin
+ iProxyTransactionPhase = EResponsePhase;
+ }
+ else
+ {
+ // Inform the connection that we wish to receive data from the connection
+ CMTPConnection& connection(iSingletons.ConnectionMgr().ConnectionL(aConnection.ConnectionId()));
+ connection.ReceiveDataL(aData, aRequest, iStatus);
+ SetActive();
+ // Async call so wait for object to be activated...
+ }
+ __FLOG_VA((_L8("ReceiveDataL - Exit, data provider %d "), iId));
+ }
+
+void CMTPDataProvider::SendDataL(const MMTPType& aData, const TMTPTypeRequest& aRequest, MMTPConnection& aConnection)
+ {
+ __FLOG_VA((_L8("SendDataL - Entry, data provider %d "), iId));
+ __ASSERT_DEBUG(iImplementation, User::Invariant());
+ __ASSERT_DEBUG(!IsActive(), User::Invariant());
+
+ if (iProxy)
+ {
+ // Pass to proxy plugin for processing
+ iProxy->ProxySendDataL(aData,aRequest, aConnection, iStatus);
+ SetActive();
+
+ // Running under proxy mode so manually set the next transaction phase to be processed by the plugin
+ iProxyTransactionPhase = EResponsePhase;
+ }
+ else
+ {
+ // Pass request to connection...
+ CMTPConnection& connection(iSingletons.ConnectionMgr().ConnectionL(aConnection.ConnectionId()));
+ connection.SendDataL(aData, aRequest, iStatus);
+ SetActive();
+ // Async call so wait for object to be activated...
+ }
+ __FLOG_VA((_L8("SendDataL - Exit, data provider %d "), iId));
+ }
+
+void CMTPDataProvider::SendEventL(const TMTPTypeEvent& aEvent, MMTPConnection& aConnection)
+ {
+ __FLOG_VA((_L8("SendEventL - Entry, data provider %d "), iId));
+ __ASSERT_DEBUG(iImplementation, User::Invariant());
+
+ CMTPConnection& connection(iSingletons.ConnectionMgr().ConnectionL(aConnection.ConnectionId()));
+ connection.SendEventL(aEvent);
+ __FLOG_VA((_L8("SendEventL - Exit, data provider %d "), iId));
+ }
+
+void CMTPDataProvider::SendEventL(const TMTPTypeEvent& aEvent)
+ {
+ __FLOG_VA((_L8("SendEventL - Entry, data provider %d "), iId));
+ if (aEvent.Uint32(TMTPTypeEvent::EEventSessionID) != KMTPSessionAll)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ TUint numConnections(iSingletons.ConnectionMgr().ConnectionCount());
+
+ for (TUint i(0); (i < numConnections); i++)
+ {
+ iSingletons.ConnectionMgr()[i].SendEventL(aEvent);
+ }
+ __FLOG_VA((_L8("SendEventL - Exit, data provider %d "), iId));
+ }
+
+void CMTPDataProvider::SendResponseL(const TMTPTypeResponse& aResponse, const TMTPTypeRequest& aRequest, MMTPConnection& aConnection)
+ {
+ __FLOG_VA((_L8("SendResponseL - Entry, data provider %d "), iId));
+ __ASSERT_DEBUG(iImplementation, User::Invariant());
+ __ASSERT_DEBUG(!IsActive(), User::Invariant());
+
+ if (iProxy)
+ {
+ // Pass to proxy plugin for processing
+ iProxy->ProxySendResponseL(aResponse, aRequest, aConnection, iStatus);
+ SetActive();
+
+ // Running under proxy mode so manually set the next transaction phase to be processed by the plugin
+ iProxyTransactionPhase = ECompletingPhase;
+ }
+ else
+ {
+ CMTPConnection& connection(iSingletons.ConnectionMgr().ConnectionL(aConnection.ConnectionId()));
+ connection.SendResponseL(aResponse, aRequest, iStatus);
+ SetActive();
+ }
+ __FLOG_VA((_L8("SendResponseL - Exit, data provider %d "), iId));
+ }
+
+void CMTPDataProvider::TransactionCompleteL(const TMTPTypeRequest& aRequest, MMTPConnection& aConnection)
+ {
+ __FLOG_VA((_L8("TransactionCompleteL - Entry, data provider %d "), iId));
+ __ASSERT_DEBUG(iImplementation, User::Invariant());
+
+ if (iProxy)
+ {
+ // Pass to proxy plugin for processing
+ iProxy->ProxyTransactionCompleteL(aRequest, aConnection);
+ // Running under proxy mode so manually set the next transaction phase to be processed by the plugin
+ iProxyTransactionPhase = ERequestPhase;
+ }
+ else
+ {
+ CMTPConnection& connection(iSingletons.ConnectionMgr().ConnectionL(aConnection.ConnectionId()));
+ connection.TransactionCompleteL(aRequest);
+ }
+
+ // Clear pointers
+ iProxy = NULL;
+ iCurrentRequest = NULL;
+ iCurrentConnection = NULL;
+
+ __FLOG_VA((_L8("TransactionCompleteL - Exit, data provider %d "), iId));
+ }
+
+void CMTPDataProvider::RouteRequestRegisterL(const TMTPTypeRequest& aRequest, MMTPConnection& aConnection)
+ {
+ __FLOG_VA((_L8("RouteRequestRegisterL - Entry, data provider %d "), iId));
+ iSingletons.Router().RouteRequestRegisterL(aRequest, aConnection, iId);
+ __FLOG_VA((_L8("RouteRequestRegisterL - Exit, data provider %d "), iId));
+ }
+
+void CMTPDataProvider::RouteRequestUnregisterL(const TMTPTypeRequest& aRequest, MMTPConnection& aConnection)
+ {
+ __FLOG_VA((_L8("RouteRequestUnregister - Entry, data provider %d "), iId));
+ iSingletons.Router().RouteRequestUnregisterL(aRequest, aConnection);
+ __FLOG_VA((_L8("RouteRequestUnregister - Exit, data provider %d "), iId));
+ }
+
+#ifdef __FLOG_ACTIVE
+void CMTPDataProvider::ObjectEnumerationCompleteL(TUint32 aStorageId)
+#else
+void CMTPDataProvider::ObjectEnumerationCompleteL(TUint32 /*aStorageId*/)
+#endif // __FLOG_ACTIVE
+ {
+ __FLOG_VA((_L8("ObjectEnumerationCompleteL - Entry, data provider %d "), iId));
+ __FLOG_VA((_L8("StorageId = 0x%08X "), aStorageId));
+ iEnumerationState = ((iEnumerationState & ~EObjectsEnumerationState) | EObjectsEnumerated);
+ iSingletons.DpController().EnumerationStateChangedL(*this);
+ __FLOG_VA((_L8("ObjectEnumerationCompleteL - Exit, data provider %d "), iId));
+ }
+
+void CMTPDataProvider::StorageEnumerationCompleteL()
+ {
+ __FLOG_VA((_L8("StorageEnumerationCompleteL - Entry, data provider %d "), iId));
+ iEnumerationState = ((iEnumerationState & ~EStoragesEnumerationState) | EStoragesEnumerated);
+ iSingletons.DpController().EnumerationStateChangedL(*this);
+ __FLOG_VA((_L8("StorageEnumerationCompleteL - Exit, data provider %d "), iId));
+ }
+
+const MMTPDataProviderConfig& CMTPDataProvider::DataProviderConfig() const
+ {
+ return *iConfig;
+ }
+
+const MMTPFrameworkConfig& CMTPDataProvider::FrameworkConfig() const
+ {
+ return iSingletons.FrameworkConfig();
+ }
+
+MMTPObjectMgr& CMTPDataProvider::ObjectMgr() const
+ {
+ return iSingletons.ObjectMgr();
+ }
+
+MMTPReferenceMgr& CMTPDataProvider::ReferenceMgr() const
+ {
+ return iSingletons.ReferenceMgr();
+ }
+
+MMTPStorageMgr& CMTPDataProvider::StorageMgr() const
+ {
+ return iSingletons.StorageMgr();
+ }
+
+RFs& CMTPDataProvider::Fs() const
+ {
+ return iSingletons.Fs();
+ }
+
+MMTPDataCodeGenerator& CMTPDataProvider::DataCodeGenerator() const
+ {
+ return iSingletons.DataCodeGenerator();
+ }
+
+void CMTPDataProvider::DoCancel()
+ {
+ __FLOG_VA((_L8("DoCancel - Entry, data provider %d "), iId));
+ __FLOG_VA((_L8("DoCancel - Exit, data provider %d "), iId));
+
+ if (iTimerActive)
+ {
+ iTimer.Cancel();
+ iTimerActive = EFalse;
+ }
+ else
+ {
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, KErrCancel);
+ }
+ }
+
+void CMTPDataProvider::RunL()
+ {
+ __FLOG_VA((_L8("RunL - Entry, data provider %d "), iId));
+ __MTP_HEAP_FLOG
+ __ASSERT_DEBUG(iCurrentConnection, User::Invariant());
+
+
+ iTimerActive = EFalse;
+
+ if (iProxy)
+ {
+ iCurrentTransactionPhase = iProxyTransactionPhase;
+ }
+ else
+ {
+ iCurrentTransactionPhase = iCurrentConnection->TransactionPhaseL(iCurrentRequest->Uint32(TMTPTypeRequest::ERequestSessionID));
+ }
+ __FLOG_VA((_L8("Current transaction phase = 0x%08X"), iCurrentTransactionPhase));
+
+ TInt status(iStatus.Int());
+ if ((status != KErrNone) &&
+ (status != KErrAbort) &&
+ (status != KErrCancel))
+ {
+ // Framework or transport error has occured, force error recovery.
+ iErrorRecovery = iStatus.Int();
+ }
+ else if (status == KErrCancel)
+ {
+ iImplementation->Cancel();
+ }
+
+
+ if (iErrorRecovery != KErrNone)
+ {
+ __FLOG(_L8("Error recovery in progress"));
+ switch (iCurrentTransactionPhase)
+ {
+ case ERequestPhase:
+ case EDataIToRPhase:
+ case EDataRToIPhase:
+ case EResponsePhase:
+ SendErrorResponseL(iErrorRecovery);
+ break;
+
+ case ECompletingPhase:
+ TRAPD(err, iImplementation->ProcessRequestPhaseL(iCurrentTransactionPhase, *iCurrentRequest, *iCurrentConnection));
+ __FLOG_VA((_L8("iImplementation->ProcessRequestPhaseL error %d"), err));
+ if (err != KErrNone)
+ {
+ TransactionCompleteL(*iCurrentRequest, *iCurrentConnection);
+ }
+ iErrorRecovery = KErrNone;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ else if (iSingletons.DpController().EnumerateState() != CMTPDataProviderController::EEnumerated)
+ {
+ __FLOG(_L8("DP Enumeration is not complete"));
+
+ TUint16 opCode = iCurrentRequest->Uint16(TMTPTypeRequest::ERequestOperationCode);
+
+ switch(opCode)
+ {
+ case EMTPOpCodeOpenSession:
+ case EMTPOpCodeCloseSession:
+ case EMTPOpCodeGetDeviceInfo:
+ case EMTPOpCodeGetDevicePropDesc:
+ case EMTPOpCodeGetObjectPropsSupported:
+ case EMTPOpCodeGetObjectPropDesc:
+ case EMTPOpCodeVendorExtextensionEnd:
+ iImplementation->ProcessRequestPhaseL(iCurrentTransactionPhase, *iCurrentRequest, *iCurrentConnection);
+ break;
+
+ case EMTPOpCodeGetStorageIDs:
+ case EMTPOpCodeGetStorageInfo:
+ if(iSingletons.DpController().EnumerateState() > CMTPDataProviderController::EEnumeratingDataProviderStorages)
+ {
+ iImplementation->ProcessRequestPhaseL(iCurrentTransactionPhase, *iCurrentRequest, *iCurrentConnection);
+ }
+ else
+ {
+ //If storages are not enumerated wait for 3 secs and check it again.
+ iTimer.After(iStatus, TTimeIntervalMicroSeconds32(KWaitForEnumeration));
+ SetActive();
+ iTimerActive = ETrue;
+ }
+ break;
+
+ default:
+
+ switch (iCurrentTransactionPhase)
+ {
+ case ERequestPhase:
+ // Wait till the objects are enumerated.
+ // checks for every 3 secs till the objects are eumrated.
+ // Won't send any device busy response.
+ // Windows wont repond if it gets device busy response after it has send Openseesion.
+ iTimer.After(iStatus, TTimeIntervalMicroSeconds32(KWaitForEnumeration));
+ SetActive();
+ iTimerActive = ETrue;
+ break;
+ case ECompletingPhase:
+ TransactionCompleteL(*iCurrentRequest, *iCurrentConnection);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else
+ {
+ // Pass to the bound plugin for processing.
+ iImplementation->ProcessRequestPhaseL(iCurrentTransactionPhase, *iCurrentRequest, *iCurrentConnection);
+
+ //Make ActiveRequest processor and CancelRequest processing to occur synchronously
+ if( iCurrentTransactionPhase == ERequestPhase )
+ {
+ CMTPSession& session(static_cast<CMTPSession&>(iCurrentConnection->SessionWithMTPIdL(iCurrentRequest->Uint32(TMTPTypeRequest::ERequestSessionID))));
+ MMTPConnectionProtocol& connection(static_cast<MMTPConnectionProtocol&>(*iCurrentConnection));
+
+ // Pass transaction to session to check against any pending events
+ if ( session.CheckPendingEvent(*iCurrentRequest) )
+ {
+ //Current request matches a pending event, pass event to connection layer event processing
+ connection.ReceivedEventL(session.PendingEvent());
+ }
+ }
+
+ }
+
+ __MTP_HEAP_FLOG
+ __FLOG_VA((_L8("RunL - Exit, data provider %d "), iId));
+ }
+
+TInt CMTPDataProvider::RunError(TInt aError)
+ {
+ __FLOG_VA((_L8("RunError - Entry, data provider %d "), iId));
+ __FLOG_VA((_L8("Error = %d"), aError));
+
+ /*
+ CMTPDataProvider or iImplementation error, save the error state and
+ re-schedule.
+ */
+ iErrorRecovery = aError;
+ Schedule();
+
+ __FLOG_VA((_L8("RunError - Exit, data provider %d "), iId));
+ return KErrNone;
+ }
+
+/**
+Constructor.
+@param aId The data provider identifier.
+@param aUid The data provider implementation UID.
+@param aConfig The data provider configurability parameter data. Ownership IS
+transfered.
+*/
+CMTPDataProvider::CMTPDataProvider(TUint aId, TUid aUid, CMTPDataProviderConfig* aConfig) :
+ CActive(EPriorityStandard),
+ iConfig(aConfig),
+ iId(aId),
+ iImplementationUid(aUid),
+ iProxyTransactionPhase(ERequestPhase)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+/**
+Second phase constructor.
+@leave One of the system wide error codes if a processing failure occurs.
+*/
+void CMTPDataProvider::ConstructL()
+ {
+ __FLOG_OPEN(KMTPSubsystem, KComponent);
+ __FLOG_VA((_L8("ConstructL - Entry, data provider %d "), iId));
+
+ iSingletons.OpenL();
+ TUint tDPType = iConfig->UintValue(MMTPDataProviderConfig::EDataProviderType);
+ const TUint KExcludeCategoryStart = EVendorExtensionSets;
+ const TUint KExcludeCategoryEnd = EFormatExtensionSets;
+ if( tDPType == KMTPDummyDataProvider)
+ {
+ iImplementation = static_cast<CMTPDataProviderPlugin*>(CDummyDp::NewL(static_cast<MMTPDataProviderFramework*>(this)));
+ //create your dummy classCMTPDataProviderPlugin
+ for (TUint i(EAssociationTypes); (i < ENumCategories); i++)
+ {
+ CSupportedCodes* codes = CSupportedCodes::NewLC(static_cast<TMTPSupportCategory>(i), Plugin());
+
+ if((i >= KExcludeCategoryStart) && (i <= KExcludeCategoryEnd) && (codes->Codes().Count() >0))
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ iSupported.AppendL(codes);
+ CleanupStack::Pop(codes);
+ }
+ iConstructed = ETrue;
+ }
+ else
+ {
+ iImplementation = CMTPDataProviderPlugin::NewL(iImplementationUid, static_cast<MMTPDataProviderFramework*>(this));
+
+ for (TUint i(EAssociationTypes); (i < ENumCategories); i++)
+ {
+ CSupportedCodes* codes = CSupportedCodes::NewLC(static_cast<TMTPSupportCategory>(i), Plugin());
+
+ if((i >= KExcludeCategoryStart) && (i <= KExcludeCategoryEnd) && (codes->Codes().Count() >0))
+ {
+ User::Leave(KErrNotSupported);
+ }
+ iSupported.AppendL(codes);
+ CleanupStack::Pop(codes);
+ }
+
+ User::LeaveIfError(iTimer.CreateLocal());
+
+ // Only assume ownership of passed objects on successful construction.
+ iConstructed = ETrue;
+
+ __FLOG_VA((_L8("Data provider %d iImplementationUid 0x08%X "), iId, iImplementationUid));
+ __FLOG_VA((_L8("ConstructL - Exit, data provider %d "), iId));
+ }
+
+ }
+
+/**
+Schedules the next request phase or event.
+*/
+void CMTPDataProvider::Schedule()
+ {
+ __FLOG_VA((_L8("Schedule - Entry, data provider %d "), iId));
+ iStatus = KRequestPending;
+ TRequestStatus* status = &iStatus;
+ SetActive();
+ User::RequestComplete(status, KErrNone);
+ __FLOG_VA((_L8("Schedule - Exit, data provider %d "), iId));
+ }
+
+/**
+Formats and sends an MTP response dataset from the specified error code.
+@param aError The error code.
+@leave One of the system wide error codes, if a processing error occurs.
+*/
+void CMTPDataProvider::SendErrorResponseL(TInt aError)
+ {
+ __FLOG_VA((_L8("SendResponseL - Entry, data provider %d "), iId));
+ __ASSERT_DEBUG(iCurrentRequest != NULL, User::Invariant());
+
+ TMTPResponseCode code;
+ switch (aError)
+ {
+ case KErrOverflow:
+ case KMTPDataTypeInvalid:
+ code = EMTPRespCodeInvalidDataset;
+ break;
+
+ default:
+ code = EMTPRespCodeGeneralError;
+ break;
+ }
+
+ __FLOG_VA((_L8("Sending response code 0x%04X"), code));
+ iResponse.SetUint16(TMTPTypeResponse::EResponseCode, code);
+ iResponse.SetUint32(TMTPTypeResponse::EResponseSessionID, iCurrentRequest->Uint32(TMTPTypeResponse::EResponseSessionID));
+ iResponse.SetUint32(TMTPTypeResponse::EResponseTransactionID, iCurrentRequest->Uint32(TMTPTypeResponse::EResponseTransactionID));
+ SendResponseL(iResponse, *iCurrentRequest, *iCurrentConnection);
+
+ __FLOG_VA((_L8("SendResponseL - Exit, data provider %d "), iId));
+ }
+
+CMTPDataProvider::CSupportedCodes* CMTPDataProvider::CSupportedCodes::NewLC(TMTPSupportCategory aCategory, MMTPDataProvider& aDp)
+ {
+ CSupportedCodes* self = new(ELeave) CSupportedCodes();
+ CleanupStack::PushL(self);
+ self->ConstructL(aCategory, aDp);
+ return self;
+ }
+
+CMTPDataProvider::CSupportedCodes::~CSupportedCodes()
+ {
+ iCodes.Close();
+ }
+
+const RArray<TUint>& CMTPDataProvider::CSupportedCodes::Codes() const
+ {
+ return iCodes;
+ }
+
+TBool CMTPDataProvider::CSupportedCodes::Supported(TUint aCode) const
+ {
+ return (iCodes.FindInOrder(aCode) != KErrNotFound);
+ }
+
+CMTPDataProvider::CSupportedCodes::CSupportedCodes() :
+ iCodes()
+ {
+
+ }
+
+void CMTPDataProvider::CSupportedCodes::ConstructL(TMTPSupportCategory aCategory, MMTPDataProvider& aDp)
+ {
+ aDp.Supported(aCategory, iCodes);
+ iCodes.Sort();
+ }
+
+