mtpdataproviders/mtppictbridgedp/src/cptpsession.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:11:40 +0200
changeset 0 d0791faffa3f
child 47 63cf70d3ecd8
permissions -rw-r--r--
Revision: 201003 Kit: 201005

// Copyright (c) 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/mmtpdataproviderframework.h>
#include <f32file.h>
#include "cptpsession.h"
#include "cptpserver.h"
#include "cptpreceivedmsghandler.h"
#include "cmtppictbridgeprinter.h"
#include "cptptimer.h"
#include "mtppictbridgedpconst.h"
#include "ptpdef.h" 

// --------------------------------------------------------------------------
// 
// 2-phased constructor.
// --------------------------------------------------------------------------
//
CPtpSession* CPtpSession::NewL(CPtpServer* aServer)
    {
    CPtpSession* self= new (ELeave) CPtpSession(aServer);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);
    return self;
    }

// --------------------------------------------------------------------------
// 
// C++ constructor.
// --------------------------------------------------------------------------
//
CPtpSession::CPtpSession(CPtpServer* aServer) : iServerP(aServer) 
    {
    iServerP->Printer()->RegisterObserver(this); // since PTP register service 
                  // is deprecated we register the observer at session creation
    iServerP->IncrementSessionCount();                  
    }

// --------------------------------------------------------------------------
// 
// --------------------------------------------------------------------------
//
void CPtpSession::ConstructL()
    {
    __FLOG_OPEN(KMTPSubsystem, KPtpServerLog);
    iTimerP=CPtpTimer::NewL(*this);
    }
// --------------------------------------------------------------------------
// 
// C++ destructor.
// --------------------------------------------------------------------------
//
CPtpSession::~CPtpSession()
    {
    __FLOG(_L8(">>>CPtpSession::~"));
    delete iTimerP;
    CancelOutstandingRequest();
    TRAP_IGNORE(CleanupL()); // there is not much we can do at this phase if the removal fails, so just ignore
    if(iServerP->NumSession())
        {
        iServerP->DecrementSessionCount();
        }
    __FLOG(_L8("<<<CPtpSession::~"));
    __FLOG_CLOSE;
    }

// --------------------------------------------------------------------------
// 
// From CSession2, passes the request forward to DispatchMessageL.
// --------------------------------------------------------------------------
//
void CPtpSession::ServiceL( const RMessage2& aMessage )
    {
    __FLOG(_L8(">>>CPtpSession::ServiceL"));
    DispatchMessageL(aMessage);
    __FLOG(_L8("<<<CPtpSession::ServiceL"));
    }

// --------------------------------------------------------------------------
//  Cleans up the previously received DPS file, since the files are used only 
//  for communication
// --------------------------------------------------------------------------
//
void CPtpSession::CleanupL()
    {
    __FLOG(_L8(">>>CPtpSession::Cleanup"));
    if(iReceivedFile.Size())
        {
        __FLOG_VA((_L16("   deleting file %S"), &iReceivedFile));
        User::LeaveIfError(iServerP->Framework().Fs().Delete(iReceivedFile));
        __FLOG(_L8("   removing from DB"));
        iServerP->RemoveObjectL(iReceivedFile);
        iReceivedFile.Zero();
        }
    __FLOG(_L8("<<<CPtpSession::Cleanup"));
    }

// --------------------------------------------------------------------------
// Handles the request from client.
// --------------------------------------------------------------------------
//
void CPtpSession::DispatchMessageL( const RMessage2& aMessage )
    {
    __FLOG_VA((_L8(">>>CPtpSession::DispatchMessageL %d"), aMessage.Function()));
    TInt ret = KErrNone;
    TBool complete = ETrue;        
    CleanupL(); // calling this here assumes that the client never makes a new call 
                // before it has handled the received DPS message
    switch( aMessage.Function() )
        {        
        case EIsDpsPrinter:
            ret = IsDpsPrinter(aMessage, complete);
            break;

        case ECancelIsDpsPrinter:
            CancelIsDpsPrinter();
            break;

        case EGetObjectHandleByName:  
            GetObjectHandleByNameL(aMessage);
            break;

        case EGetNameByObjectHandle:
            GetNameByObjectHandleL(aMessage);
            break;

        case ESendObject:
            ret = SendObject(aMessage, complete);
            break;

        case ECancelSendObject:
            CancelSendObject();
            break;

        case EObjectReceivedNotify:
            ret = ObjectReceivedNotify(aMessage, complete);
            break;

        case ECancelObjectReceivedNotify:
            CancelObjectReceivedNotify();
            break;

        case EPtpFolder:
            ret = PtpFolder(aMessage);
            break;

        default:
            __FLOG(_L8("!!!Error: ---Wrong param from client!!!"));
            aMessage.Panic(KPTPClientPanicCategory, EBadRequest);
            break;
        }
        
    if (complete)
        {
        aMessage.Complete(ret);
        }
    __FLOG_VA((_L8("<<<PtpSession::DispatchMessageL ret=%d"), ret));
    }

