ImagePrint/ImagePrintEngine/DeviceProtocols/pictbridge2/src/cpbprintingdevice.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:30:38 +0100
branchRCL_3
changeset 28 d59c248c9d36
parent 0 d11fb78c4374
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201031 Kit: 201035

/*
* Copyright (c) 2002-2007 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:  Contains the CPBPrintingDevice class definition.
*
*/


#include <e32std.h>
#include <pictbridge.h>
#include <s32file.h>
#include <f32file.h>

#include "cpbprintingdevice.h"
#include "printcapabilitycodes.h"
#include "printmessagecodes.h"
#include "imageprint.h"
#include "cpbconnect.h"
#include "clog.h"

//  CONSTANTS
namespace
	{
	const TInt KPBVersionMajor = 0;
	const TInt KPBVersionMinor = 0;
	const TInt KPBVersionBuild = 1;
	}

const TInt KConfigLength = 16;
const TInt KMaxRetry = 10;
_LIT( KConfigInfoFile, "config.DPS");


MProtPrintingDevice* CPBPrintingDevice::NewL()
	{
	return new (ELeave) CPBPrintingDevice();
	}


CPBPrintingDevice::CPBPrintingDevice() :
CActive( CActive::EPriorityStandard ), iState(EPBUninitialized), iDisconnectPrinter(EFalse)
	{
	CActiveScheduler::Add(this);
	}

void CPBPrintingDevice::ConstructL(const TDesC& /*aDLLPath*/)
	{
	LOG("CPBPrintingDevice::ConstructL begin");	
	
	iDpsEngine = CDpsEngine::GetEngineL();		
	iConnect = CPBConnect::NewL( *iDpsEngine, *this );
	
    iCongFileName = HBufC::NewL( iDpsEngine->DpsFolder().Length() + KConfigLength );
    TInt k = iDpsEngine->DpsFolder().Length() + KConfigLength;
    iCongFileName->Des().Copy( iDpsEngine->DpsFolder() );
    iCongFileName->Des().Append( KConfigInfoFile );
 	
	iCancelRetry = 0;

    // for Cert software to indicate that printing state and idle state 
    iPrintingStateComplete = 0;
	
	iUserSelectedPaperSize = EDpsPaperSizeDefault;
	iNewJobOK = ETrue;
	
	LOG("CPBPrintingDevice::ConstructL end");
	}


CPBPrintingDevice::~CPBPrintingDevice()
	{
	LOG("CPBPrintingDevice::~CPBPrintingDevice begin");
	Cancel();
	delete iConnect;
	delete iCongFileName;
	if ( iDpsEngine )
		{
		iDpsEngine->Delete();
		}
	REComSession::DestroyedImplementation( iDtor_ID_Key );
	LOG("CPBPrintingDevice::~CPBPrintingDevice end");
	}


TVersion CPBPrintingDevice::Version()
	{
	return TVersion(KPBVersionMajor, KPBVersionMinor, KPBVersionBuild);
	}

TUint CPBPrintingDevice::SupportedProtocols()
	{
	return KImagePrint_PrinterProtocol_PictBridge;
	}

void CPBPrintingDevice::StartDiscoveryL(MProtDiscoveryObserver& aObserver, TUint aProtocol)
	{		
	LOG1("CPBPrintingDevice::StartDiscoveryL aProtocol: %d", aProtocol);
	iDiscoveryObserver = &aObserver;
		
	if ( IsActive() )
		{
		LOG1("CPBPrintingDevice::StartDiscoveryL invalid state %d, cannot start discovery", iState);
		iDiscoveryObserver->DiscoveryStatusL( EDiscoveryFinished, KErrInvalidSequence, 0 );
		return;
		}
				
	if ( !( aProtocol & KImagePrint_PrinterProtocol_PictBridge ) )
		{
		LOG("CPBPrintingDevice::StartDiscoveryL NO protocol match, ending discovery...");
		iDiscoveryObserver->DiscoveryStatusL( EDiscoveryFinished, KErrNotSupported, 0 );
		return;
		}

	if ( !iPrinterConnected )
		{
		LOG("CPBPrintingDevice::StartDiscoveryL no printer connected, ending discovery");
		iDiscoveryObserver->DiscoveryStatusL( EDiscoveryFinished, KErrNone, 0 );
		return;
		}


	// clear capability map
	iCapToDps.Close();

    iConfigS.iReqParam.Reset();
    iDpsEngine->GetDpsConfigL( iConfigS.iReqParam );
    iDpsEngine->DoDpsRequestL( &iConfigS, iStatus );
	iState = EPBDiscovery;
    SetActive();
	LOG("CPBPrintingDevice::StartDiscoveryL setting state to Discovery");
		
	LOG("CPBPrintingDevice::StartDiscoveryL end");
	}


TInt CPBPrintingDevice::RemoveCachedDeviceL( TInt aDeviceID )
	{
  	LOG1("CPBPrintingDevice::RemoveCachedDeviceL, aDeviceID: %d", aDeviceID);
  	return KErrInvalidData;
	}

void CPBPrintingDevice::CancelDiscovery( TBool aDoCallBack )
	{
  	LOG2("CPBPrintingDevice::CancelDiscovery aDoCallBack %d, iState %d", aDoCallBack, iState );  	
  	if ( iState == EPBDiscovery )
	  	{
	  	Cancel();
		if ( aDoCallBack && iDiscoveryObserver )
			{
			//We're not interested if the call back leaves
			TRAP_IGNORE( iDiscoveryObserver->DiscoveryStatusL( EDiscoveryCancelling, KErrNone, 0 ) );
			//We're not interested if the call back leaves
			TRAP_IGNORE( iDiscoveryObserver->DiscoveryStatusL( EDiscoveryFinished, KErrNone, 0 ) );
			}
		iState = EPBUninitialized;
	  	}  	
	LOG("CPBPrintingDevice::CancelDiscovery end");
	}


