diff -r 000000000000 -r d0791faffa3f mtptransports/mtpptpiptransport/ptpipcontroller/src/cptpipcontroller.cpp --- /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 +#include "ptpipsocketpublish.h" +#include +#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; +} + + +