// --------------------------------------------------------------------------
// CPtpSession::CancelIsDpsPrinter()
// Cancels Asynchronous request IsDpsPrinter
// --------------------------------------------------------------------------
//
void CPtpSession::CancelIsDpsPrinter()
    {
    __FLOG(_L8(">>>CPtpSession::CancelIsDpsPrinter"));
    if (iDpsPrinterMsg.Handle())
        {
        iDpsPrinterMsg.Complete(KErrCancel);
        iServerP->Printer()->DeRegisterDpsPrinterNotify(this);
        iTimerP->Cancel();
        iServerP->CancelNotifyOnMtpSessionOpen(this);
        } 
    __FLOG(_L8("<<<CPtpSession::CancelIsDpsPrinter"));
    }
    
// --------------------------------------------------------------------------
// CPtpSession::CancelSendObject()
// Cancel Asynchronous request send Object
// --------------------------------------------------------------------------
//
void CPtpSession::CancelSendObject()
    {
    __FLOG(_L8(">>>CancelSendObject"));
    if (iSendObjectMsg.Handle())
        {
        iServerP->Printer()->CancelSendDpsFile();
        iSendObjectMsg.Complete(KErrCancel);
        iTimerP->Cancel();
        }
    __FLOG(_L8("<<<CancelSendObject"));    
    }
    
// --------------------------------------------------------------------------
// CPtpSession::CancelObjectReceivedNotify()
// Deregisters for Object received notification
// --------------------------------------------------------------------------
//
void CPtpSession::CancelObjectReceivedNotify()
    {
    __FLOG(_L8(">>>CancelObjectReceivedNotify"));       
    if (iObjectReceivedNotifyMsg.Handle())
        {
        __FLOG_VA((_L8("the handle is 0x%x"), iObjectReceivedNotifyMsg.Handle()));
        iServerP->Printer()->MsgHandlerP()->DeRegisterReceiveObjectNotify();
        iObjectReceivedNotifyMsg.Complete(KErrCancel);                    
        }
    __FLOG(_L8("<<<CancelObjectReceivedNotifiy"));
    }
    
// --------------------------------------------------------------------------
// CPtpSession::IsDpsPrinter()
// --------------------------------------------------------------------------
//    
TInt CPtpSession::IsDpsPrinter(const RMessage2& aMessage, TBool& aComplete)
    {
    __FLOG(_L8(">>>IsDpsPrinter"));
    TInt ret=EPrinterNotAvailable;
    if (!iDpsPrinterMsg.Handle()) // not already pending
        {
        switch (iServerP->Printer()->Status())
            {   
            case CMTPPictBridgePrinter::ENotConnected:
                iDpsPrinterMsg = aMessage;    
                iServerP->Printer()->RegisterDpsPrinterNotify(this);
                aComplete = EFalse;
                if(iServerP->MtpSessionOpen())
                    {
                    if (!iTimerP->IsActive()) 
                        {
                        iTimerP->After(KDiscoveryTime);
                        }
                    }
                else
                    {
                    iServerP->NotifyOnMtpSessionOpen(this);
                    }                    
                // we do not set ret since the  value does not really matter, we will be waiting for the discovery to complete
                __FLOG(_L8(" waiting"));
                break;
                
            case CMTPPictBridgePrinter::EConnected:
                ret=EPrinterAvailable;
                aComplete = ETrue;
                __FLOG(_L8(" connected"));
                break;

            case CMTPPictBridgePrinter::ENotPrinter:
                ret=EPrinterNotAvailable;
                aComplete = ETrue;
                __FLOG(_L8(" not connected"));
                break;

            default:
                break;                
            }
        }
    else
        {
        __FLOG(_L8("!!!Error: client message error, duplicated IsDpsPrinter"));                        
        aMessage.Panic(KPTPClientPanicCategory, ERequestPending);
        aComplete = EFalse;
        }
    __FLOG(_L8("<<<IsDpsPrinter"));
    return ret;
    }