TInt CPBPrintingDevice::CreatePrintJobL(TInt aDeviceID, RPointerArray<TDesC>& aImages, MProtPrintEventObserver& aObserver)
	{
  	LOG2("CPBPrintingDevice::CreatePrintJobL begin, deviceid %d imagecount %d", aDeviceID, aImages.Count());
	iPrintEventObserver = &aObserver;		

	if ( aDeviceID != 0 )
		{
		LOG("CPBPrintingDevice::CreatePrintJobL invalid device");
		return KErrArgument;
		}
		
	if ( iState != EPBReady && iState != EPBJobReady )
		{
		LOG1("CPBPrintingDevice::CreatePrintJobL invalid state %d", iState);
		if(iDisconnectPrinter) // If printer is disconnected then return KErrDisconnected.
			return KErrDisconnected;
		else 
			return KErrInvalidSequence;
		}
		
    iStart.iReqParam.Reset();                                                                               
		
	// these must be appended in same order as PBJobSettingIndex
	
    TDpsArgsInt arg;    
    arg.iElement = EDpsArgPaperSize;
    arg.iContent = EDpsPaperSizeDefault;
    iStart.iReqParam.iJobConfig.Append(arg);

    arg.iElement = EDpsArgQuality;
    arg.iContent = EDpsPrintQualityDefault;
    iStart.iReqParam.iJobConfig.Append(arg);
				
    arg.iElement = EDpsArgLayout;
    arg.iContent = EDpsLayoutDefault;
    iStart.iReqParam.iJobConfig.Append(arg);
                        	
	for ( TInt i = 0; i < aImages.Count(); ++i )
		{
	    TDpsPrintInfo info;
	    info.Reset();
	    const TDesC& image = *aImages[i];
	    LOG1("CPBPrintingDevice::CreatePrintJobL image %S", &image);
	    info.iFile.Copy( image );
	    iStart.iReqParam.iPrintInfo.Append( info );
		}

	LOG("CPBPrintingDevice::CreatePrintJobL setting state to JobReady");
	iState = EPBJobReady;
	
	LOG("CPBPrintingDevice::CreatePrintJobL end");
	return KErrNone;
	}

void CPBPrintingDevice::SubmitPrintJobL()
	{
	LOG("CPBPrintingDevice::SubmitPrintJobL begin");

	// Checking that job is ready and printer has send aStatus.iRepParam.iNewJobOk
	// Check PrinterNotify function
	if ( iState == EPBJobReady && iNewJobOK )
		{
		iDpsEngine->DoDpsRequestL( &iStart, iStatus );
		iState = EPBSubmittingJob;
		SetActive();
		LOG("CPBPrintingDevice::SubmitPrintJobL setting state to SubmittingJob");
		}
	else
		{
		LOG1("CPBPrintingDevice::SubmitPrintJobL invalid state %d", iState);
		if( iDisconnectPrinter )
		    {
		    User::Leave( KErrDisconnected );
		    }
		else
		    {
		  	// Job or printer not ready, inform user
		  	if( iPrintEventObserver )
		  	    {
    		  	LOG("CPBPrintingDevice::SubmitPrintJobL sending EPbStatusErrorReasonHardwarePrinterBusy message to UI");
    		  	iPrintEventObserver->PrinterStatusEvent( EPbStatusErrorReasonHardwarePrinterBusy );
		  	    }
		    else
		        {
       			LOG1("CPBPrintingDevice::SubmitPrintJobL invalid state %d", iState);
       			User::Leave( KErrInvalidSequence );
		        }
		    }
		
		}
	
	LOG("CPBPrintingDevice::SubmitPrintJobL end");
	}

TInt CPBPrintingDevice::CancelPrintJob()
	{
	LOG("CPBPrintingDevice::CancelPrintJob begin");

    if( iCancelRetry > KMaxRetry )
        {
        return KErrInUse;
        }
	
	if ( iState == EPBSubmittingJob || iState == EPBPrinting || iState == EPBCancelling )
		{
        Cancel();
        iAbort.iReqParam.iAbortStyle = EDpsAbortStyleImmediately;
        TRAPD( err, iDpsEngine->DoDpsRequestL( &iAbort, iStatus ) );
        if ( err != KErrNone )
	        {
	        LOG1("CPBPrintingDevice::CancelPrintJob FATAL, DoDpsRequestL failed %d, setting state to Uninitialized", err);
	       	iState = EPBUninitialized;
	       	return KErrGeneral;
	        }        
        iState = EPBCancelling;
        SetActive();
        LOG("CPBPrintingDevice::CancelPrintJob setting state to Cancelling");
		}	
	else if ( iState == EPBJobReady )
		{
		LOG("CPBPrintingDevice::CancelPrintJob state is JobReady so doing nothing");
		return KErrNone;
		}
	else 
		{
		LOG1("CPBPrintingDevice::CancelPrintJob invalid state %d", iState);
		return KErrInvalidSequence;
		}
		
	LOG("CPBPrintingDevice::CancelPrintJob end");
	return KErrNone;
	}

TInt CPBPrintingDevice::ContinuePrintJobL()
	{
	LOG1("CPBPrintingDevice::ContinuePrintJobL returns with: %d", KErrNotSupported);
	return KErrNotSupported;
	}

TInt CPBPrintingDevice::GetNumPrintPages()
	{
	LOG("CPBPrintingDevice::GetNumPrintPages begin");
	
	if ( iState != EPBJobReady && iState != EPBSubmittingJob && iState != EPBPrinting )
		{
		LOG1("CPBPrintingDevice::GetNumPrintPages invalid state %d, returning 0", iState);
		return 0;
		}

	TInt imagesPerPage = 1;
	TDpsArgsInt& config = iStart.iReqParam.iJobConfig[EPBSettingLayout];
	switch ( config.iContent )
		{        
        case EDpsLayout2Up:
			imagesPerPage = 2;
        	break;        
        case EDpsLayout4Up:
			imagesPerPage = 4;
        	break;        
        case EDpsLayout6Up:
			imagesPerPage = 6;
        	break;        
        case EDpsLayout9Up:
			imagesPerPage = 9;
        	break;        	        			        		        						
		default:
			break;
		}

	TInt numPrintPages = (iStart.iReqParam.iPrintInfo.Count() + imagesPerPage - 1) / imagesPerPage;
	LOG1("CPBPrintingDevice::GetNumPrintPages end, result %d", numPrintPages);
	return numPrintPages;
	}

TInt CPBPrintingDevice::GetPrintJobStatus()
	{
	LOG1("CPBPrintingDevice::GetPrintJobStatus returns with: %d", KErrNotSupported);
	return KErrNotSupported;
	}

TInt CPBPrintingDevice::GetPrinterStatus(TInt /*aDeviceID*/)
	{
	LOG1("CPBPrintingDevice::GetPrinterStatus returns with: %d", KErrNotSupported);
	return KErrNotSupported;
	}

TInt CPBPrintingDevice::GetDeviceCapabilityIDsL(TInt aDeviceID, RArray<TInt>& aCapabilityIDs)
	{
	LOG1("CPBPrintingDevice::GetDeviceCapabilityIDsL begins with aDeviceID: %d", aDeviceID);

	if ( aDeviceID != 0 )
		{
		LOG("CPBPrintingDevice::GetDeviceCapabilityL invalid device");
		return KErrArgument;
		}		
					
	if ( iState != EPBReady && iState != EPBJobReady )
		{
		LOG1("CPBPrintingDevice::GetDeviceCapabilityL invalid state %d", iState);
		return KErrInvalidSequence;
		}	
	
	aCapabilityIDs.Append( EPrintCapabLayout );
	aCapabilityIDs.Append( EPrintCapabQuality );
	aCapabilityIDs.Append( EPrintCapabPaperSize );
		
	LOG("CPBPrintingDevice::GetDeviceCapabilityIDsL end");
	return KErrNone;
	}

