diff -r 000000000000 -r d0791faffa3f mtptransports/mtpptpiptransport/ptpipplugin/src/cptpipconnection.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mtptransports/mtpptpiptransport/ptpipplugin/src/cptpipconnection.cpp Tue Feb 02 01:11:40 2010 +0200 @@ -0,0 +1,1597 @@ +// Copyright (c) 2008-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: +// + +/** + @internalComponent +*/ + +// System includes +#include "e32base.h" +#include "ptpippanic.h" +#include "e32property.h" + +// MTP includes +#include +#include + +// Plugin includes +#include "cptpipcommandhandler.h" +#include "cptpipeventhandler.h" +#include "cptpipconnection.h" +#include "ptpipsocketpublish.h" + +// File type constants. +const TInt KMTPNullChunkSize(0x00020000); // 100KB +const TUint32 KPTPIPDataHeaderSize = 12; // Size of len, type and tran id. +__FLOG_STMT(_LIT8(KComponent,"PTPIPConnection");) +#define UNUSED_VAR(a) (a) = (a) + +/** + PTPIP device class connection factory method. + @param aConnectionMgr The MTP connection manager interface. + @return A pointer to an PTPIP device class connection. Ownership IS transfered. + @leave One of the system wide error codes, if a processing failure occurs. + */ +CPTPIPConnection* CPTPIPConnection::NewL(MMTPConnectionMgr& aConnectionMgr ) + { + CPTPIPConnection* self = new(ELeave) CPTPIPConnection(aConnectionMgr); + CleanupStack::PushL (self ); + self->ConstructL ( ); + CleanupStack::Pop (self ); + return self; + } + +/** + Destructor + */ +CPTPIPConnection::~CPTPIPConnection( ) + { + __FLOG(_L8("Destructor - Entry")); + StopConnection ( ); + + // Delete all the handlers which will close the sockets. + delete iCommandHandler; + delete iEventHandler; + + delete iPTPIPCommandContainer; + delete iPTPIPDataContainer; + delete iPTPIPEventContainer; + + iNullBuffer.Close(); + + __FLOG(_L8("Destructor - Exit")); + __FLOG_CLOSE; + } + +/** + Second phase constructor + @leave One of the system wide error codes, if a processing failure occurs. + */ +void CPTPIPConnection::ConstructL( ) + { + __FLOG_OPEN(KMTPSubsystem, KComponent); + __FLOG(_L8("ConstructL - Entry")); + + // Construct the Command and event handlers + iCommandHandler = CPTPIPCommandHandler::NewL (*this ); + iEventHandler = CPTPIPEventHandler::NewL (*this ); + + iPTPIPCommandContainer = CPTPIPGenericContainer::NewL ( ); + iPTPIPDataContainer = CPTPIPDataContainer::NewL ( ); + iPTPIPEventContainer = CPTPIPGenericContainer::NewL ( ); + + // Transfer the sockets + TransferSocketsL(); + + SetConnectionState (EInitialising ); + CompleteSelf (KErrNone ); + + __FLOG(_L8("ConstructL - Exit")); + } + +/** + Constructor + */ +CPTPIPConnection::CPTPIPConnection(MMTPConnectionMgr& aConnectionMgr ) : + CActive(EPriorityStandard), + iConnectionMgr(&aConnectionMgr) + { + CActiveScheduler::Add (this ); + } + +// +// MMTPTransportConnection functions +// + +/** + Binds the protocol layer. + @param aProtocol - The connectionProtocol provides the SPI or the observer + for the communication to happen from the transport to the framework. + */ +void CPTPIPConnection::BindL(MMTPConnectionProtocol& aProtocol ) + { + __FLOG(_L8("BindL - Entry")); + iProtocolLayer = &aProtocol; + __FLOG(_L8("BindL - Exit")); + } + +/** + Returns the protocol layer. + @return The SPI or the observer protocol layer + */ +MMTPConnectionProtocol& CPTPIPConnection::BoundProtocolLayer( ) + { + __FLOG(_L8("BoundProtocolLayer - Entry")); + __ASSERT_ALWAYS(iProtocolLayer, Panic(EPTPIPBadState)); + __FLOG(_L8("BoundProtocolLayer - Exit")); + return *iProtocolLayer; + } + +/** + Close the connection, stop all data transfer activity and and wait for the host + to issue a Device Reset Request. + */ +void CPTPIPConnection::CloseConnection( ) + { + __FLOG(_L8("CloseConnection - Entry")); + StopConnection ( ); + __FLOG(_L8("CloseConnection - Exit")); + } + +/** + A transaction is one set of request, data transfer and response phases. + The fw calls this to mark the end of an MTP transaction. + */ +void CPTPIPConnection::TransactionCompleteL(const TMTPTypeRequest& /*aRequest*/) + { + __FLOG(_L8("TransactionCompleteL - Entry")); + __FLOG(_L8("******** Transaction Complete **************")); + SetTransactionPhase (EIdlePhase ); + + // Clear the cancel flag. + iCancelOnCommandState = ECancelNotReceived; + iCancelOnEventState = ECancelNotReceived; + + // Again start listening for the command request. + InitiateCommandRequestPhaseL( ); + + __FLOG(_L8("TransactionCompleteL - Exit")); + } + +/** + Called by the fw to indicate that protocol layer is not using this transport anymore + and so we will not have any callback/SPI funtions to the fw any more + */ +void CPTPIPConnection::Unbind(MMTPConnectionProtocol& /*aProtocol*/) + { + __FLOG(_L8("Unbind - Entry")); + __ASSERT_DEBUG(iProtocolLayer, Panic(EPTPIPBadState)); + // Protocol will no longer be bound to the transport + iProtocolLayer = NULL; + __FLOG(_L8("Unbind - Exit")); + } + +/** + Not used + */ +TAny* CPTPIPConnection::GetExtendedInterface(TUid /*aInterfaceUid*/) + { + return NULL; + } + +/* + * return PTPIP transport implementation UID + */ +TUint CPTPIPConnection::GetImplementationUid() + { + return KMTPPTPIPTransportImplementationUid; + } + +// +// Active Object functions +// + +/** + Used to cancel the outstanding requests, and reset internal states as appropriate. + */ +void CPTPIPConnection::DoCancel( ) + { + __FLOG(_L8("DoCancel - Entry")); + + iCommandHandler->Cancel( ); + iEventHandler->Cancel( ); + + SetConnectionState(ECancelled ); + + __FLOG(_L8("DoCancel - Exit")); + } + +/** +The connection behaves as an active object during the PTPIP connection establishment phase. +Subsequently, it behaves as a normal object whose functions are invoked by the MTP framework +or by the SocketHandler on sending/ receiving data. + +Thus the runl is not hit after the initial connection establishment. + */ +void CPTPIPConnection::RunL( ) + { + __FLOG(_L8("RunL - Entry")); + __FLOG_VA((_L8("Current State is %d, and status is %d"), iState, iStatus.Int())); + + if(iStatus != KErrNone ) + { + CloseConnection( ); + } + else + { + + switch(iState ) + { + // ConstructL is complete, + // the PTPIP connection establishment will be complete after the init ack is sent. + case EInitialising: + SendInitAckL( ); + break; + + // Now the PTPIP connection has been established. + case EInitialisationComplete: + SetConnectionState(EStartListening ); + CompleteSelf(KErrNone ); + break; + + // Start listeing for requests on the 2 channels + case EStartListening: + InitiateEventRequestPhaseL( ); + InitiateCommandRequestPhaseL( ); + break; + + default: + __FLOG(_L8("PTPIP ERROR: Invalid connection state")); + Panic(EPTPIPBadState ); + break; + } + } + + __FLOG(_L8("RunL - Exit")); + } + +/** + Called when an error occurs in the RunL + */ +#ifdef __FLOG_ACTIVE +TInt CPTPIPConnection::RunError(TInt aError ) +#else +TInt CPTPIPConnection::RunError(TInt /*aError*/ ) +#endif + { + __FLOG(_L8("RunError - Entry")); + __FLOG_VA((_L8("PTPIP ERROR: Error received is %d"), aError)); + + // Cancel all the outstanding requests. + Cancel( ); + + // Stop the connection, if necessary. + StopConnection( ); + + __FLOG(_L8("RunError - Exit")); + return KErrNone; + } + +// +// Receive data functions +// + +/** + Called internally to recevive the commands over the command channel. + This will invoke the command handler + to listen on the socket and get the data into the buffers passed. + */ +void CPTPIPConnection::InitiateCommandRequestPhaseL( ) + { + __FLOG(_L8("InitiateCommandRequestPhaseL - Entry")); + __FLOG(_L8("******** Phase 1 - Request **************")); + // Set current state to request phase + SetTransactionPhase(ERequestPhase ); + + // The PTPIP data buffer is a member of connection. + // Since we are expecting a request now, set the payload to request type + iPTPIPRequestPayload.Reset( ); + iPTPIPCommandContainer->SetPayloadL(&iPTPIPRequestPayload ); + + // Call the CommandHandler to get the request in the container + iCommandHandler->ReceiveCommandRequestL(*iPTPIPCommandContainer ); + + __FLOG(_L8("InitiateCommandRequestPhaseL - Exit")); + } + +/** + Called to indicate completion of receive of data started by InitiateCommandRequestPhaseL. + There is no point in reporting the error up to the f/w since no transaction has started. + USB does nothing at this stage. In PTP , the connection is closed. + @param aError - The error if any, received from socket. + */ +void CPTPIPConnection::ReceiveCommandCompleteL(TInt aError ) + { + __FLOG(_L8("ReceiveCommandCompleteL - Entry")); + + if(KErrNone != aError ) + { + __FLOG_VA((_L8("PTPIP Error: Received error=%d in request phase, closing connection"), aError)); + CloseConnection( ); + } + else if(ValidateTransactionPhase(ERequestPhase ) ) + { + // Request block received. + TPTPIPTypeRequestPayload* pRequest = static_cast(iPTPIPCommandContainer->Payload()); + + TUint16 op(pRequest->Uint16(TPTPIPTypeRequestPayload::EOpCode )); + TUint32 tran(pRequest->Uint32(TPTPIPTypeRequestPayload::ETransactionId )); + TUint32 sessionId = KMTPSessionNone; + __FLOG_VA((_L8("Command block received with op = 0x%04X ,transId = %d"), op, tran)); + + // Reset the iMTPRequest. + iMTPRequest.Reset( ); + + // Setup the MTP request dataset buffer. Set Operation Code and TransactionID + iMTPRequest.SetUint16(TMTPTypeRequest::ERequestOperationCode, op ); + iMTPRequest.SetUint32(TMTPTypeRequest::ERequestTransactionID, tran ); + + // Set SessionID. + if(op == EMTPOpCodeOpenSession ) + { + __FLOG(_L8("Processing OpenSession request")); + } + else if(op == EMTPOpCodeCloseSession || op == EMTPOpCodeResetDevice ) + { + __FLOG(_L8("Processing CloseSession or the ResetDevice request")); + // Force CloseSession requests to be processed outside an active session. + // ResetDevice currently behaves the same way as CloseSession. + iMTPRequest.SetUint32(TMTPTypeRequest::ERequestParameter1, + iMTPSessionId ); + } + else + { + sessionId = iMTPSessionId; + __FLOG_VA((_L8("Processing general request on session %d"), sessionId)); + } + + iMTPRequest.SetUint32(TMTPTypeRequest::ERequestSessionID,sessionId ); + + // Set Parameter 1 .. Parameter 5. + pRequest->CopyOut(iMTPRequest, TMTPTypeRequest::ERequestParameter1, TMTPTypeRequest::ERequestParameter5 ); + pRequest->Reset( ); + + // Notify the protocol layer. + + BoundProtocolLayer().ReceivedRequestL(iMTPRequest ); + + } + __FLOG(_L8("ReceiveCommandCompleteL - Exit")); + } + +/** + Called to get data over the command channel,( in turn its called by f/ws ReceiveData) + @param aData - The buffer provided by the F/w in which to receive data. + */ +void CPTPIPConnection::ReceiveCommandDataL(MMTPType& aData ) + { + __FLOG(_L8("ReceiveCommandDataL - Entry")); + + iRecvData = 0; + iTotalRecvData = 0; + + // First we will receive a PTPIP start data packet which is stored in the commandContainer + iPTPIPCommandContainer->SetPayloadL(&iPTPIPStartDataPayload ); + + // The mtp buffer is passed from the framework and will be passed on as the payload. + // in the next ptpip data packet. + iPTPIPDataContainer->SetPayloadL(&aData ); + iCommandHandler->ReceiveCommandDataL(*iPTPIPCommandContainer ); + + __FLOG(_L8("ReceiveCommandDataL - Exit")); + } + +/** + Called to indicate completion of receive of data started by ReceiveCommandDataL. + Any errors received are sent back up to the framework. + */ +void CPTPIPConnection::ReceiveCommandDataCompleteL(TInt aError ) + { + __FLOG(_L8("ReceiveCommandDataCompleteL - Entry")); + if(ValidateTransactionPhase(EDataIToRPhase ) ) + { + // Data block received, notify the protocol layer. + iPTPIPDataContainer->SetUint32L(CPTPIPDataContainer::EPacketType, 0 ); + BoundProtocolLayer().ReceiveDataCompleteL(aError, *iPTPIPDataContainer->Payload(), iMTPRequest ); + } + __FLOG(_L8("ReceiveCommandDataCompleteL - Exit")); + } + +/** + Called by the command handler to indicate completion of receive on the command channel. + Now check whether it was commands or data completion and call the appropriate function. + */ + +void CPTPIPConnection::ReceiveCommandChannelCompleteL(TInt aError, MMTPType& /*aSource*/) + { + __FLOG(_L8("ReceiveCommandChannelCompleteL - Entry")); + __FLOG(_L8("******** Receiving 1 ptpip packet on command/data channel complete **************")); + HandleTCPError(aError ); + TUint32 typeCommand = iPTPIPCommandContainer->Uint32L(CPTPIPGenericContainer::EPacketType ); + TUint32 typeData = iPTPIPDataContainer->Uint32L(CPTPIPGenericContainer::EPacketType ); + __FLOG_VA((_L8("type on the command buffer is %d and type on the data buffer is %d"), typeCommand, typeData ) ); + + + switch (typeCommand) + { + case EPTPIPPacketTypeOperationRequest: + ReceiveCommandCompleteL(aError ); + break; + + case EPTPIPPacketTypeStartData: + if(aError != KErrNone ) + { + ReceiveCommandCompleteL(aError ); + } + else + { + // Save the total data expected. + iTotalRecvData =(static_cast(iPTPIPCommandContainer->Payload()))->Uint64(TPTPIPTypeStartDataPayload::ETotalSize ); + __FLOG_VA((_L8("Total data to receive in data phase is %ld"), iTotalRecvData)); + + //reset the command container + iPTPIPCommandContainer->SetUint32L(CPTPIPGenericContainer::EPacketType, 0 ); + iCommandHandler->ReceiveCommandDataL(*iPTPIPDataContainer ); + } + break; + + case EPTPIPPacketTypeCancel: + { + TMTPTypeInt32* pTransId; + pTransId = static_cast(iPTPIPCommandContainer->Payload()); + iCancelOnCommandState = ECancelCmdReceived; + HandleCommandCancelL(pTransId->Value()); + } + break; + + + default: + // No known types came on the command container, now check the data container. + switch (typeData) + { + case EPTPIPPacketTypeData: + // One PTPIP packet has been received. We will now continue getting the next PTPIP packets. + iRecvData += iPTPIPDataContainer->Uint32L(CPTPIPDataContainer::EPacketLength ); + iRecvData -= KPTPIPDataHeaderSize; // The header size is not included in the total size sent. + + //If more data is expected,then set the flag to use the current offset + //in the chunk + if (iRecvData < iTotalRecvData) + { + iCommandHandler->iUseOffset = ETrue; + + } + + + __FLOG_VA((_L8("Data received so far in data phase is %ld"), iRecvData)); + if(iRecvData <= iTotalRecvData ) + { + iCommandHandler->ReceiveCommandDataL(*iPTPIPDataContainer ); + } + else + { + __FLOG_VA((_L8("PTPIP ERROR: The data received so far= %ld is more than expected data = %ld "), iRecvData, iTotalRecvData)); + CloseConnection( ); + } + break; + + case EPTPIPPacketTypeEndData: + iRecvData += iPTPIPDataContainer->Uint32L(CPTPIPDataContainer::EPacketLength ); + iRecvData -= KPTPIPDataHeaderSize; // The header size is not included in the total size sent. + + iCommandHandler->iUseOffset = EFalse; + + __FLOG_VA((_L8("Data received so far in data phase is %ld"), iRecvData)); + if(iTotalRecvData == iRecvData ) + { + ReceiveCommandDataCompleteL(aError ); + } + else + { + __FLOG_VA((_L8("PTPIP ERROR: The data received so far= %ld is not equal to expected data = %ld "), iRecvData, iTotalRecvData)); + CloseConnection( ); + } + break; + + case EPTPIPPacketTypeCancel: + { + TUint32 transId = iPTPIPDataContainer->Uint32L(CPTPIPDataContainer::ETransactionId); + iCancelOnCommandState = ECancelCmdReceived; + iPTPIPDataContainer->SetUint32L(CPTPIPDataContainer::EPacketType, 0 ); + HandleCommandCancelL(transId); + } + break; + + default: + __FLOG_VA((_L8("PTPIP ERROR: Unexpected type received, data container = %d, command container =%d "), typeData, typeCommand)); + CloseConnection( ); + break; + } // switch data + } // switch command + + __FLOG(_L8("ReceiveCommandChannelCompleteL - Exit")); + } + +/** + Called by MTP fw to get data from the transport. + */ +void CPTPIPConnection::ReceiveDataL(MMTPType& aData, const TMTPTypeRequest& /*aRequest*/) + { + __FLOG(_L8("ReceiveDataL - Entry")); + __FLOG(_L8("******** Phase 2 - Data I to R **************")); + SetTransactionPhase(EDataIToRPhase ); + ReceiveCommandDataL(aData ); + __FLOG(_L8("ReceiveDataL - Exit")); + } + +/** + Called by MTP fw to cancel the receiving data. + */ +void CPTPIPConnection::ReceiveDataCancelL(const TMTPTypeRequest& /*aRequest*/) + { + __FLOG(_L8("ReceiveDataCancelL - Entry")); + + iCommandHandler->CancelReceiveL(KErrCancel ); + __FLOG(_L8("ReceiveDataCancelL - Exit")); + } + +/** + This will invoke the event handler to listen on the socket and get the events + into the buffers passed. + */ +void CPTPIPConnection::InitiateEventRequestPhaseL( ) + { + __FLOG(_L8("InitiateEventRequestPhaseL - Entry")); + + // Initialise the PTP buffers to get the data. + iPTPIPEventPayload.Reset( ); + iPTPIPEventContainer->SetUint32L(CPTPIPGenericContainer::EPacketType, NULL ); + iPTPIPEventContainer->SetUint32L(CPTPIPGenericContainer::EPacketLength, NULL ); + iPTPIPEventContainer->SetPayloadL(&iPTPIPEventPayload ); + + // Call the EventHandler + iEventHandler->ReceiveEventL(*iPTPIPEventContainer ); + __FLOG(_L8("InitiateEventRequestPhaseL - Exit")); + } + +/** + Signals the completion of receving an event. + */ +void CPTPIPConnection::ReceiveEventCompleteL(TInt aError, MMTPType& /*aSource*/) + { + __FLOG(_L8("ReceiveEventCompleteL - Entry")); + + TUint32 type = iPTPIPEventContainer->Uint32L(CPTPIPGenericContainer::EPacketType ); + __FLOG_VA((_L8("Error value is %d and type is %d"), aError, type)); + + if(KErrNone != aError ) + { + __FLOG_VA((_L8("PTPIP Error: Received error=%d in request phase, closing connection"), aError)); + CloseConnection( ); + } + else + { + // For a probe request, we just send a probe response and don't notify the MTP f/w. + if( type == EPTPIPPacketTypeProbeRequest ) + { + __FLOG(_L8("Received a probe request, sending back a probe response")); + // Send the response, + iPTPIPEventContainer->SetPayloadL(NULL ); + iPTPIPEventContainer->SetUint32L(CPTPIPGenericContainer::EPacketLength, iPTPIPEventContainer->Size( ) ); + iPTPIPEventContainer->SetUint32L(CPTPIPGenericContainer::EPacketType, EPTPIPPacketTypeProbeResponse ); + + // Call the EventHandler + iEventHandler->SendEventL(*iPTPIPEventContainer ); + } + else if(type == EPTPIPPacketTypeCancel ) + { + iCancelOnEventState = ECancelCmdReceived; + HandleEventCancelL(); + } + else if(type == EPTPIPPacketTypeEvent ) + { + // Request block received. + TPTPIPTypeResponsePayload* pEvent = static_cast(iPTPIPEventContainer->Payload()); + TUint16 op(pEvent->Uint16(TPTPIPTypeResponsePayload::EResponseCode )); + __FLOG_VA((_L8("Event block 0x%04X received"), op)); + + // Reset the iMTPRequest. + iMTPEvent.Reset( ); + + // Setup the MTP request dataset buffer. Set Operation Code and TransactionID + iMTPEvent.SetUint16(TMTPTypeEvent::EEventCode, op ); + iMTPEvent.SetUint32(TMTPTypeEvent::EEventSessionID, iMTPSessionId ); + iMTPEvent.SetUint32(TMTPTypeEvent::EEventTransactionID, pEvent->Uint32(TPTPIPTypeResponsePayload::ETransactionId ) ); + + // Set Parameter 1 .. Parameter 3. + pEvent->CopyOut(iMTPRequest,TMTPTypeResponse::EResponseParameter1, TMTPTypeResponse::EResponseParameter3 ); + pEvent->Reset( ); + + BoundProtocolLayer().ReceivedEventL(iMTPEvent ); + InitiateEventRequestPhaseL( ); + } + // If unexpected data is received , its ignored in the release mode. + else + { + __FLOG(_L8("PTPIP ERROR : Unknown event type received, ignoring it.")); + __ASSERT_DEBUG(type, Panic(EPTPIPBadState)); + } + } + __FLOG(_L8("ReceiveEventCompleteL - Exit")); + } + +// +// Send data functions +// +/** + Called by the MTP f/w to send the response to the initiator. + Also called from this connection itself to send the cancel response. + */ +void CPTPIPConnection::SendResponseL(const TMTPTypeResponse& aResponse, const TMTPTypeRequest& aRequest ) + { + __FLOG(_L8("SendResponseL - Entry")); + + // Update the transaction state. + SetTransactionPhase(EResponsePhase ); + __FLOG(_L8("******** Phase 3 - Response **************")); + + if(iCancelOnCommandState ) + { + __FLOG(_L8("Cancel has been received from initiator, so send own response")); + + SendCancelResponseL(aRequest.Uint32(TMTPTypeRequest::ERequestTransactionID )); + } + else + { + TUint16 opCode(aRequest.Uint16(TMTPTypeRequest::ERequestOperationCode )); + TUint16 rspCode(aResponse.Uint16(TMTPTypeResponse::EResponseCode )); + __FLOG_VA((_L8("ResponseCode = 0x%04X, Operation Code = 0x%04X"), rspCode, opCode)); + + if((opCode == EMTPOpCodeOpenSession) &&(rspCode == EMTPRespCodeOK) ) + { + // An session has been opened. Record the active SessionID. + iMTPSessionId = aRequest.Uint32(TMTPTypeRequest::ERequestParameter1 ); + __FLOG_VA((_L8("Processing OpenSession response, SessionID = %d"), iMTPSessionId)); + } + else if(((opCode == EMTPOpCodeCloseSession) || + (opCode == EMTPOpCodeResetDevice))&&(rspCode == EMTPRespCodeOK) ) + { + // An session has been closed. Clear the active SessionID. + __FLOG_VA((_L8("Processing CloseSession or ResetDevice response, SessionID = %d"), iMTPSessionId)); + iMTPSessionId = KMTPSessionNone; + } + + //Setup the parameter block payload dataset. Note that since this is a + //variable length dataset, it must first be reset. + + iPTPIPResponsePayload.Reset( ); + TUint numberOfNullParam = TMTPTypeResponse::EResponseParameter5 - TMTPTypeResponse::EResponseParameter1 + 1; + + iPTPIPResponsePayload.CopyIn(aResponse, + TMTPTypeResponse::EResponseParameter1, TMTPTypeResponse::EResponseParameter5, + ETrue, + numberOfNullParam); + iPTPIPResponsePayload.SetUint16(TPTPIPTypeResponsePayload::EResponseCode, rspCode ); + iPTPIPResponsePayload.SetUint32(TPTPIPTypeResponsePayload::ETransactionId, aRequest.Uint32(TMTPTypeRequest::ERequestTransactionID ) ); + + // Setup the command container. + iPTPIPCommandContainer->SetPayloadL(const_cast(&iPTPIPResponsePayload) ); + iPTPIPCommandContainer->SetUint32L( CPTPIPGenericContainer::EPacketLength, static_cast(iPTPIPCommandContainer->Size()) ); + iPTPIPCommandContainer->SetUint32L( CPTPIPGenericContainer::EPacketType, EPTPIPPacketTypeOperationResponse ); + + // Initiate the command send sequence. + __FLOG_VA((_L8("Sending response 0x%04X(%d bytes)"), + iPTPIPResponsePayload.Uint16(TPTPIPTypeResponsePayload::EResponseCode), + iPTPIPCommandContainer->Uint32L(CPTPIPGenericContainer::EPacketLength))); + iCommandHandler->SendCommandL(*iPTPIPCommandContainer ); + } + + __FLOG(_L8("SendResponseL - Exit")); + } + +/** + Send response complete + */ +void CPTPIPConnection::SendCommandCompleteL(TInt aError ) + { + + __FLOG(_L8("SendCommandCompleteL - Entry")); + + if(ValidateTransactionPhase(EResponsePhase ) ) + { + BoundProtocolLayer().SendResponseCompleteL( aError, + *static_cast(iPTPIPCommandContainer->Payload()), + iMTPRequest ); + } + __FLOG(_L8("SendCommandCompleteL - Exit")); + } + +/** + Send data complete + */ +void CPTPIPConnection::SendCommandDataCompleteL(TInt aError ) + { + __FLOG(_L8("SendCommandDataCompleteL - Entry")); + + if(ValidateTransactionPhase(EDataRToIPhase ) ) + { + BoundProtocolLayer().SendDataCompleteL(aError, *iPTPIPDataContainer->Payload(), iMTPRequest ); + } + SetConnectionState(EDataSendFinished); + iPTPIPDataContainer->SetPayloadL(NULL ); + + __FLOG(_L8("SendCommandDataCompleteL - Exit")); + } + +/** + Called by the command handler to indicate completion of send on the command channel. + Now check whether it was commands or data completion and call the appropriate function. + */ +void CPTPIPConnection::SendCommandChannelCompleteL(TInt aError, const MMTPType& /*aSource*/) + { + __FLOG(_L8("SendCommandChannelCompleteL - Entry")); + + // Now see whether we have completed getting data or commands, and call the appropriate function. + TUint typeCommand = iPTPIPCommandContainer->Uint32L(CPTPIPGenericContainer::EPacketType ); + TUint typeData = iPTPIPDataContainer->Uint32L(CPTPIPGenericContainer::EPacketType ); + __FLOG_VA((_L8("type on the command buffer is %d and type on the data buffer is %d"), typeCommand, typeData ) ); + + + // if we have received a cancel on the event channel then terminate the current sending + // and handle the receiving and sending of cancel on the channel. + if (iCancelOnEventState && !iCancelOnCommandState) + { + HandleCancelDuringSendL(); + } + + // A command has been sent + else if((EPTPIPPacketTypeOperationResponse == typeCommand) &&(0 == typeData) ) + { + // If this response was a cancel, then we don't inform the framework, as it was internally generated + if(iCancelOnCommandState ) + { + iCancelOnCommandState = ECancelCmdHandled; + SendCommandCompleteL(aError ); + HandleCommandCancelCompleteL( ); + } + // Tell the framework that a command has been received. + else + { + iPTPIPCommandContainer->SetUint32L(CPTPIPGenericContainer::EPacketType, 0 ); + SendCommandCompleteL(aError ); + } + } + + // Tell the connection that data has been sent. + else if((EPTPIPPacketTypeEndData == typeData) &&(0 == typeCommand ) ) + { + iPTPIPDataContainer->SetUint32L(CPTPIPDataContainer::EPacketType, 0 ); + SendCommandDataCompleteL(aError ); + } + + // We sent the start data packet, and we now have to send the actual data. + else if((EPTPIPPacketTypeStartData == typeCommand) &&(EDataSendInProgress == iState ) ) + { + iPTPIPCommandContainer->SetUint32L( CPTPIPGenericContainer::EPacketType, 0 ); + SendDataPacketL( ); + } + + // Any other type indicates a programming error, and a panic is raised. + else + { + __FLOG_VA((_L8("PTPIP ERROR: Unexpected type in sent data, type = = %d, command =%d "), typeData, typeCommand)); + Panic(EPTPIPBadState ); + } + + __FLOG(_L8("SendCommandChannelCompleteL - Exit")); + } + +/** + Called by the MTP fw to send the data by the transport via the sockets + */ +void CPTPIPConnection::SendDataL(const MMTPType& aData, const TMTPTypeRequest& aRequest ) + { + __FLOG(_L8("SendDataL - Entry")); + + __FLOG(_L8("******** Phase 2 - Data R to I **************")); + SetTransactionPhase(EDataRToIPhase ); + SetConnectionState(EDataSendInProgress ); + + // Save the actual data in the dataContainer + iPTPIPDataContainer->SetPayloadL(const_cast(&aData) ); + iPTPIPDataContainer->SetUint32L(CPTPIPDataContainer::EPacketLength, iPTPIPDataContainer->Size( ) ); + + iPTPIPDataContainer->SetUint32L(CPTPIPDataContainer::EPacketType,EPTPIPPacketTypeEndData ); + iPTPIPDataContainer->SetUint32L(CPTPIPDataContainer::ETransactionId,aRequest.Uint32(TMTPTypeRequest::ERequestTransactionID ) ); + + // Create the start data ptpip packet. + iPTPIPStartDataPayload.Reset( ); + iPTPIPStartDataPayload.SetUint32(TPTPIPTypeStartDataPayload::ETransactionId, aRequest.Uint32(TMTPTypeRequest::ERequestTransactionID ) ); + iPTPIPStartDataPayload.SetUint64(TPTPIPTypeStartDataPayload::ETotalSize, aData.Size( ) ); + + iPTPIPCommandContainer->SetPayloadL(&iPTPIPStartDataPayload ); + iPTPIPCommandContainer->SetUint32L(CPTPIPGenericContainer::EPacketLength, iPTPIPCommandContainer->Size( ) ); + iPTPIPCommandContainer->SetUint32L(CPTPIPGenericContainer::EPacketType, EPTPIPPacketTypeStartData ); + + // First send the start data packet, once this is complete, it will invoke the + // SendCommandChannelCompleteL, where we will check the state and send the + // actual data in the next packet, which has been saved in the dataContainer. + SendStartDataPacketL( ); + + __FLOG(_L8("SendDataL - Exit")); + } + +/** + The data will be sent in 2 ptpip operations. + first the start data ptpip packet will be sent. This has the totalk size and transaction. + next the actual data packet will be sent, with the end data ptp ip header. + */ +void CPTPIPConnection::SendStartDataPacketL( ) + { + __FLOG(_L8("SendStartDataPacketL - Entry")); + + SetConnectionState(EDataSendInProgress ); + iCommandHandler->SendCommandL(*iPTPIPCommandContainer ); + __FLOG(_L8("SendStartDataPacketL - Exit")); + } + +/** + Send the actual data, which has come from the MTP framework + */ +void CPTPIPConnection::SendDataPacketL( ) + { + __FLOG(_L8("SendDataPacketL - Entry")); + + MMTPType* payLoad = iPTPIPDataContainer->Payload(); + + TPtr8 headerChunk(NULL, 0); + TBool hasTransportHeader = payLoad->ReserveTransportHeader(KPTPIPDataHeaderSize, headerChunk); + if (hasTransportHeader) + { + const TInt KLengthOffset = 0; + const TInt KTypeOffset = 4; + const TInt KXIDOffset = 8; + TUint32 pkgLength = iPTPIPDataContainer->Uint32L(CPTPIPDataContainer::EPacketLength); + TUint32 pkgType = iPTPIPDataContainer->Uint32L(CPTPIPDataContainer::EPacketType); + TUint32 transId = iPTPIPDataContainer->Uint32L(CPTPIPDataContainer::ETransactionId); + + memcpy(&(headerChunk[KLengthOffset]), &pkgLength, sizeof(TUint32)); + memcpy(&(headerChunk[KTypeOffset]), &pkgType, sizeof(TUint32)); + memcpy(&(headerChunk[KXIDOffset]), &transId, sizeof(TUint32)); + + SetConnectionState(EDataSendInProgress ); + iCommandHandler->SendCommandDataL(*payLoad, transId); + } + else + { + + SetConnectionState(EDataSendInProgress ); + iCommandHandler->SendCommandDataL(*iPTPIPDataContainer, iPTPIPDataContainer->Uint32L(TMTPTypeRequest::ERequestTransactionID ) ); + } + + __FLOG(_L8("SendDataPacketL - Exit")); + } + +/** + Called by the fw to cancel the sending of data + */ +void CPTPIPConnection::SendDataCancelL(const TMTPTypeRequest& /*aRequest*/) + { + __FLOG(_L8("SendDataCancelL - Entry")); + iCommandHandler->CancelSendL(KErrCancel ); + __FLOG(_L8("SendDataCancelL - Exit")); + } + +/** + Called by the fw to send an event. + */ +void CPTPIPConnection::SendEventL(const TMTPTypeEvent& aEvent ) + { + __FLOG(_L8("SendEventL - Entry")); + + // Reset the event. + iMTPEvent.Reset(); + MMTPType::CopyL(aEvent, iMTPEvent); + + TUint16 opCode(aEvent.Uint16(TMTPTypeEvent::EEventCode )); + TUint32 tran(aEvent.Uint32(TMTPTypeEvent::EEventTransactionID )); + __FLOG_VA((_L8(" Sending event with Operation Code = 0x%04X and tran id = %d"), opCode, tran )); + + TBool isNullParamValid = EFalse; + TUint numberOfNullParam = 0; + + iPTPIPEventPayload.CopyIn(aEvent, + TMTPTypeResponse::EResponseParameter1,TMTPTypeResponse::EResponseParameter3, + isNullParamValid, + numberOfNullParam ); + + iPTPIPEventPayload.SetUint16(TPTPIPTypeResponsePayload::EResponseCode, opCode ); + iPTPIPEventPayload.SetUint32(TPTPIPTypeResponsePayload::ETransactionId, tran ); + + // Setup the bulk container. + iPTPIPEventContainer->SetPayloadL(const_cast(&iPTPIPEventPayload) ); + iPTPIPEventContainer->SetUint32L(CPTPIPGenericContainer::EPacketLength, static_cast(iPTPIPEventContainer->Size()) ); + iPTPIPEventContainer->SetUint32L(CPTPIPGenericContainer::EPacketType, EPTPIPPacketTypeEvent ); + + // Initiate the event send sequence. + __FLOG_VA((_L8("Sending response 0x%04X(%d bytes)"), + iPTPIPEventPayload.Uint16(TPTPIPTypeResponsePayload::EResponseCode), + iPTPIPEventContainer->Uint32L(CPTPIPGenericContainer::EPacketLength))); + + iEventHandler->SendEventL(*iPTPIPEventContainer ); + __FLOG(_L8("SendEventL - Exit")); + } + +/** + Marks the completion of the asynchronous send event. + */ +void CPTPIPConnection::SendEventCompleteL(TInt aError, const MMTPType& /*aSource*/) + { + __FLOG(_L8("SendEventCompleteL - Entry")); + TUint type = iPTPIPEventContainer->Uint32L(CPTPIPGenericContainer::EPacketType ); + + // Notify the fw that event was sent. + if(type == EPTPIPPacketTypeEvent ) + { + // Notify the fw + BoundProtocolLayer().SendEventCompleteL(aError, iMTPEvent ); + } + +#ifdef _DEBUG + //In case we sent a probe response, we dont' need to notify the fw. + else + if(type == EPTPIPPacketTypeProbeResponse ) + { + __FLOG(_L8("Probe response was sent successfully")); + } + else + { + // If unexpected data was sent , it is ignored in the release mode. + __FLOG(_L8("PTPIP ERROR: An invalid send event completion signalled")); + __ASSERT_DEBUG(type, Panic(EPTPIPBadState)); + } +#endif + + // Restart listening for events + InitiateEventRequestPhaseL( ); + __FLOG(_L8("SendEventCompleteL - Exit")); + } + +// +// Cancel handling functions +// + +/** + Handle the cancel on the event channel. This can come before + or after the cancel on the command channle, and it can also come + in any of the MTP transaction states ( request, response, data) + */ +void CPTPIPConnection::HandleEventCancelL( ) + { + __FLOG(_L8("HandleEventCancelL - Entry")); + __FLOG_VA((_L8("iCancelOnCommandState = 0x%04X, and iCancelOnEventState = 0x%04X"), iCancelOnCommandState, iCancelOnEventState)); + + // Check whether the cancel has already been received on the command channel. + // If so then we can simply ignore this on the event channel. + switch(iCancelOnCommandState ) + { + case ECancelCmdHandled: + // Cancel has already been received and handled on the command channel + // ignore the cancel on event channel and reset the state to none, + // and start listening for the next transaction. + iCancelOnCommandState = ECancelNotReceived; + iCancelOnEventState = ECancelNotReceived; + InitiateEventRequestPhaseL(); + break; + + case ECancelCmdReceived: + case ECancelCmdHandleInProgress: + // cancel has already been received on the command channel and is being + // handled. Ignore the cancel on event channel. + iCancelOnEventState = ECancelEvtHandled; + break; + + case ECancelNotReceived: + // cancel on command has not yet been received. depending on the current + // mtp transaction state, handle the cancel. + + switch(iTransactionState ) + { + case EDataIToRPhase: + SetNULLPacketL(); + iCancelOnEventState = ECancelEvtHandled; + break; + + case EDataRToIPhase: + // Set the commandHandler's cancel flag on. + // It will complete sending the current PTPIP packet and then handle. + // Once a PTPIP packet has been sent , the sendCommandChannel complete will + // be invoked, and the cancel will be checked and handled. + iCancelOnEventState = ECancelEvtHandled; + iCommandHandler->SetCancel(); + break; + + case EResponsePhase: + case ERequestPhase: + default: + __FLOG(_L8(" Cancel received on event channel during a non data phase, ignoring, as this will be handled when its received on command channel.")); + iCancelOnEventState = ECancelEvtHandled; + break; + }// end of switch for transaction phase. + + break; + default: + break; + } + __FLOG(_L8("HandleEventCancelL - Exit")); + } + +/** + Handle the cancel on the command channel. This can come before + or after the cancel on the event channel, and it can also come + in any of the MTP transaction states ( request, response, data) + */ +void CPTPIPConnection::HandleCommandCancelL(TUint32 aTransId ) + { + __FLOG(_L8("HandleCommandCancelL - Entry")); + + switch(iTransactionState ) + { + case ERequestPhase: + __FLOG(_L8(" Cancel received during the request phase before the request packet, ignoring.")); + iCancelOnCommandState = ECancelCmdHandled; + if (iCancelOnEventState == ECancelNotReceived) + { + // Wait for it to be received on event + __FLOG(_L8("Awaiting cancel on the event channel.")); + } + else + { + HandleCommandCancelCompleteL(); + } + InitiateCommandRequestPhaseL(); + break; + + case EDataRToIPhase: + iCancelOnCommandState = ECancelCmdHandleInProgress; + SendCancelToFrameworkL(aTransId ); + SendCommandDataCompleteL(KErrCancel); + break; + + case EDataIToRPhase: + iCancelOnCommandState = ECancelCmdHandleInProgress; + SendCancelToFrameworkL(aTransId ); + ReceiveCommandDataCompleteL(KErrCancel); + break; + + case EResponsePhase: + iCancelOnCommandState = ECancelCmdHandled; + if (iCancelOnEventState == ECancelNotReceived) + { + // Wait for it to be received on event + __FLOG(_L8("Awaiting cancel on the event channel.")); + } + else + { + HandleCommandCancelCompleteL(); + } + + break; + }// switch + + __FLOG(_L8("HandleCommandCancelL - Exit")); + } + + +void CPTPIPConnection::HandleCancelDuringSendL() + { + __FLOG(_L8("HandleCancelDuringSendL - Entry")); + iCommandHandler->Cancel( ); + // Now start listening for the cancel on command channel. + iPTPIPDataContainer->SetUint32L(CPTPIPDataContainer::EPacketType, 0 ); + iPTPIPCommandContainer->SetUint32L( CPTPIPGenericContainer::EPacketType, 0 ); + iPTPIPCommandCancelPayload.Set(0 ); + iPTPIPCommandContainer->SetPayloadL(&iPTPIPCommandCancelPayload ); + iCommandHandler->ReceiveCommandRequestL(*iPTPIPCommandContainer ); + __FLOG(_L8("HandleCancelDuringSendL - Exit")); + } + +/** + Called when the reponse to the cancel has been sent to the initiator + */ +void CPTPIPConnection::HandleCommandCancelCompleteL( ) + { + __FLOG(_L8("HandleCommandCancelCompleteL - Entry")); + //now cancel handling is complete. + + if((ECancelCmdHandled == iCancelOnCommandState) &&(ECancelEvtHandled == iCancelOnEventState) ) + { + __FLOG(_L8("Completed handling cancel on both channels. ")); + // Cancel has already been received and handled on the command channel + // ignore the cancel on event channel and reset the state to none, + // and start listening for the next transaction. + iCancelOnCommandState = ECancelNotReceived; + iCancelOnEventState = ECancelNotReceived; + // The transaction has been cancelled, now start listening again for next transaction. + InitiateEventRequestPhaseL(); + } + // if the cancel has not been received yet on event, we wait for it. + else if(ECancelEvtHandled != iCancelOnEventState ) + { + __FLOG(_L8("Waiting for the cancel on the event channel. ")); + } + __FLOG(_L8("HandleCommandCancelCompleteL - Exit")); + } + +/** + Inform the MTP framework that a cancel has been received. + */ +void CPTPIPConnection::SendCancelToFrameworkL(TUint32 aTransId ) + { + __FLOG(_L8("SendCancelToFramework - Entry")); + + // Setup the MTP request dataset buffer. Set Operation Code and TransactionID + iMTPEvent.Reset( ); + iMTPEvent.SetUint16(TMTPTypeEvent::EEventCode, EMTPEventCodeCancelTransaction ); + iMTPEvent.SetUint32(TMTPTypeEvent::EEventSessionID, iMTPSessionId ); + iMTPEvent.SetUint32(TMTPTypeEvent::EEventTransactionID, aTransId ); + + BoundProtocolLayer().ReceivedEventL(iMTPEvent ); + __FLOG(_L8("SendCancelToFramework - Exit")); + } + +/** + Send the response to the cancel event. + */ +void CPTPIPConnection::SendCancelResponseL(TUint32 aTransId ) + { + __FLOG(_L8("SendCancelResponse - Entry")); + iPTPIPResponsePayload.Reset( ); + iPTPIPResponsePayload.SetUint16(TPTPIPTypeResponsePayload::EResponseCode, EMTPRespCodeTransactionCancelled ); + iPTPIPResponsePayload.SetUint32(TPTPIPTypeResponsePayload::ETransactionId, aTransId ); + + // Setup the command container. + iPTPIPCommandContainer->SetPayloadL(const_cast(&iPTPIPResponsePayload) ); + iPTPIPCommandContainer->SetUint32L(CPTPIPGenericContainer::EPacketLength, static_cast(iPTPIPCommandContainer->Size()) ); + iPTPIPCommandContainer->SetUint32L(CPTPIPGenericContainer::EPacketType, EPTPIPPacketTypeOperationResponse ); + + // Initiate the command send sequence. + __FLOG_VA((_L8("Sending response 0x%04X(%d bytes)"), + iPTPIPResponsePayload.Uint16(TPTPIPTypeResponsePayload::EResponseCode), + iPTPIPCommandContainer->Uint32L(CPTPIPGenericContainer::EPacketLength))); + iCommandHandler->SendCommandL(*iPTPIPCommandContainer ); + __FLOG(_L8("SendCancelResponse - Exit")); + } + +/** + * If the cancel packet is received on the event channel first + * and we are in the DataItoR phase, we have to continue reading and ignoreing the + * data packets sent by the initiator, into dummy buffers until the cancel packet is received. + */ +void CPTPIPConnection::SetNULLPacketL() + { + __FLOG(_L8("SetNULLPacketL - Entry")); + // Setup the bulk container and initiate the bulk data receive sequence. + iNullBuffer.Close(); + iNullBuffer.CreateL(KMTPNullChunkSize); + iNullBuffer.SetLength(KMTPNullChunkSize); + iNull.SetBuffer(iNullBuffer); + iPTPIPDataContainer->SetPayloadL(&iNull); + __FLOG(_L8("SetNULLPacketL - Exit")); + } + +// +// Getters , Setters and other helper functions +// + +/** + This function will transfer the two command and event sockets from the Controller + and indicate the successful transfer to the PTP controller + @leave - In case the Publish and Subscribe mechanism gives any errors while getting the + property names, then a leave occurs. + Also in case opening or transferring the socket fails, a leave is generated. + */ +void CPTPIPConnection::TransferSocketsL( ) + { + + __FLOG(_L8("TransferSocketsL - Entry")); + + TName evtsockname, cmdsockname; + TUid propertyUid=iConnectionMgr->ClientSId(); + User::LeaveIfError(RProperty::Get(propertyUid, ECommandSocketName, cmdsockname )); + User::LeaveIfError(RProperty::Get(propertyUid, EEventSocketName, evtsockname )); + + RSocketServ serversocket; + TInt err=serversocket.Connect( ); + __FLOG_VA((_L8("Connected to socketServer with %d code"), err) ); + + if (KErrNone == err) + { + User::LeaveIfError(iCommandHandler->Socket().Open(serversocket )); + User::LeaveIfError(iEventHandler->Socket().Open(serversocket )); + + User::LeaveIfError(err=iCommandHandler->Socket().Transfer(serversocket, cmdsockname )); + User::LeaveIfError(err=iEventHandler->Socket().Transfer(serversocket, evtsockname )); + } + + iCommandHandler->SetSocketOptions(); + iEventHandler->SetSocketOptions(); + + __FLOG(_L8("TransferSocketsL - Exit")); + } + + +/** + Connection establishment has 4 steps, the first 3 are completed by the controller process: + + 1. Initiator connects to command socket, sends the init command request + 2. Responder replies with the init command ack + 3. Initiator connects to the command socket, sends the init event request + + 4. Responder replies with the init event ack or init event fail. + + The last step of sending the init ack is done by the transport plugin from + the mtp process. This is done after the the framework has loaded, the sockets have + been transferred to this process and the transport is up. + */ +void CPTPIPConnection::SendInitAckL( ) + { + + __FLOG(_L8("SendInitAckL - Entry")); + + iPTPIPEventContainer->SetPayloadL(NULL ); + iPTPIPEventContainer->SetUint32L(TPTPIPInitEvtAck::ELength, iPTPIPEventContainer->Size( ) ); + iPTPIPEventContainer->SetUint32L(TPTPIPInitEvtAck::EType, EPTPIPPacketTypeEventAck ); + + // Send the packet + iEventHandler->SendInitAck(iPTPIPEventContainer ); + + __FLOG(_L8("SendInitAckL - Exit")); + } + +/** + Stop the connection. + + First cancel the command and socket handlers which are controlled by it + and complete any data send of receive commands with error code of abort. + + Also inform the fw that connection is closed. + + */ +void CPTPIPConnection::StopConnection( ) + { + __FLOG(_L8("StopConnection - Entry")); + + if(ConnectionOpen( ) ) + { + __FLOG(_L8("Stopping socket handlers")); + iEventHandler->Cancel( ); + iCommandHandler->Cancel( ); + if(iTransactionState == EDataIToRPhase ) + { + __FLOG(_L8("Aborting active I to R data phase")); + TRAPD(err, BoundProtocolLayer().ReceiveDataCompleteL(KErrAbort, *iPTPIPDataContainer->Payload(), iMTPRequest)); + UNUSED_VAR(err); + } + else + if(iTransactionState == EDataRToIPhase ) + { + __FLOG(_L8("Aborting active R to I data phase")); + TRAPD(err, BoundProtocolLayer().SendDataCompleteL(KErrAbort, *iPTPIPDataContainer->Payload(), iMTPRequest)) ; + UNUSED_VAR(err); + } + + __FLOG(_L8("Notifying protocol layer connection closed")); + iConnectionMgr->ConnectionClosed(*this ); + SetTransactionPhase(EUndefined ); + SetConnectionState(EIdle ); + } + + __FLOG(_L8("StopConnection - Exit")); + } + +/** + * Invoked by the SocketHandler when there is an error. + */ +#ifdef __FLOG_ACTIVE +void CPTPIPConnection::HandleError(TInt aError) +#else +void CPTPIPConnection::HandleError(TInt /*aError*/) +#endif + { + __FLOG_VA((_L8("SocketHandler received an error=%d, stopping connection.)"),aError)); + StopConnection(); + } + +/** + Used to trigger the RunL, by first setting itself to active and + then simulating a fake asynchronous service provider which will complete us + with a completion code. + */ +void CPTPIPConnection::CompleteSelf(TInt aCompletionCode ) + { + // Setting ourselves active to wait to be done by ASP. + SetActive( ); + + // Simulating a fake ASP which completes us. + TRequestStatus* stat = &iStatus; + User::RequestComplete(stat, aCompletionCode ); + } + +/** + Setter for transaction phase(request, dataItoR, dataRtoI, or response) + */ +void CPTPIPConnection::SetTransactionPhase(TMTPTransactionPhase aPhase ) + { + __FLOG(_L8("SetTransactionPhase - Entry")); + iTransactionState = aPhase; + __FLOG_VA((_L8("Transaction Phase set to 0x%08X"), iTransactionState)); + __FLOG(_L8("SetTransactionPhase - Exit")); + } + +/** + Setter for connection state,( initialising, send data, etc) + */ +void CPTPIPConnection::SetConnectionState(TConnectionState aState ) + { + __FLOG(_L8("SetConnectionState - Entry")); + iState = aState; + __FLOG_VA((_L8("Connection state set to 0x%08X"), iState)); + __FLOG(_L8("SetConnectionState - Exit")); + } + +/** + Getter + */ +TBool CPTPIPConnection::ConnectionOpen( ) const + { + return((iState >= EInitialising) && (iState <= EDataSendFinished)); + } + +/** + Getter for the command container, + */ +CPTPIPGenericContainer* CPTPIPConnection::CommandContainer( ) + { + return iPTPIPCommandContainer; + } + +/** + Getter for the event container + */ +CPTPIPGenericContainer* CPTPIPConnection::EventContainer( ) + { + return iPTPIPEventContainer; + } + +/** + Getter for the data container + */ +CPTPIPDataContainer* CPTPIPConnection::DataContainer( ) + { + return iPTPIPDataContainer; + } + +/** + Getter for the transaction phase: request, dataItoR, dataRtoI or response + */ +TMTPTransactionPhase CPTPIPConnection::TransactionPhase( ) const + { + return iTransactionState; + } + +/** + Takes the 4 bytes from the chunk(iReceiveChunkData) and return + whether the type is a valid request, cancel or probe packet. + + @return: The container type, in case of an unknown type, + the value 0 ( undefined) is returned + + */ +TUint32 CPTPIPConnection::ValidateAndSetCommandPayloadL( ) + { + __FLOG(_L8("ValidateAndSetCommandPayload - Entry")); + + TUint32 containerType = CommandContainer()->Uint32L(CPTPIPGenericContainer::EPacketType ); + + __FLOG_VA((_L8("PTP packet type = %d, adjust payload accordingly"), containerType)); + + switch(containerType ) + { + case EPTPIPPacketTypeOperationRequest: + if (!ValidateTransactionPhase(ERequestPhase )) + { + __FLOG(_L8("PTPIP ERROR: Request data unexpected in this phase, setting type to undefined")); + containerType = EPTPIPPacketTypeUndefined; + } + // Nothing to do , the payload is already set. In case this is unexpected, + //then the validate function will close the connection. + break; + + case EPTPIPPacketTypeStartData: + if (!ValidateTransactionPhase(EDataIToRPhase )) + { + __FLOG(_L8("PTPIP ERROR: Start data unexpected in this phase, setting type to undefined")); + containerType = EPTPIPPacketTypeUndefined; + } + // Nothing to do , the payload is already set. In case this is unexpected, + //then the validate function will close the connection. + break; + + case EPTPIPPacketTypeCancel: + // This can come on the command channel either during the data phase or + // during the command phase. + // In data phase, no payload is needed on the data container. + if (EDataIToRPhase == iTransactionState) + { + DataContainer()->SetPayloadL(NULL); + } + else + { + CommandContainer()->SetPayloadL(&iPTPIPCommandCancelPayload ); + } + break; + + case EPTPIPPacketTypeOperationResponse: + __FLOG(_L8("PTPIP ERROR: Response not expected from the initiator, setting type to undefined")); + containerType = EPTPIPPacketTypeUndefined; + // As per the protocol, the initiator cannot send a response, + // only the responder( here device) will create a response, + // if this is recieved it is an erro + break; + + + default: + __FLOG_VA((_L8("PTPIP ERROR: Invalid packet type received %d )"), containerType)); + containerType = EPTPIPPacketTypeUndefined; + break; + } + + __FLOG(_L8("ValidateAndSetCommandPayload - Exit")); + return containerType; + } + +/** + Takes the 4 bytes from the chunk(iReceiveChunkData) and return + whether the type is a valid event packet. + + @return: The container type, in case of an unknown type, + the value 0 ( undefined) is returned + + */ +TUint32 CPTPIPConnection::ValidateDataPacketL( ) + { + __FLOG(_L8("ValidateDataPacketL - Entry")); + + TUint32 containerType = DataContainer()->Uint32L(CPTPIPDataContainer::EPacketType ); + __FLOG_VA((_L8("PTP data packet type = %d, "), containerType)); + + switch(containerType ) + { + case EPTPIPPacketTypeData: + case EPTPIPPacketTypeEndData: + if (!ValidateTransactionPhase(EDataIToRPhase )) + { + __FLOG(_L8("PTPIP ERROR: Receiving data unexpected in this phase, setting type to undefined")); + containerType = EPTPIPPacketTypeUndefined; + } + break; + + default: + __FLOG_VA((_L8("PTPIP ERROR: Unexpected or Invalid packet type received while expecting data packet%d )"), containerType)); + containerType = EPTPIPPacketTypeUndefined; + break; + } + + __FLOG(_L8("ValidateDataPacket - Exit")); + return containerType; + } + +/** + Takes the 4 bytes from the chunk(iReceiveChunkData) and return + whether the type is a valid event packet. + + @return: The container type, in case of an unknown type, + the value 0 ( undefined) is returned + + */ +TUint32 CPTPIPConnection::ValidateAndSetEventPayloadL( ) + { + __FLOG(_L8("ValidateAndSetEventPayload - Entry")); + + TUint32 containerType = EventContainer()->Uint32L(CPTPIPGenericContainer::EPacketType ); + __FLOG_VA((_L8("PTP event packet type = %d, adjust payload accordingly"), containerType)); + + switch(containerType ) + { + case EPTPIPPacketTypeProbeRequest: + EventContainer()->SetPayloadL(NULL ); + break; + + case EPTPIPPacketTypeCancel: + EventContainer()->SetPayloadL(&iPTPIPEventCancelPayload ); + break; + + case EPTPIPPacketTypeEvent: + EventContainer()->SetPayloadL(&iPTPIPEventPayload ); + break; + + default: + __FLOG_VA((_L8("PTPIP ERROR: Invalid packet type received %d )"), containerType)); + containerType = EPTPIPPacketTypeUndefined; + break; + } + + __FLOG(_L8("ValidateAndSetEventPayload - Exit")); + return containerType; + } + +/** + Processes bulk transfer request transaction state checking. If the transaction + state is invalid, then the connection is shutdown. + @return ETrue if the control request completion status was abnormal, otherwise + EFalse. + */ +TBool CPTPIPConnection::ValidateTransactionPhase( + TMTPTransactionPhase aExpectedTransactionState ) + { + __FLOG(_L8("ValidateTransactionPhase - Entry")); + __FLOG_VA((_L8("transaction state = %d"), iTransactionState)); + TBool valid(iTransactionState == aExpectedTransactionState); + if(!valid ) + { + // Invalid transaction state, close the connection. + __FLOG_VA((_L8("PTPIP ERROR: invalid transaction state, current = %d, expected = %d"), iTransactionState, aExpectedTransactionState)); + CloseConnection( ); + } + __FLOG(_L8("ValidateTransactionPhase - Exit")); + return valid; + } + +/** + Convert the TCP errors, the disconnect should be reported as an abort, + since that is what the MTP frameword expects. + */ +TBool CPTPIPConnection::HandleTCPError(TInt& aError ) + { + __FLOG(_L8("TCPErrorHandled - Entry")); + TInt ret(EFalse); + if(aError == KErrDisconnected || aError == KErrEof) + { + aError = KErrAbort; + CloseConnection( ); + ret = ETrue; + } + __FLOG(_L8("TCPErrorHandled - Exit")); + return ret; + } + +void CPTPIPConnection::SetDataTypeInDataContainerL(TPTPIPPacketTypeCode aType ) + { + iPTPIPDataContainer->SetUint32L(CPTPIPDataContainer::EPacketType, aType ); + } + + +