// --------------------------------------------------------------------------
// start the timer for printer detection, since we have now session open and 
// we are ready to communicate wioth the host
// --------------------------------------------------------------------------
void CPtpSession::MTPSessionOpened()
    {
    __FLOG(_L8(">>>CPtpSession::MTPSessionOpened"));
    if (!iTimerP->IsActive() && iDpsPrinterMsg.Handle()) 
        {
        __FLOG(_L8("   CPtpSession::MTPSessionOpened timer started"));
        iTimerP->After(KDiscoveryTime);
        }        
    __FLOG(_L8("<<<CPtpSession::MTPSessionOpened"));
    }
    
// --------------------------------------------------------------------------
// CPtpSession::GetObjectHandleByNameL()
// 
// --------------------------------------------------------------------------
//
void CPtpSession::GetObjectHandleByNameL(const RMessage2& aMessage)
    {
    __FLOG(_L8(">>>CPtpSession::GetObjectHandleByNameL"));
    TFileName file;
    User::LeaveIfError(aMessage.Read(0, file));
    __FLOG_VA((_L16("--the file is %S"), &file));
    TUint32 handle=0;
    TRAP_IGNORE(iServerP->GetObjectHandleByNameL(file, handle));
    TPckgBuf<TUint32> handlePckg(handle);
    aMessage.WriteL(1, handlePckg);     
    __FLOG_VA((_L16("<<<CPtpSession::GetObjectHandleByNameL handle=%d"), handle));
    }
    
// --------------------------------------------------------------------------
// CPtpSession::GetNameByObjectHandle()

// --------------------------------------------------------------------------
//
void CPtpSession::GetNameByObjectHandleL(const RMessage2& aMessage)
    {
    __FLOG(_L8(">>>CPtpSession::GetNameByObjectHandle"));               
    TUint32 handle = 0;
    TPckgBuf<TUint32> pckgHandle(handle);
    User::LeaveIfError(aMessage.Read(1, pckgHandle));
    TFileName file; 
    handle = pckgHandle();
    __FLOG_VA((_L8("---handle is %x"), handle));
    TRAP_IGNORE(iServerP->GetObjectNameByHandleL(file, handle));
    __FLOG_VA((_L16("the file is %S"), &file));
    aMessage.WriteL(0, file);
    
    __FLOG(_L8("<<<CPtpSession::GetNameByObjectHandle"));               
    }
              
// --------------------------------------------------------------------------
// CPtpSession::SendObject()
// Asynch. request send Object
// --------------------------------------------------------------------------
//
TInt CPtpSession::SendObject(const RMessage2& aMessage, TBool& aComplete)
    {
    __FLOG(_L8(">>>CPtpSession::SendObject"));                      
    TInt err(KErrNone);
    
    if (iSendObjectMsg.Handle())
        {
        __FLOG(_L8("!!!!Error: client message error, duplicated SendObject"));
        aMessage.Panic(KPTPClientPanicCategory, ERequestPending);
        aComplete = EFalse;
        return KErrNone;
        }
    else
        {
        // Parameter add is depracated. We do not send Object added and we do not keep ther DPS object permanently in
        // our system.
        //
        // Sending ObjectAdded Event is not mandatory ( See Appendix B page 78. DPS Usage of USB and PTP in CIPA DC-001-2003)

        TBool timeout = aMessage.Int2();    
        __FLOG_VA((_L8("---timeout is %d"), timeout));    
        TFileName file; 
        err = aMessage.Read(0, file);
        if (err == KErrNone)
            {
            __FLOG_VA((_L16("---the file is %S"), &file));
            TInt size = aMessage.Int3();
            __FLOG_VA((_L8("---the file size is %d"), size)); // size is deprecated and not used anymore
            TRAP(err, iServerP->Printer()->SendDpsFileL(file, timeout, size));
            if (err == KErrNone)
                {
                iSendObjectMsg = aMessage;
                aComplete = EFalse;    
                }
            }
        if ((EFalse != timeout) && !iTimerP->IsActive())
            {
            iTimerP->After(KSendTimeout);
            }
        __FLOG_VA((_L8("<<<CPtpSession::SendObject err=%d"), err));
        return err;    
        }    
    }             

// --------------------------------------------------------------------------
// CPtpSession::ObjectReceivedNotify()
// 
// --------------------------------------------------------------------------
//   
TInt CPtpSession::ObjectReceivedNotify(const RMessage2& aMessage, 
                                       TBool& aComplete)
    {
    __FLOG(_L8(">>>CPtpSession::ObjectReceivedNotify"));                        
    if (iObjectReceivedNotifyMsg.Handle())
        {
        __FLOG(_L8("!!!!Error: client message error, duplicated ObjectReceivedNotify"));
        aMessage.Panic(KPTPClientPanicCategory, ERequestPending);
        aComplete = EFalse;
        return KErrNone;
        }
    else
        {
        //TBool del = aMessage.Int2();
        //__FLOG_VA((_L8("---the del is %d"), del));    

        TBuf<KFileExtLength> ext; 
        TInt err = aMessage.Read(0, ext);
        if (err == KErrNone)
            {
            __FLOG_VA((_L16("the extension is %S"), &ext));
            
            iObjectReceivedNotifyMsg = aMessage; 
            aComplete = EFalse;
            iServerP->Printer()->MsgHandlerP()->RegisterReceiveObjectNotify(ext);
            }
        __FLOG(_L8("<<<CPtpSession::ObjectReceivedNotify"));                            
        return err;
        }
    }
    