TInt CPBPrintingDevice::GetDeviceCapabilityL(TInt aDeviceID, TInt aCapabilityID, TPrintCapability& aCapability)
	{		
	LOG2("CPBPrintingDevice::GetDeviceCapabilityL begins with aDeviceID %d, aCapabilityID %d", aDeviceID, aCapabilityID);

	if ( aDeviceID != 0 )
		{
		LOG("CPBPrintingDevice::GetDeviceCapabilityL invalid device");
		return KErrArgument;
		}		
					
	if ( iState != EPBReady && iState != EPBJobReady )
		{
		LOG1("CPBPrintingDevice::GetDeviceCapabilityL invalid state %d", iState);
		return KErrInvalidSequence;
		}	

	if ( aCapabilityID == EPrintCapabPaperSize )
		{
		// paper sizes
		iCap.iRepParam.Reset();
		iCap.iReqParam.iCap = EDpsArgPaperSizes;
		iDpsEngine->DoDpsRequestL(&iCap, iStatus);
		SetActive();
		iWait.Start();
		HandlePapersizesResponseL( aCapability );
		
		if ( !aCapability.iEnumCount )
			{
			LOG("CPBPrintingDevice::GetDeviceCapabilityL paper sizes not supported, set to default");
	    	aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabPaperSizeAuto;
	    	iCapToDps.InsertL( EPrintCapabPaperSizeAuto, EDpsPaperSizeDefault );
			}				    		
	    }
	else if ( aCapabilityID == EPrintCapabQuality )
		{
		// qualities
		LOG("CPBPrintingDevice::GetDeviceCapabilityL qualities");
		iCap.iRepParam.Reset();
		iCap.iReqParam.iCap = EDpsArgQualities;
		iDpsEngine->DoDpsRequestL( &iCap, iStatus );
		SetActive();
		iWait.Start();
		HandleQualitiesResponseL( aCapability );
		}
	else if ( aCapabilityID == EPrintCapabLayout )
		{			
		// layouts		
		LOG("CPBPrintingDevice::GetDeviceCapabilityL layouts");
		iCap.iRepParam.Reset();
		iCap.iReqParam.iCap = EDpsArgLayouts;
		iCap.iReqParam.iAttribute = iUserSelectedPaperSize;
		LOG("CPBPrintingDevice::GetDeviceCapabilityL layouts dodpsrequest");		
		iDpsEngine->DoDpsRequestL(&iCap, iStatus);
		SetActive();
		LOG("CPBPrintingDevice::GetDeviceCapabilityL layouts wait");
		iWait.Start();
		HandleLayoutsResponseL( aCapability );
		}
	else
		{
		LOG("CPBPrintingDevice::GetDeviceCapabilityL invalid capabilityID");
		return KErrArgument;
		}	    
		
	LOG1("CPBPrintingDevice::GetDeviceCapabilityL iCapToDps count %d", iCapToDps.Count());

	LOG("CPBPrintingDevice::GetDeviceCapabilityL end");
	return KErrNone;
	}

TInt CPBPrintingDevice::GetJobSetting(TInt aCapabilityID, TInt& aValue)
	{
	LOG1("CPBPrintingDevice::GetJobSetting begin, aCapabilityID %d", aCapabilityID);

	TInt err = KErrNone;		
	if ( iState != EPBJobReady )
		{
		LOG1("CPBPrintingDevice::GetJobSetting invalid state %d", iState);
		err = KErrInvalidSequence;
		}	
	else if ( aCapabilityID == EPrintCapabPaperSize )
		{
		err = GetPapersizeJobSetting( aValue );
	    }
	else if ( aCapabilityID == EPrintCapabQuality )
		{
		err = GetQualityJobSetting( aValue );
		}
	else if ( aCapabilityID == EPrintCapabLayout )
		{
		err = GetLayoutJobSetting( aValue );
		}
	else
		{
		LOG("CPBPrintingDevice::GetJobSetting invalid capabilityID");
		err = KErrArgument;
		}	    
		
	LOG2("CPBPrintingDevice::GetJobSetting end, return code %d value %d", err, aValue);
	return err;
	}

TInt CPBPrintingDevice::SetJobSettingL(TInt aCapabilityID, TInt aValue, TInt& aAffectedCapability)
	{
	LOG2("CPBPrintingDevice::SetJobSettingL begin, aCapabilityID %d aValue %d", aCapabilityID, aValue);

	aAffectedCapability = aCapabilityID;
	
	RArray<TDpsArgsInt>& config = iStart.iReqParam.iJobConfig;
	TInt err = KErrNone;
	if ( iState != EPBJobReady )
		{
		LOG1("CPBPrintingDevice::SetJobSettingL invalid state %d", iState);
		err = KErrInvalidSequence;
		}
	else if ( aCapabilityID == EPrintCapabPaperSize )
		{
		TInt* dpsValue = iCapToDps.Find( aValue );
		if ( dpsValue )
		    {
			config[EPBSettingPaperSize].iContent = *dpsValue;
		
			// for CertSW: needs layouts for particular paper sizes
			iUserSelectedPaperSize = config[EPBSettingPaperSize].iContent;
		    }
		else
			{
			LOG("CPBPrintingDevice::SetJobSettingL invalid value");
			err = KErrInvalidData;
			}
	    }
	else if ( aCapabilityID == EPrintCapabQuality )
		{
		TInt* dpsValue = iCapToDps.Find( aValue );
		if ( dpsValue )
			{
			config[EPBSettingQuality].iContent = *dpsValue;
			}
		else
			{
			LOG("CPBPrintingDevice::SetJobSettingL invalid value");
			err = KErrInvalidData;
			}
		}
	else if ( aCapabilityID == EPrintCapabLayout )
		{
		TInt* dpsValue = iCapToDps.Find( aValue );
		if ( dpsValue )
			{
			config[EPBSettingLayout].iContent = *dpsValue;
			}
		else
			{
			LOG("CPBPrintingDevice::SetJobSettingL invalid value");
			err = KErrInvalidData;
			}
		}
	else
		{
		LOG("CPBPrintingDevice::SetJobSettingL invalid capabilityID");
		err = KErrArgument;
		}	    
		
	LOG1("CPBPrintingDevice::SetJobSettingL end, return code %d", err);
	return err;	
	}


TInt CPBPrintingDevice::GetNumPreviewPages()
	{
	LOG1("CPBPrintingDevice::GetNumPreviewPages ends with: %d", 1);
	return 1;
	}

TInt CPBPrintingDevice::GetJobTemplateIconL( TInt /*aTemplateID*/, TInt& /*aFsBitmapHandle*/ )
	{
	return KErrNone;
	}


TInt CPBPrintingDevice::CreatePreviewImage(TInt /*aPageNumber*/)
	{
	return KErrNotSupported;
	}

