--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mtptransports/mtpptpiptransport/ptpipcontroller/src/cptpipcontroller.cpp Tue Feb 02 01:11:40 2010 +0200
@@ -0,0 +1,635 @@
+// Copyright (c) 2007-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 "cptpipcontroller.h" // Cptpipcontroller
+
+#include <mtp/tmtptypeuint128.h>
+#include "ptpipsocketpublish.h"
+#include <in_sock.h>
+#include "ptpipprotocolconstants.h"
+
+
+
+_LIT_SECURITY_POLICY_PASS(KAllowReadAll);
+_LIT_SECURITY_POLICY_C1(KProcPolicy,ECapability_None);
+__FLOG_STMT(_LIT8(KComponent,"PTPIPController");)
+
+
+#define PTPIP_INIT_COMMAND_REQUEST 1
+#define PTPIP_INIT_COMMAND_ACK 2
+#define PTPIP_INIT_EVENT_REQUEST 3
+#define PTPIP_INIT_FAIL 5
+#define PTPIP_FIXED_CONNECTION_ID 1
+#define PTPIP_PRPTOCOL_VERSION 0x00000001
+
+
+enum TPTPIPControllerPanicReasons
+ {
+ EPanicTransportNotStarted = 0,
+ };
+
+
+EXPORT_C CPTPIPController* CPTPIPController::NewLC()
+ {
+ CPTPIPController* self = new (ELeave) CPTPIPController;
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+/*
+ Factory Method
+*/
+EXPORT_C CPTPIPController* CPTPIPController::NewL()
+ {
+ CPTPIPController* self = CPTPIPController::NewLC();
+ CleanupStack::Pop(1);
+ return self;
+ }
+
+
+CPTPIPController::CPTPIPController():
+ CActive(EPriorityStandard),iDeviceGUID()
+ {
+ iCtrlState=EIdle;
+ iTransportId=TUid::Uid(KMTPPTPIPTransportImplementationUid);
+ iCounter=0;
+ CActiveScheduler::Add(this);
+ }
+
+/*
+Creates two PTPIP SocketHandlers and handles the sockets to
+PTPIP SocketHandler & loads the Filter plugin.
+*/
+void CPTPIPController::ConstructL()
+ {
+ __FLOG_OPEN(KMTPSubsystem, KComponent);
+ iCmdHandler = CPTPIPSocketHandler::NewL();
+ iEvtHandler = CPTPIPSocketHandler::NewL();
+ iFilter=CPTPIPHostFilterInterface::NewL();
+ iInitCmdAck = CPTPIPInitCmdAck::NewL();
+ iTimer=CPTPIPTimer::NewL(*this);
+
+ TParameter param=EDeviceFriendlyName;
+
+ iIsConnectedToMTP = EFalse;
+ iDeviceGUID.Set(0,0);
+ const TUint32 KUidMTPRepositoryValue(0x10282FCC);
+ const TUid KUidMTPRepository = {KUidMTPRepositoryValue};
+ iRepository = CRepository::NewL(KUidMTPRepository);
+ iDeviceFriendlyName = HBufC16::NewL(100);
+ TPtr16 name = iDeviceFriendlyName->Des();
+ TInt result=iRepository->Get(param,name);
+ }
+
+/*
+Destructor
+*/
+EXPORT_C CPTPIPController::~CPTPIPController()
+ {
+ delete iCmdHandler;
+ delete iEvtHandler;
+ delete iFilter;
+ delete iTimer;
+ delete iDeviceFriendlyName;
+ delete iRepository;
+ delete iInitCmdReq;
+ delete iInitCmdAck;
+ iMTP.Close();
+ iIsConnectedToMTP = EFalse;
+ iProperty.Close();
+ iConnectionState.Close();
+ __FLOG_CLOSE;
+ }
+
+
+
+EXPORT_C RSocket& CPTPIPController::NewSocketL()
+ {
+ iCounter++;
+ if(iCounter==1)
+ return iCmdHandler->Socket();
+ else if(iCounter==2)
+ return iEvtHandler->Socket();
+ else
+ return iDummySocket;
+ //Issue :If Newsocket is called 4 time then we are going to give
+ //the same socket that we have given him third time.
+
+ }
+TInt CPTPIPController::CheckMTPConnection()
+{
+ TInt error = KErrNone;
+ if(iIsConnectedToMTP == EFalse)
+ {
+ error = iMTP.Connect();
+ }
+ if(error ==KErrNone)
+ {
+ iIsConnectedToMTP = ETrue;
+ error = iMTP.IsAvailable(iTransportId);
+ }
+ return error;
+}
+/*
+Validates the socket connection based on the current value of iCtrlState
+@return ETrue on succes EFalse on failure*/
+TBool CPTPIPController::Validate()
+ {
+ if(iCtrlState==EIdle || iCtrlState==EInitEvtAwaited)
+ return ETrue;
+ else
+ return EFalse;
+ }
+
+
+/*Saves the CommandSocket and EventSocket;The respective SocketHandlers are given the sockets
+and Calls itself on a CompleteSelf()
+ @param aSocket Pointer to socket
+ @param TRequestStatus of the caller i.e., CPTPIPAgent
+*/
+EXPORT_C void CPTPIPController::SocketAccepted(TRequestStatus& aStatus)
+ {
+ iCallerStatus=&aStatus;
+ aStatus=KRequestPending;
+ TBool result=Validate();
+ if(result==EFalse)
+ {
+ User::RequestComplete(iCallerStatus,KErrServerBusy);
+ return;
+ }
+
+ if(iCtrlState==EInitEvtAwaited)
+ { // we are not gracefully rejecting a new PTPIP connection from other host
+ // as of now just socket closed.
+ if(CompareHost(iEvtHandler->Socket())==EFalse)
+ {
+ User::RequestComplete(iCallerStatus,KErrServerBusy);
+ return;
+ }
+ }
+ if(iCtrlState==EPTPIPConnected)
+ {
+ /*if(CompareHost(iDummySocket->Socket())==EFalse)
+ * User::RequestComplete(status,KErrServerBusy);
+ * Note : As of now this check is not required because
+ * call to Validate(0) will fail.
+ */
+ }
+
+ /*
+ Check whether PTPIPController is in a state of accepting new socket connections
+ */
+ if (iCtrlState == EIdle)
+ {
+ iCtrlState = EInitCommandAwaited;
+ }
+ else if (iCtrlState == EInitEvtAwaited)
+ {
+ iCtrlState = EInitEvtAwaited;
+ }
+
+ Schedule();
+ }
+
+
+/*
+Compares whether the second connection request is from the same remote host
+@param returns ETrue if the second request comes from the same host
+*/
+TBool CPTPIPController::CompareHost(RSocket& aSocket)
+ {
+
+ TInetAddr thisaddr, newAddr;
+
+ iCmdHandler->Socket().RemoteName(thisaddr);
+ aSocket.RemoteName(newAddr);
+ if(newAddr.Address() == thisaddr.Address())
+ {
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+
+ }
+
+/**
+Schedules the next request phase or event.
+*/
+void CPTPIPController::Schedule()
+ {
+ iStatus = KRequestPending;
+ TRequestStatus* status(&iStatus);
+ SetActive();
+ User::RequestComplete(status, KErrNone);
+ }
+
+/*
+ Defines the two socket names to be published
+ @return one of the system wide error codes on failure
+*/
+TInt CPTPIPController::PublishSocketNamePair()
+ {
+ TName iCommandSocketSysName,iEventSocketSysName;
+ iCmdHandler->Socket().Name(iCommandSocketSysName);
+ iEvtHandler->Socket().Name(iEventSocketSysName);
+
+
+
+ /******************Define command socket system name************************/
+ RProcess serverprocess;
+
+ const TUid KPropertyUid= serverprocess.Identity();
+
+ TInt error=iProperty.Define(KPropertyUid,ECommandSocketName,RProperty::EText,KAllowReadAll,KAllowReadAll);
+
+ error=iProperty.Attach(KPropertyUid,ECommandSocketName);
+
+ error=RProperty::Set(KPropertyUid,ECommandSocketName,iCommandSocketSysName);
+
+ /*****************Define event socket system name***********************/
+
+ error=iProperty.Define(KPropertyUid,EEventSocketName,RProperty::EText,KAllowReadAll,KAllowReadAll);
+
+ error=iProperty.Attach(KPropertyUid,EEventSocketName);
+
+ error=RProperty::Set(KPropertyUid,EEventSocketName,iEventSocketSysName);
+
+ return error;
+ }
+
+
+/*Makes the sockets Transfer enabled
+ @return one of the system wide error codes on failure
+ */
+TInt CPTPIPController::EnableSocketTransfer()
+ {
+ TInt err;
+ err = iCmdHandler->Socket().SetOpt(KSOEnableTransfer, KSOLSocket,KProcPolicy().Package());
+
+ if(err != KErrNone) return err;
+
+ err = iEvtHandler->Socket().SetOpt(KSOEnableTransfer, KSOLSocket,KProcPolicy().Package());
+
+ return err;
+ }
+
+/*
+Sets the obtained DeviceGUID as the current DeviceGUID
+@param TDesC8& aDeviceGUID
+@return TInt KErrArgument if DeviceGUID is invalid or KErrNone
+*/
+EXPORT_C TInt CPTPIPController::SetDeviceGUID(TDesC8& aDeviceGUID)
+ {
+ TInt size = aDeviceGUID.Size();
+ if (size != 16) return KErrArgument;
+ TMTPTypeUint128 guid(aDeviceGUID);
+ iDeviceGUID = guid;
+ return KErrNone;
+ }
+
+/*
+Sets the obtained DeviceFriendlyName
+@param TDesC16* aDeviceGUID
+*/
+EXPORT_C void CPTPIPController::SetDeviceFriendlyName(TDesC16* aDeviceFreindlyName)
+ {
+ delete iDeviceFriendlyName;
+
+ TRAPD(err, iDeviceFriendlyName=aDeviceFreindlyName->AllocL());
+
+ if(err != KErrNone)
+ {
+ __FLOG_VA((_L8("CPTPIPController::SetDeviceFriendlyName ERROR = %d\n"), err));
+ }
+
+ }
+
+
+void CPTPIPController::Reset()
+ {
+ iCmdHandler->Socket().Close();
+ iEvtHandler->Socket().Close();
+ if(iIsConnectedToMTP)
+ {
+ TInt stopStatus=iMTP.StopTransport(iTransportId);
+ if (KErrNone != stopStatus)
+ {
+ __FLOG_VA((_L8("CPTPIPController::Reset ERROR = %d\n"), stopStatus));
+ }
+
+ }
+
+ iMTP.Close();
+ iProperty.Close();
+ iConnectionState.Close();
+ iCounter=0;
+ iIsConnectedToMTP = EFalse;
+ iCtrlState = EIdle;
+ iCmdHandler->State()=EReadState;
+ iEvtHandler->State()=EReadState;
+ }
+
+EXPORT_C void CPTPIPController::StopTransport()
+ {
+ Reset();
+ }
+
+
+
+void CPTPIPController:: CheckAndHandleErrorL(TInt aError)
+ {
+ if(aError != KErrNone)
+ {
+ Reset();
+ __FLOG_VA((_L8("PTPIP Controller CheckAndHandleErrorL, Error = %d"), aError));
+ User::Leave(aError);
+ }
+ }
+
+void CPTPIPController:: CheckInitFailL(TInt aError)
+ {
+
+ TInitFailReason reason = EInitFailUnSpecified;
+
+ // we send Init fail packet to Initiator on command channel
+ // even after InitEvent is received.
+ if(aError!=KErrNone && (iCtrlState==EInitCommandRead|| iCtrlState==EInitEventRead))
+ {
+ if(aError == KErrAccessDenied)
+ {
+ reason = EInitFailRejected;
+ }
+ BuildInitFailL(reason);
+ iCtrlState= EWaitForInitFail;
+ if(iCmdHandler->State()==EWriteState)
+ iCmdHandler->WriteToSocket(iInitFailed,iStatus);
+ else
+ iEvtHandler->WriteToSocket(iInitFailed,iStatus);
+ StartTimer(30);
+ __FLOG_VA((_L8("PTPIP Controller Error, Error = %d"), aError));
+ User::Leave(aError);
+ }
+ }
+
+/*
+Cause a Time-Out event to occur
+*/
+EXPORT_C void CPTPIPController::OnTimeOut()
+ {
+ TRequestStatus* status(&iStatus);
+ User::RequestComplete(status,KErrTimedOut);
+ }
+
+void CPTPIPController::StartTimer(TInt aSecond)
+ {
+ iTimer->IssueRequest(aSecond);
+ iStatus = KRequestPending;
+ SetActive();
+ }
+
+void CPTPIPController::RunL()
+ {
+
+ TInt StatusError=iStatus.Int();
+
+ if(iCmdHandler->IsActive() || iEvtHandler->IsActive())
+ {
+ if(iCmdHandler->IsActive())
+ iCmdHandler->Cancel();
+ if(iEvtHandler->IsActive())
+ iEvtHandler->Cancel();
+
+ }
+ else if(iTimer->IsActive())
+ {
+ iTimer->Cancel();
+ }
+
+ TPtrC8 hostGUID;
+ TInt error;
+ switch(iCtrlState)
+ {
+ case EIdle:
+ break;
+
+ case EInitCommandAwaited :
+
+ iInitCmdReq = CPTPIPInitCmdRequest::NewL();
+
+ iCmdHandler->ReadFromSocket(*iInitCmdReq,iStatus);
+ iCtrlState=EInitCommandRead;
+
+ StartTimer(30);
+ break;
+
+ case EInitCommandRead:
+ CheckAndHandleErrorL(StatusError);
+
+
+ error = ParseInitPacketL();
+ CheckInitFailL(error);
+
+ // Need special error number for MTP not available
+ // so that licensee can understand it.
+ if(iMTP.IsProcessRunning() != KErrNotFound )
+ {
+ error = CheckMTPConnection();
+ CheckInitFailL(error);
+ }
+
+ //coverity[unchecked_value]
+ iHostGUID.FirstReadChunk(hostGUID);
+
+ iFilter->Accept(*iHostFriendlyName,hostGUID,iStatus);
+ iCtrlState=EFilterConsentAwaited;
+ StartTimer(30);
+ break;
+
+ case EFilterConsentAwaited:
+
+ // Please wriet in function in m class that filter must send KErrAccessDenied
+ CheckInitFailL(StatusError );
+ //give error code for rejection.
+ BuildInitAckL();
+ iCtrlState = EWaitForInitCommandAck;
+ iCmdHandler->WriteToSocket(*iInitCmdAck,iStatus);
+ StartTimer(30);
+ break;
+
+ case EWaitForInitFail :
+ // Do not call any other leaving function here
+ // because RunError is going to ignore it.
+
+ // Error code is wrong if this happens due to local error.
+ CheckAndHandleErrorL(KErrAccessDenied);
+ break;
+
+ case EWaitForInitCommandAck :
+ CheckAndHandleErrorL(StatusError);
+ iCtrlState = EInitEvtAwaited;
+ User::RequestComplete(iCallerStatus,KErrNone);
+ break;
+
+
+ case EInitEvtAwaited:
+
+ iEvtHandler->ReadFromSocket(iInitEvtReq,iStatus);
+ iCtrlState=EInitEventRead;
+ StartTimer(30);
+ break;
+
+ case EInitEventRead:
+
+ CheckInitFailL(StatusError);
+ error = ParseEvtPacket();
+ CheckInitFailL(error);
+
+ error = EnableSocketTransfer();
+ CheckInitFailL(error);
+
+ error = PublishSocketNamePair();
+ CheckInitFailL(error);
+
+ error = CheckMTPConnection();
+ CheckInitFailL(error);
+ error = iMTP.StartTransport(iTransportId);
+ CheckAndHandleErrorL(error);
+
+ /************Subscribe to the state of plugin********/
+ TInt connState;
+ error = iConnectionState.Attach(KMTPPublishConnStateCat,EMTPConnStateKey);
+ CheckAndHandleErrorL(error);
+ error = iConnectionState.Get(KMTPPublishConnStateCat,EMTPConnStateKey,connState);
+ CheckAndHandleErrorL(error);
+ iConnectionState.Subscribe(iStatus);
+ iCtrlState = EPTPIPConnected;
+ SetActive();
+ break;
+
+
+ case EPTPIPConnected:
+ {
+ error=iConnectionState.Get(connState);
+ if((error!=KErrNone) || (connState==EDisconnectedFromHost))
+ {
+ Reset();
+ User::RequestComplete(iCallerStatus,KErrNone);
+ }
+ else
+ {
+ iConnectionState.Subscribe(iStatus);
+ SetActive();
+ }
+ break;
+ }
+ default :
+ {
+ break;
+ }
+
+ }
+
+ }
+
+/*
+Over-ridden to return KErrNone by checking the state of PTPIP Controller
+*/
+TInt CPTPIPController::RunError(TInt aErr)
+ {
+ if(iCtrlState != EWaitForInitFail)
+ {
+ User::RequestComplete(iCallerStatus,aErr);
+ iCtrlState = EIdle;
+ iCmdHandler->State()=EReadState;
+ iEvtHandler->State()=EReadState;
+ iCounter=0;
+ iMTP.Close();
+ iIsConnectedToMTP = EFalse;
+ }
+ //Return KErrNone back to RunL()
+ return KErrNone;
+ }
+
+
+
+
+void CPTPIPController::DoCancel()
+ {
+
+ }
+
+TInt CPTPIPController::ParseInitPacketL()
+{
+ TUint32 length(iInitCmdReq->Uint32L(CPTPIPInitCmdRequest::ELength));
+ TUint32 type(iInitCmdReq->Uint32L(CPTPIPInitCmdRequest::EPktType));
+ if(type != PTPIP_INIT_COMMAND_REQUEST)
+ {
+ return KErrBadHandle;
+ }
+
+ iInitCmdReq->GetL(CPTPIPInitCmdRequest::EInitiatorGUID,iHostGUID);
+
+
+ TDesC& name = iInitCmdReq->HostFriendlyName();
+ iHostFriendlyName = &name;
+ TUint32 version(iInitCmdReq->Uint32L(CPTPIPInitCmdRequest::EVersion));
+ return KErrNone;
+}
+
+TInt CPTPIPController::ParseEvtPacket()
+{
+ TUint32 length(iInitEvtReq.Uint32(TPTPIPInitEvtRequest::ELength));
+ TUint32 type(iInitEvtReq.Uint32(TPTPIPInitEvtRequest::EType));
+ if(type != PTPIP_INIT_EVENT_REQUEST) return KErrBadHandle;
+ TUint32 conNumber(iInitEvtReq.Uint32(TPTPIPInitEvtRequest::EconNumber));
+ if(conNumber !=PTPIP_FIXED_CONNECTION_ID)
+ {
+ // We are supporting only one connection,So connection Id is fixed.
+ return KErrBadHandle;
+ }
+
+ return KErrNone;
+}
+void CPTPIPController::BuildInitAckL()
+{
+ iInitCmdAck->SetUint32L(CPTPIPInitCmdAck::EPktType,PTPIP_INIT_COMMAND_ACK);
+ // We are supporting only one connection,So connection Id is fixed
+ iInitCmdAck->SetUint32L(CPTPIPInitCmdAck::EConNumber,PTPIP_FIXED_CONNECTION_ID);
+
+ iInitCmdAck->SetL(CPTPIPInitCmdAck::EResponderGUID,iDeviceGUID);
+
+ iInitCmdAck->SetDeviceFriendlyName(*iDeviceFriendlyName);
+ iInitCmdAck->SetUint32L(CPTPIPInitCmdAck::EVersion,PTPIP_PRPTOCOL_VERSION);
+ TUint64 size = iInitCmdAck->Size();
+ iInitCmdAck->SetUint32L(CPTPIPInitCmdAck::ELength,(TUint32)size);
+}
+
+void CPTPIPController::BuildInitFailL(TInitFailReason aReason)
+{
+ iInitFailed.SetUint32(TPTPIPInitFailed::ELength,iInitFailed.Size());
+ iInitFailed.SetUint32(TPTPIPInitFailed::EType,PTPIP_INIT_FAIL);
+ iInitFailed.SetUint32(TPTPIPInitFailed::EReason,aReason);
+}
+
+TBool E32Dll()
+{
+ return ETrue;
+}
+
+
+