// --------------------------------------------------------------------------
// CPtpSession::PtpFolder()
// Returns PtpFolder Name and Path
// --------------------------------------------------------------------------
//    
TInt CPtpSession::PtpFolder(const RMessage2& aMessage)
    {
    __FLOG(_L8(">>>CPtpSession::PtpFolder"));
    TInt err(KErrNotReady);
    TFileName folder = iServerP->PtpFolder();
    err = aMessage.Write(0,folder);
    __FLOG_VA((_L16("<<<CPtpSession::PtpFolder %S err(%d)"), &folder, err));
    return err;
    }
    
// --------------------------------------------------------------------------
// CPtpSession::SendObjectCompleted()
// 
// --------------------------------------------------------------------------
//    
void CPtpSession::SendObjectCompleted(TInt aStatus)
    {
    __FLOG_VA((_L16(">>>CPtpSession::SendObjectCompleted status(%d)"), aStatus));
    if (iSendObjectMsg.Handle())
        {
        iSendObjectMsg.Complete(aStatus);    
        iTimerP->Cancel();
        }
    else
        {
        __FLOG(_L8("!!!Warning: CPtpSession::SendObjectCompleted: UNEXPECTED CALL"));
        }
    __FLOG(_L8("<<<CPtpSession::SendObjectCompleted")); 
    }

// --------------------------------------------------------------------------
// CPtpSession::IsDpsPrinterCompleted()
// 
// --------------------------------------------------------------------------
//
void CPtpSession::IsDpsPrinterCompleted(TDpsPrinterState aState)
    {
    __FLOG(_L8(">>>CPtpSession::IsDpsPrinterCompleted"));    
    if (iDpsPrinterMsg.Handle())
        {
        iDpsPrinterMsg.Complete(aState);
        iTimerP->Cancel();
        iServerP->Printer()->DeRegisterDpsPrinterNotify(this);
        }
    else
        {
        __FLOG(_L8("!!!Warning: CPtpSession::IsDpsPrinterCompleted: UNEXPECTED CALL"));
        }
    __FLOG(_L8("<<<CPtpSession::IsDpsPrinterCompleted"));    
    }

// --------------------------------------------------------------------------
// CPtpSession::ReceivedObjectCompleted()
// 
// --------------------------------------------------------------------------
//
void CPtpSession::ReceivedObjectCompleted(TDes& aFile)
    {
    __FLOG(_L8(">>>CPtpSession::ReceivedObjectCompleted"));
    if (iObjectReceivedNotifyMsg.Handle())
        {
        TInt err = iObjectReceivedNotifyMsg.Write(1, aFile);
        iReceivedFile.Copy(aFile);
        __FLOG_VA((_L8("***CPtpSession::ReceivedObjectCompleted err=%d"), err));
        iObjectReceivedNotifyMsg.Complete(err);
        }
    else
        {
        __FLOG(_L8("!!!Warning: Strange Happened!!!"));    
        }
    __FLOG(_L8("<<<CPtpSession::ReceivedObjectCompleted"));
    }

// --------------------------------------------------------------------------
// 
// Cancels outstanding request
// --------------------------------------------------------------------------
//
void CPtpSession::CancelOutstandingRequest()
    {
    __FLOG(_L8(">>>CPtpSession::CancelOutstandingRequest"));
    if (iSendObjectMsg.Handle())
        {
        iSendObjectMsg.Complete(KErrCancel);
        }
    if (iObjectReceivedNotifyMsg.Handle())
        {
        iObjectReceivedNotifyMsg.Complete(KErrCancel);
        }
    if (iDpsPrinterMsg.Handle())
        {
        iDpsPrinterMsg.Complete(KErrCancel);
        }
    __FLOG(_L8("<<<CPtpSession::CancelOutstandingRequest"));    
    }
// --------------------------------------------------------------------------
// 
// --------------------------------------------------------------------------
//
CPtpServer* CPtpSession::ServerP() const
    {
    return iServerP;    
    }