void CPBPrintingDevice::RegisterIdleObserver( MProtIdleObserver *aObserver )
	{
	iIdleObserver = aObserver;
	}

void CPBPrintingDevice::DoCancel()
	{
	iDpsEngine->CancelDpsRequest();
	if ( iWait.IsStarted() )
		{
		LOG("CPBPritingDevice::DoCancel() calling iWait.AsyncStop()");
		iWait.AsyncStop();
		}	
	}

void CPBPrintingDevice::RunL()
	{
	LOG2("CPBPrintingDevice::RunL begin, status %d state %d", iStatus.Int(), iState);
		
   	if ( iWait.IsStarted() )
    	{
    	LOG("CPBPrintingDevice::RunL calling iWait.AsyncStop() and returning");
    	iWait.AsyncStop();
    	return;
    	}
    
    if ( iStatus.Int() == KErrNone ) // everything ok
        {
    	switch( iState )
    		{
    		case EPBDiscovery:
    			{    	   			
    			iPrinter.iPrinterID = 0;
                iPrinter.iProtocol = KImagePrint_PrinterProtocol_PictBridge;
    	        iPrinter.iProperties = 0;

    			if( iConfigS.iResult.iMajorCode == EDpsResultOk ) 
    			    {
    			    iPrinter.iVendor = TPrinter::EVendorNone;
    			
    			    HBufC* buf = HBufC::NewLC( iConfigS.iRepParam.iProductName.Length() );
    			    TPtr p = buf->Des();
    			    p.Copy( iConfigS.iRepParam.iProductName );
    			    if ( p.Length() > 84 )
    				    {
    				    TPtrC p2 = p.Left( 84 );
    				    iPrinter.iDisplayName = p2;
    				    }
    			    else
    				    {
    				    iPrinter.iDisplayName = p;
    				    }
    			    
    			    CleanupStack::PopAndDestroy( buf );
    			    LOG1("CPBPrinterDevice::RunL config displayname %S", &iPrinter.iDisplayName);
    			    
    			    // Config info have to be saved in file, because it can retrieved only once
    			    // when cable is plugged in the device
    			    SaveConfigInfoL();
    			    }
    			
                if( iConfigS.iResult.iMajorCode == EDpsResultNotExecuted )
                    {
                    // Read info from file
                    ReadConfigInfoL();
    			    }

    		    iDiscoveryObserver->FoundDeviceL( iPrinter );
    		    iDiscoveryObserver->DiscoveryStatusL( EDiscoveryFinished, KErrNone, 0 );
    		    iState = EPBReady;

    			// Close Dps request to avoid -14 error
    			iDpsEngine->CancelDpsRequest();
    		    iDpsEngine->CancelDpsEventNotify();

    			LOG("CPBPrintingDevice::RunL setting state to Ready");
    			break;
    			}    		
    		case EPBSubmittingJob:
    			LOG2("CPBPrintingDevice::RunL submittingjob result major 0x%x minor 0x%x", iStart.iResult.iMajorCode, iStart.iResult.iMinorCode);
    			if ( iStart.iResult.iMajorCode == EDpsResultOk )
    				{
    				LOG("CPBPrintingDevice::RunL setting state to Printing");
    				iState = EPBPrinting;
    				
    				// for Cert software remove dialog from UI 
    				iPrintEventObserver->PrintJobProgressEvent( EDone, 100, ENoMessage );
    				}
    			else
    				{
    				LOG("CPBPrintingDevice::RunL error occurred, setting state to JobReady");
    				iState = EPBJobReady;
    				if ( iPrintEventObserver )
    					{
    					TPrintMessageCodes err = EPbStatusErrorReasonNoReason;
    					if ( iStart.iResult.iMajorCode == EDpsResultNotSupported &&
    						 iStart.iResult.iMinorCode == EDpsResultMissingParam )
    						{
    						// image file is probably missing
    						err = EPbFileNotFound;
    						}						
    					iPrintEventObserver->PrinterStatusEvent( err );
    					iPrintEventObserver->PrintJobProgressEvent( EDone, 100, ECancelling );
    					}
    				}
    			break;    			
    		case EPBCancelling:			
    			LOG2("CPBPrintingDevice::RunL cancelling result major 0x%x minor 0x%x", iAbort.iResult.iMajorCode, iAbort.iResult.iMinorCode);
    			
    			if( iAbort.iResult.iMajorCode == EDpsResultNotExecuted )
    			    {
    			    iCancelRetry++;
    			    CancelPrintJob();
    			    }
    			
    			if( iAbort.iResult.iMajorCode == EDpsResultOk )
    			    {
    			    if ( iPrintEventObserver )
    				    {
    				    iPrintEventObserver->PrintJobProgressEvent( EDone, 100, ECancelling );
    				    }

    			        LOG("CPBPrintingDevice::RunL setting state to JobReady");
    			        iState = EPBJobReady;
    			        iCancelRetry = 0;
    			        }
    			break;    		
    		default:
    			LOG1("CPBPrintingDevice::RunL unrecognized state %d", iState);
    			break;
		}	
    } 
	else // iStatus != KErrNone -> Handle error here 
	    {
	    switch( iStatus.Int()  )
    		{
    		case KErrTimedOut:
    			LOG( "CPBPrintingDevice::RunL KErrTimedOut" );
				if ( iPrintEventObserver )
			        {
				    LOG("CPBPrintingDevice::Timeout, finish printing...");
				    iPrintEventObserver->PrintJobProgressEvent( EDone, 100, ECancelling );
				    }
    			break;
    		default:
    		    // Handle error here.
    		    LOG2( "CPBPrintingDevice::RunL error, status %d state %d", iStatus.Int(), iState );
    		    break;
    		}
	    }
	
	LOG("CPBPrintingDevice::RunL end");
	}

TInt CPBPrintingDevice::RunError( TInt aError )
	{
	LOG1("CPBPrintingDevice::RunError code %d", aError);
	if ( iWait.IsStarted() )
		{		
		LOG("CPBPrintingDevice::RunError calling iWait.AsyncStop()");
		iWait.AsyncStop();
		}
	return KErrNone;
	}

		
void CPBPrintingDevice::SetNumsOfCopiesL( const RArray<TInt>& aNumsOfCopies, TInt& aErr )
	{
	LOG("CPBPrintingDevice::SetNumsOfCopiesL begin");
		
	if ( iState != EPBJobReady )
		{
		LOG1("CPBPrintingDevice::SetNumsOfCopiesL invalid state %d", iState);
		aErr = KErrInvalidSequence;
		}		
	else if ( aNumsOfCopies.Count() != iStart.iReqParam.iPrintInfo.Count() )
		{
		LOG2("CPBPrintingDevice::SetNumsOfCopiesL counts don't match, %d %d", aNumsOfCopies.Count(), iStart.iReqParam.iPrintInfo.Count());
		aErr = KErrInvalidData;
		}
	else
		{	
		for ( TInt i = 0; i < aNumsOfCopies.Count(); ++i )
			{
			iStart.iReqParam.iPrintInfo[i].iCopies = aNumsOfCopies[i];
			}			
		aErr = KErrNone;
		}
	
	LOG("CPBPrintingDevice::SetNumsOfCopiesL end");
	}


void CPBPrintingDevice::ConnectionNotifyL( TInt aStatus )
	{
	LOG2("CPBPrintingDevice::ConnectionNotifyL begin, status %d iState %d", aStatus, iState);
    switch ( aStatus )
        {        
        case CDpsEngine::ENotConnected:
        	LOG("CPBPrintingDevice::ConnectionNotify not connected");
        	break;
        case CDpsEngine::EPrinterConnected:
        	LOG("CPBPrintingDevice::ConnectionNotifyL printer connected");
        	iPrinterConnected = ETrue;
        	iDisconnectPrinter = EFalse;
	        if ( iIdleObserver )
		        {
		        LOG("CPBPrintingDevice::ConnectionNotifyL informing idle observer about connect");
		        TEvent event = { KImagePrint_PrinterProtocol_PictBridge, ENotSpecified, EConnect };
		        iIdleObserver->StatusEvent( event, KErrConnected, ENoMessage );
	    	    }
        	break;        
        case CDpsEngine::EPrinterDisconnected:
					iPrinterConnected = EFalse;
					iDisconnectPrinter = ETrue;
        	if ( iState != EPBUninitialized )
	        	{
	        	Cancel();
	        	if ( iState == EPBDiscovery )
		        	{
		        			//We're not interested if the call back leaves
							TRAP_IGNORE( iDiscoveryObserver->DiscoveryStatusL( EDiscoveryFinished, KErrNone, 0 ) );
		        	}		        	
					LOG("CPBPrintingDevice::ConnectionNotifyL printer disconnected, setting state to Uninitialized");
	        	iState = EPBUninitialized;
	        	}
	        if ( iIdleObserver )
		        {
		        LOG("CPBPrintingDevice::ConnectionNotifyL informing idle observer about disconnect");
		        TEvent event = { KImagePrint_PrinterProtocol_PictBridge, ENotSpecified, EDisconnect };
		        iIdleObserver->StatusEvent( event, KErrDisconnected, ENoMessage );
	    	    }
	        break;	        
        case CDpsEngine::EOtherConnected:
        	LOG("CPBPrintingDevice::ConnectionNotify other connected");
        	break;        
        case CDpsEngine::EWrongPrintModeConnected: 
            LOG("CPBPrintingDevice::ConnectionNotify Other personality");
            iPrinterConnected = ETrue;
            iDisconnectPrinter = EFalse;
	        if ( iIdleObserver )
		        {
		        LOG("CPBPrintingDevice::ConnectionNotifyL informing idle observer about connect");
		        TEvent event = { KImagePrint_PrinterProtocol_PictBridge, ENotSpecified, EConnect };
		        iIdleObserver->StatusEvent( event, KErrConnected, ENoMessage );
	    	    }
        	break;                        
        default:
        	LOG1("CPBPrintingDevice::ConnectionNotifyL unrecognized status %d", aStatus);
	        break;
        }
	LOG("CPBPrintingDevice::ConnectionNotifyL end");
	}

void CPBPrintingDevice::JobNotify( const TDpsGetJobStatus& aStatus )
	{		
	LOG1("CPBPrintingDevice::JobNotify begin, state %d", iState);
    LOG2("CPBPrintingDevice::JobNotify progress %d, prtPID %d", aStatus.iRepParam.iProgress, aStatus.iRepParam.iPrtPID);
    LOG1("CPBPrintingDevice::JobNotify copyID %d", aStatus.iRepParam.iCopyID);
    LOG2("CPBPrintingDevice::JobNotify filepath %S, images printed %d", &aStatus.iRepParam.iFilePath, aStatus.iRepParam.iImagesPrinted);        
    
    if ( iPrintEventObserver )
	    {
	    iPrintEventObserver->PrintJobProgressEvent( EActive, aStatus.iRepParam.iProgress, ENoMessage );
	    }
    
	LOG("CPBPrintingDevice::JobNotify end");
	}

void CPBPrintingDevice::PrinterNotify( const TDpsGetPrinterStatus& aStatus )
	{		
	LOG1("CPBPrintingDevice::PrinterNotify begin, state %d", iState );
    LOG2("CPBPrintingDevice::PrinterNotify service status 0x%x, job status 0x%x", aStatus.iRepParam.iPrintStatus, aStatus.iRepParam.iJobStatus);
    LOG2("CPBPrintingDevice::PrinterNotify error status 0x%x, job end reason 0x%x", aStatus.iRepParam.iErrorStatus, aStatus.iRepParam.iJobEndReason.iMajor);
    LOG1("CPBPrintingDevice::PrinterNotify aStatus.iRepParam.iNewJobOk 0x%x,", aStatus.iRepParam.iNewJobOk);
    
    // New job checking that job is ok and device status is ok.
    iNewJobOK = aStatus.iRepParam.iNewJobOk;
    
    TPBProtocolState oldState = iState;
    if ( iState == EPBPrinting )
		{
		// for SWCert software to indicate that printing state has executed
		iPrintingStateComplete = 1;
		
		if ( aStatus.iRepParam.iJobStatus == EDpsJobStatusEndedOk )
			{
			LOG("CPBPrintingDevice::PrinterNotify job finished successfully, setting state to JobReady");
			if ( iPrintEventObserver )
				{
				LOG("CPBPrintingDevice::PrinterNotify job finished iPrintEventObserver->PrintJobProgressEvent( EDone, 100, ENoMessage );");
				iPrintEventObserver->PrintJobProgressEvent( EDone, 100, ENoMessage );
				}
			iState = EPBJobReady;
			}
		else if ( aStatus.iRepParam.iJobStatus != EDpsJobStatusNotEnded )
			{
			LOG("CPBPrintingDevice::PrinterNotify job aborted, setting state to JobReady");
			if ( iPrintEventObserver )
				{
				iPrintEventObserver->PrintJobProgressEvent( EDone, 100, ECancelling );
				}
			iState = EPBJobReady;
			}
		}

    if ( iState == EPBJobReady )
        { 
        // for Cert software: CertSW doesn't give any indication about aStatus.iRepParam.iJobStatus 
        // it only indicate printer state. We have to send message to UI to remove generig progress bar.
        if ( aStatus.iRepParam.iPrintStatus == EDpsPrintServiceStatusIdle && iPrintingStateComplete )
            {
			// for Cert software to indicate that idle state has executed
			iPrintingStateComplete = 0;
			
			if ( iPrintEventObserver )
				{
			    LOG("CPBPrintingDevice::PrinterNotify job finished iPrintEventObserver->PrintJobProgressEvent( EDone, 100, ENoMessage );");
			    
			    // for Cert software remove dialog from UI 
			    iPrintEventObserver->PrintJobProgressEvent( EDone, 100, ENoMessage );
				}
            }
        }

    if ( !iPrintEventObserver )
	    {
	    LOG("CPBPrintingDevice::PrinterNotify no event observer, returning");
	    return;
	    }
    
	TPrintMessageCodes err = DpsJobError( aStatus.iRepParam.iJobEndReason );
    if ( err == ENoMessage && aStatus.iRepParam.iErrorStatus == EDpsErrorStatusFatal )
		{
		// Show fatal error
		err = EPbStatusErrorReasonHardwareFatal;
		}	        
    
    if ( err == ENoMessage && aStatus.iRepParam.iErrorStatus == EDpsErrorStatusWarning )
		{
		// Show warning
		err = EPbStatusErrorReasonWarning;
		}	        

    if ( err != ENoMessage )
	    {
	    if ( oldState == EPBPrinting )
		    {
		    LOG1("CPBPrintingDevice::PrinterNotify calling PrintJobErrorEvent with code %d", err);
		    iPrintEventObserver->PrintJobErrorEvent( err );
			}
		else
			{
			LOG1("CPBPrintingDevice::PrinterNotify calling PrinterStatusEvent with code %d", err);
			iPrintEventObserver->PrinterStatusEvent( err );
			}
	    }
    				
	LOG("CPBPrintingDevice::PrinterNotify end");
	}

void CPBPrintingDevice::HandlePapersizesResponseL( TPrintCapability& aCapability )
	{
    LOG2("CPBPrintingDevice::HandlePapersizesResponseL result major 0x%x minor 0x%x", iCap.iResult.iMajorCode, iCap.iResult.iMinorCode);
	LOG2("CPBPrintingDevice::HandlePapersizesResponseL cap 0x%x count %d", iCap.iRepParam.iCap, iCap.iRepParam.iContent.Count());	
	
	aCapability.iCapabilityID = EPrintCapabPaperSize;
	aCapability.iType = TPrintCapability::Int;
	aCapability.iDefaultValue = EPrintCapabPaperSizeAuto;
	aCapability.iEnumCount = 0;
	
	if ( iCap.iResult.iMajorCode == EDpsResultOk )
		{		
	    for ( TInt i = 0; i < iCap.iRepParam.iContent.Count() && aCapability.iEnumCount < KMaxEnumAmount; ++i )
	        {
	        LOG1("CPBPrintingDevice::HandlePapersizesResponseL content 0x%x", iCap.iRepParam.iContent[i]);
	        switch ( iCap.iRepParam.iContent[i] )
		        {
		        case EDpsPaperSizeDefault:
		        	aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabPaperSizeAuto;
		        	iCapToDps.InsertL( EPrintCapabPaperSizeAuto, EDpsPaperSizeDefault );
		        	break;		        	
	        	case EDpsPaperSizeLetter:
	        		aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabPaperSizeLetter;
	        		iCapToDps.InsertL( EPrintCapabPaperSizeLetter, EDpsPaperSizeLetter );
	        		break;	        		
	        	case EDpsPaperSizeA4:
	        		aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabPaperSizeA4;
	        		iCapToDps.InsertL( EPrintCapabPaperSizeA4, EDpsPaperSizeA4 );
	        		break;	        		
	        	case EDpsPaperSizeA6:
	        		aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabPaperSizeA6;
	        		iCapToDps.InsertL( EPrintCapabPaperSizeA6, EDpsPaperSizeA6 );
	        		break;	        		
	        	case EDpsPaperSize4x6:
	        		aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabPaperSize4x6;
	        		iCapToDps.InsertL( EPrintCapabPaperSize4x6, EDpsPaperSize4x6 );
	        		break;
	        	case EDpsPaperSize2L:
	        		aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabPaperSize5x7;
	        		iCapToDps.InsertL( EPrintCapabPaperSize5x7, EDpsPaperSize2L );
	        		break;	        			        		
	        	default:
	        		break;
	    	    }
	        }
	    }
	}

	
void CPBPrintingDevice::HandleQualitiesResponseL( TPrintCapability& aCapability )
	{
    LOG2("CPBPrintingDevice::HandleQualitiesResponseL result major 0x%x minor 0x%x", iCap.iResult.iMajorCode, iCap.iResult.iMinorCode);
	LOG2("CPBPrintingDevice::HandleQualitiesResponseL cap 0x%x count %d", iCap.iRepParam.iCap, iCap.iRepParam.iContent.Count());	
	
	aCapability.iCapabilityID = EPrintCapabQuality;
	aCapability.iType = TPrintCapability::Int;
	aCapability.iDefaultValue = EPrintCapabQualityDefault;
	aCapability.iEnumCount = 0;

	if ( iCap.iResult.iMajorCode == EDpsResultOk )
		{		
	    for ( TInt i = 0; i < iCap.iRepParam.iContent.Count() && aCapability.iEnumCount < KMaxEnumAmount; ++i )
	        {
	        LOG1("CPBPrintingDevice::HandleQualitiesResponseL content 0x%x", iCap.iRepParam.iContent[i]);
	        switch ( iCap.iRepParam.iContent[i] )
		        {
		        case EDpsPrintQualityDefault:
		        	aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabQualityDefault;
		        	iCapToDps.InsertL( EPrintCapabQualityDefault, EDpsPrintQualityDefault );
		        	break;
		        case EDpsPrintQualityNormal:
		        	aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabQualityNormal;
		        	iCapToDps.InsertL( EPrintCapabQualityNormal, EDpsPrintQualityNormal );
		        	break;
		        case EDpsPrintQualityDraft:
		        	aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabQualityDraft;
		        	iCapToDps.InsertL( EPrintCapabQualityDraft, EDpsPrintQualityDraft );
		        	break;
		        case EDpsPrintQualityFine:
		        	aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabQualityFine;
		        	iCapToDps.InsertL( EPrintCapabQualityFine, EDpsPrintQualityFine );
		        	break;		        	
		        default:
		        	break;
		        }
		    }
		}
	if ( !aCapability.iEnumCount )
		{
		LOG("CPBPrintingDevice::HandleQualitiesResponseL not supported, set to default");
    	aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabQualityDefault;
    	iCapToDps.InsertL( EPrintCapabQualityDefault, EDpsPrintQualityDefault );
		}
	}

void CPBPrintingDevice::HandleLayoutsResponseL( TPrintCapability& aCapability )
	{		
    LOG2("CPBPrintingDevice::HandleLayoutsResponseL result major 0x%x minor 0x%x", iCap.iResult.iMajorCode, iCap.iResult.iMinorCode);
	LOG2("CPBPrintingDevice::HandleLayoutsResponseL cap 0x%x count %d", iCap.iRepParam.iCap, iCap.iRepParam.iContent.Count());
	
	aCapability.iCapabilityID = EPrintCapabLayout;
	aCapability.iType = TPrintCapability::Int;
	aCapability.iDefaultValue = EPrintCapabLayout1Up;
	aCapability.iEnumCount = 0;

	if ( iCap.iResult.iMajorCode == EDpsResultOk )
		{		
	    for ( TInt i = 0; i < iCap.iRepParam.iContent.Count() && aCapability.iEnumCount < KMaxEnumAmount; ++i )
	        {
	        LOG1("CPBPrintingDevice::HandleLayoutsResponseL content 0x%x", iCap.iRepParam.iContent[i]);
	        switch ( iCap.iRepParam.iContent[i] )
		        {
		        case EDpsLayout1Up:
		        	aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabLayout1Up;
		        	iCapToDps.InsertL( EPrintCapabLayout1Up, EDpsLayout1Up );
		        	break;		        
		        case EDpsLayout2Up:
		        	aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabLayout2Up;
		        	iCapToDps.InsertL( EPrintCapabLayout2Up, EDpsLayout2Up );
		        	break;		        
		        case EDpsLayout4Up:
		        	aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabLayout4Up;
		        	iCapToDps.InsertL( EPrintCapabLayout4Up, EDpsLayout4Up );
		        	break;		        
		        case EDpsLayout6Up:
		        	aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabLayout6Up;
		        	iCapToDps.InsertL( EPrintCapabLayout6Up, EDpsLayout6Up );
		        	break;		        
		        case EDpsLayout9Up:
		        	aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabLayout9Up;
		        	iCapToDps.InsertL( EPrintCapabLayout9Up, EDpsLayout9Up );
		        	break;		        	
		        // do not support this EDpsLayoutBorderless, set default value
		        case EDpsLayoutBorderless:
		        	aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabLayout1UpBorderless;
		        	iCapToDps.InsertL( EPrintCapabLayout1UpBorderless, EDpsLayoutDefault );
		        	break;		        		        	
		        default:
		        	break;
		        }			
		    }
		}
	if ( !aCapability.iEnumCount )
		{
		LOG("CPBPrintingDevice::HandleLayoutsResponseL not supported, set to default");
    	aCapability.iEnumCodes[aCapability.iEnumCount++] = EPrintCapabLayout1Up;
    	iCapToDps.InsertL( EPrintCapabLayout1Up, EDpsLayoutDefault );
		}
	}

TInt CPBPrintingDevice::GetPapersizeJobSetting( TInt& aValue )
	{
	LOG("CPBPrintingDevice::GetPapersizeJobSetting begin");

	TDpsArgsInt& paper = iStart.iReqParam.iJobConfig[EPBSettingPaperSize];
	switch ( paper.iContent )
		{
		case EDpsPaperSizeDefault:
			aValue = EPrintCapabPaperSizeAuto;
			return KErrNone;		
    	case EDpsPaperSizeLetter:
			aValue = EPrintCapabPaperSizeLetter;
			return KErrNone;    		
    	case EDpsPaperSizeA4:
			aValue = EPrintCapabPaperSizeA4;
			return KErrNone;    		
    	case EDpsPaperSizeA6:
			aValue = EPrintCapabPaperSizeA6;
			return KErrNone;    		
    	case EDpsPaperSize4x6:
			aValue = EPrintCapabPaperSize4x6;
			return KErrNone;			
    	case EDpsPaperSize2L:
    		aValue = EPrintCapabPaperSize5x7;
    		return KErrNone;
		default:
			LOG1("CPBPrintingDevice::GetPapersizeJobSetting unknown %x", paper.iContent);
			break;
		}				

	LOG("CPBPrintingDevice::GetPapersizeJobSetting end");
	return KErrInvalidData;
	}

TInt CPBPrintingDevice::GetQualityJobSetting( TInt& aValue )
	{
	LOG("CPBPrintingDevice::GetQualityJobSetting begin");

	TDpsArgsInt& config = iStart.iReqParam.iJobConfig[EPBSettingQuality];
	switch ( config.iContent )
		{
        case EDpsPrintQualityDefault:
			aValue = EPrintCapabQualityDefault;
			return KErrNone;
        case EDpsPrintQualityNormal:
			aValue = EPrintCapabQualityNormal;
			return KErrNone;
        case EDpsPrintQualityDraft:
			aValue = EPrintCapabQualityDraft;
			return KErrNone;
        case EDpsPrintQualityFine:
			aValue = EPrintCapabQualityFine;
			return KErrNone;			
		default:
			LOG1("CPBPrintingDevice::GetQualityJobSetting unknown %x", config.iContent);
			break;
		}				

	LOG("CPBPrintingDevice::GetQualityJobSetting end");
	return KErrInvalidData;
	}

TInt CPBPrintingDevice::GetLayoutJobSetting( TInt& aValue )
	{
	LOG("CPBPrintingDevice::GetLayoutJobSetting begin");

	TDpsArgsInt& config = iStart.iReqParam.iJobConfig[EPBSettingLayout];
	switch ( config.iContent )
		{
		case EDpsLayoutDefault:
            // Not supported default value is EPrintCapabLayout1UpBorderless
            // because other protocols use it too
            // EPrintCapabLayout1UpBorderless is mapped with EDpsLayoutDefault
            aValue = EPrintCapabLayout1UpBorderless; 
        case EDpsLayout1Up:
			aValue = EPrintCapabLayout1Up;
        	return KErrNone;        
        case EDpsLayout2Up:
			aValue = EPrintCapabLayout2Up;
        	return KErrNone;        
        case EDpsLayout4Up:
			aValue = EPrintCapabLayout4Up;
        	return KErrNone;        
        case EDpsLayout6Up:
			aValue = EPrintCapabLayout6Up;
        	return KErrNone;        
        case EDpsLayout9Up:
			aValue = EPrintCapabLayout9Up;
        	return KErrNone;        	
        case EDpsLayoutBorderless:
			aValue = EPrintCapabLayout1UpBorderless;
        	return KErrNone;        			        		        						
		default:
			LOG1("CPBPrintingDevice::GetLayoutJobSetting unknown %x", config.iContent);
			break;
		}

	LOG("CPBPrintingDevice::GetLayoutJobSetting end");
	return KErrInvalidData;
	}

TPrintMessageCodes CPBPrintingDevice::DpsJobError( const TDpsJobEndReason& aReason )
	{
	TPrintMessageCodes err = ENoMessage;
    switch ( aReason.iMajor )
        {
        case EDpsJobErrorPaper:
            LOG1("CPBPrintingDevice::DpsJobError paper error 0x%x", aReason.iPaperMinor);
            HandlePaperError( aReason, err );
	        break;        
        case EDpsJobErrorInk:
            LOG1("CPBPrintingDevice::DpsJobError ink error 0x%x", aReason.iInkMinor);
            HandleInkError( aReason, err );
    	    break;        
        case EDpsJobErrorHardware:
            LOG1("CPBPrintingDevice::DpsJobError hardware error 0x%x", aReason.iHardMinor);
            HandleHwError( aReason, err );
	        break;        
        case EDpsJobErrorFile:
            LOG1("CPBPrintingDevice::DpsJobError file error 0x%x", aReason.iFileMinor);
            HandleFileError( aReason, err );   
    	    break;        
        default:
        	break;
        }
    return err;
	}
void CPBPrintingDevice::HandlePaperError ( const TDpsJobEndReason& aReason, TPrintMessageCodes& aErr )
	{
	  switch ( aReason.iPaperMinor )
        {
	    case EDpsPaperEmpty:
	    	aErr = EPbStatusErrorReasonPaperEmpty;
	    	break;	    	
	    case EDpsPaperLoad:
	    	aErr = EPbStatusErrorReasonPaperLoad;
	    	break;	    	
	    case EDpsPaperEject:
	    	aErr = EPbStatusErrorReasonPaperEject;
	    	break;	    	
	    case EDpsPaperMedia:
	    	aErr = EPbStatusErrorReasonPaperMedia;
	    	break;	    	
	    case EDpsPaperJam:
	    	aErr = EPbStatusErrorReasonPaperJam;
	    	break;	    
	    case EDpsPaperNearlyEmpty:
	    	aErr = EPbStatusErrorReasonPaperNearlyEmpty;
	    	break;	    
	    case EDpsPaperTypeSizeNoMatch:
	    	aErr = EPbStatusErrorReasonPaperCombination;
	    	break;        	
        default:
        	aErr = EPbStatusErrorReasonPaper;
        	break;
        }
	}

void CPBPrintingDevice::HandleInkError ( const TDpsJobEndReason& aReason, TPrintMessageCodes& aErr )
	{
	 switch ( aReason.iInkMinor )
        {
        case EDpsInkEmpty:
        	aErr = EPbStatusErrorReasonInkEmpty;
        	break;        	
	    case EDpsInkLow:
	    	aErr = EPbStatusErrorReasonInkLow;
	    	break;	    	
		case EDpsInkWaste:
			aErr = EPbStatusErrorReasonInkWaste;
			break;
        default:
        	aErr = EPbStatusErrorReasonInk;
        	break;        	
        }
	}

void CPBPrintingDevice::HandleHwError ( const TDpsJobEndReason& aReason, TPrintMessageCodes& aErr )
	{
	 switch ( aReason.iHardMinor )
        {
        case EDpsHardFatal:
        	aErr = EPbStatusErrorReasonHardwareFatal;
        	break;        	
	    case EDpsHardServiceCall:
	    	aErr = EPbStatusErrorReasonHardwareServiceCall;
	    	break;	    	
	    case EDpsHardNotAvailable:
	    	aErr = EPbStatusErrorReasonHardwarePrinterUnavailable;
	    	break;	    	
	    case EDpsHardBusy:
	    	aErr = EPbStatusErrorReasonHardwarePrinterBusy;
	    	break;	    	
	    case EDpsHardLever:
	    	aErr = EPbStatusErrorReasonHardwareLever;
	    	break;	    	
	    case EDpsHardCoverOpen:
	    	aErr = EPbStatusErrorReasonHardwareCoverOpen;
	    	break;	    	
	    case EDpsHardNoMarkingHead:
	    	aErr = EPbStatusErrorReasonHardwareNoMarkingAgent;
	    	break;	    	
	    case EDpsHardInkCoverOpen:
	    	aErr = EPbStatusErrorReasonHardwareCoverOpen;
	    	break;	    	
	    case EDpsHardNoInkCartridge:
	    	aErr = EPbStatusErrorReasonHardwareNoInkCartridge;
	    	break;
        default:
        	aErr = EPbStatusErrorReasonHardware;
        	break;
        }                        
	}

void CPBPrintingDevice::HandleFileError ( const TDpsJobEndReason& aReason, TPrintMessageCodes& aErr )
	{
	 switch ( aReason.iFileMinor )
        {
        case EDpsFilePrintInfo:
        	aErr = EPbStatusErrorReasonFilePrintInfo;
        	break;        	
        case EDpsFileDecode:
        	aErr = EPbStatusErrorReasonFileFileDecode;
        	break;        	
        default:
        	aErr = EPbStatusErrorReasonFile;
        	break;
        }
	}

TBool CPBPrintingDevice::HasCapability( TPrintCapability& aCapability, TPrintCapabilityOptions aOption )
	{
	for ( TInt i = 0; i < aCapability.iEnumCount; ++i )
		{
		if ( aCapability.iEnumCodes[i] == aOption )
    		{
    		return ETrue;
    		}
		}
	return EFalse;
	}

void CPBPrintingDevice::SaveConfigInfoL()
	{
	LOG("CPBPrintingDevice::SaveConfigInfoL begin");
	
	RFs rFs;
    RFile file;

   	User::LeaveIfError( rFs.Connect() );
    CleanupClosePushL( rFs );
    
    User::LeaveIfError( file.Replace( rFs, iCongFileName->Des() ,EFileWrite ) ); // create the file for writing

	RFileWriteStream stream( file );
    CleanupClosePushL( stream );
    
    ExternalizeL( stream );

	CleanupStack::PopAndDestroy( &stream );
	CleanupStack::PopAndDestroy( &rFs );
	
	LOG("CPBPrintingDevice::SaveConfigInfoL end");
	}

void CPBPrintingDevice::ExternalizeL( RWriteStream& aStream ) const
	{
	LOG("CPBPrintingDevice::ExternalizeL begin");
	
	aStream << iPrinter.iDisplayName;
	aStream.WriteUint32L( iPrinter.iVendor ); 
	aStream.CommitL();
	
	LOG("CPBPrintingDevice::ExternalizeL end");
	}

void CPBPrintingDevice::ReadConfigInfoL()
    {
    LOG("CPBPrintingDevice::ReadConfigInfoL begin");
    
    RFs rFs;
    RFile file;

	User::LeaveIfError( rFs.Connect() );
    CleanupClosePushL( rFs );
    
    User::LeaveIfError( file.Open( rFs, iCongFileName->Des() ,EFileRead ) ); 
    
	RFileReadStream readStream( file );
    CleanupClosePushL( readStream );

    readStream >> iPrinter.iDisplayName;
    iPrinter.iVendor = readStream.ReadUint32L(); 
	
 	CleanupStack::PopAndDestroy( &readStream );
	CleanupStack::PopAndDestroy( &rFs );
   
    LOG("CPBPrintingDevice::ReadConfigInfoL end");
    }

//  End of File