// Copyright (c) 2006-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 <ctsy/tflogger.h>

#include "CMmCustomTsy.h"
#include "CMmPacketTsy.h"
#include "Cmmpacketcontexttsy.h"
#include "Cmmpacketcontextlist.h"

// ======== MEMBER FUNCTIONS ========

CMmPacketTsy::CMmPacketTsy()
    {
    }

void CMmPacketTsy::ConstructL()
    {
#ifdef REQHANDLE_TIMER   
    // Create req handle store
    iTsyReqHandleStore = CMmTsyReqHandleStore::NewL( iMmCustomTsy,
        iMmPhone, EMultimodePacketMaxNumOfRequests, iPacketReqHandles );
#else
    // Create req handle store
    iTsyReqHandleStore = CMmTsyReqHandleStore::NewL( 
        EMultimodePacketMaxNumOfRequests, iPacketReqHandles );
#endif // REQHANDLE_TIMER

    iGprsInformationPckg = NULL;
    }

CMmPacketTsy* CMmPacketTsy::NewL(
    CMmCustomTsy* aMmCustomTsy, 
    CMmPhoneTsy* aMmPhone )
    {
TFLOGSTRING( "CustomTSY: CMmPacketTsy::NewL" );
    CMmPacketTsy* mmPacketTsy = new ( ELeave ) CMmPacketTsy();
    CleanupStack::PushL( mmPacketTsy );
    mmPacketTsy->iMmCustomTsy = aMmCustomTsy;
    mmPacketTsy->iMmPhone = aMmPhone;
    mmPacketTsy->ConstructL();
    CleanupStack::Pop();

    return mmPacketTsy;
    }

CMmPacketTsy::~CMmPacketTsy()
    {
TFLOGSTRING( "CustomTSY: CMmPacketTsy::~CMmPacketTsy" );
    delete iTsyReqHandleStore;
    }

// ---------------------------------------------------------------------------
// CMmPacketTsy::Init
// Initialisation method that is called from ETel Server.
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
void CMmPacketTsy::Init()
    {
    }

// ---------------------------------------------------------------------------
// CMmPacketTsy::RegisterNotification
// RegisterNotification is called when the ETel Server recognises that this 
// notification is being posted for the first time on this subsession object.
// It enables the TSY to "turn on" any regular notification messages that it 
// may receive from DOS.
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
TInt CMmPacketTsy::RegisterNotification(
    const TInt aIpc )
    {
    TInt ret( KErrNotSupported );

    if ( ECustomNotifyEGprsInfoChange == aIpc )
        {
        ret = KErrNone;
        }

    return ret;
    }

// ---------------------------------------------------------------------------
// CMmPacketTsy::DeregisterNotification
// DeregisterNotification is called when the ETel Server recognises that this
// notification will not be posted again because the last client to have
// a handle on this sub-session object has just closed the handle. It
// enables the TSY to "turn off" any regular notification messages that
// it may receive from DOS.
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
TInt CMmPacketTsy::DeregisterNotification( 
    const TInt aIpc )
    {
    TInt ret( KErrNotSupported );

    if ( ECustomNotifyEGprsInfoChange == aIpc )
        {
        ret = KErrNone;
        }

    return ret;
    }

// ---------------------------------------------------------------------------
// CMmPacketTsy::SupportingIPC
// Use switch to check if given IPC is supported
// in case IPC supported
//     return ETrue
// in case IPC not supported
//     return EFalse
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
TBool CMmPacketTsy::SupportingIPC( 
    TInt aIpc )
    {
    TBool ret( EFalse );
    switch ( aIpc )
        {
        // from CustomApi
        case ECustomNotifyEGprsInfoChange:
        case ECustomGetEGprsInfo:
        case ECustomSetAlwaysOnMode:
            ret = ETrue;
            break;
        default:
            ret = EFalse;
            break;
        }

    return ret;
    }

// ---------------------------------------------------------------------------
// CMmPacketTsy::DoExtFuncL
// Dispatches extension function requests.
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
TInt CMmPacketTsy::DoExtFuncL(
    const TTsyReqHandle aTsyReqHandle, 
    const TInt aIpc, 
    const TDataPackage& aPackage )
    {
TFLOGSTRING3( "CustomTSY: CMmPacketTsy::DoExtFuncL - IPC:%d Handle:%d", aIpc, aTsyReqHandle );
    TInt ret( KErrNotSupported );

    switch ( aIpc )
        {
        case ECustomNotifyEGprsInfoChange:
            ret = NotifyEGprsInfoChange( aTsyReqHandle, aPackage.Des1n() );
            break;
        case ECustomGetEGprsInfo:
            ret = GetEGprsInfo( aTsyReqHandle, aPackage.Des1n() );
            break;
        case ECustomSetAlwaysOnMode:
TFLOGSTRING( "TSY:CMmPacketTsy::DoExtFuncL ECustomSetAlwaysOnMode");
            ret = SetAlwaysOnL( aTsyReqHandle,
               ( REINTERPRET_CAST( RMmCustomAPI::TSetAlwaysOnMode*,
                              					aPackage.Ptr1() ) ) );
        default:
            break;
        }

    return ret;
    }

// ---------------------------------------------------------------------------
// CMmPacketTsy::ReqModeL
// Returns request mode for given IPC.
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
CTelObject::TReqMode CMmPacketTsy::ReqModeL( 
    const TInt aIpc )
    {
    CTelObject::TReqMode reqMode( 0 );

    switch ( aIpc )
        {
        // Etel Server takes care of flow control. Several simultaneous
        // requests allowed.

        // All disabled
        // TSYs wishing to implement their own buffering algorithm will place
        // all requests in this category. 

        // Get methods that do not use DOS and return immediately.
        // Flow control not required.

        // Methods that can probably take a long time and cannot therefore be
        // flow controlled. Solution: All these methods must check req handle
        // table before handling the request. If the request table indicates
        // that same method has been called and has not been completed, the
        // method should return KErrServerBusy.
        case ECustomGetEGprsInfo:
        case ECustomSetAlwaysOnMode:
            break;

        // KReqModeMultipleCompletionEnabled | ReqModePostImmediately
        // Requests that notify a client about a change of state.
        // Since these requests do not require the issuing of any modem 
        // commands, they do not have to obey flow control.
        // The TSY never gets more than one of these outstanding.
        case ECustomNotifyEGprsInfoChange:
            reqMode = KReqModeMultipleCompletionEnabled |
                KReqModeRePostImmediately;
            break;
        // KReqModeFlowControlObeyed
        // Commands that change the state of the phone, e.g. clearing the AoC 
        // counter, are commands that the TSY should only deal with one at 
        // a time.

        //Other cases
            //reqMode = KReqModeFlowControlObeyed;
            //break;

        default:
            User::Leave( KErrNotSupported );
            break;
        }

    return reqMode;
    }

// ---------------------------------------------------------------------------
// CMmPacketTsy::NumberOfSlotsL
// Returns number of slots to be used for given IPC.
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
TInt CMmPacketTsy::NumberOfSlotsL(
    const TInt aIpc )
    {
    TInt numberOfSlots( KMmCustomDefaultSlots );

    switch ( aIpc )
        {
        // from CustomApi
        case ECustomNotifyEGprsInfoChange: 
        case ECustomGetEGprsInfo:
        case ECustomSetAlwaysOnMode:
            break;
        default:
            // Unknown or invalid IPC
            User::Leave( KErrNotSupported );
            break;
        }

    return numberOfSlots;
    }
    
// ---------------------------------------------------------------------------
// CMmPacketTsy::CancelService
// This function is called to cancel the outstanding request.
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
TInt CMmPacketTsy::CancelService(
    const TInt aIpc, 
    const TTsyReqHandle aTsyReqHandle )
    {
TFLOGSTRING2( "CustomTSY: CMmPacketTsy::CancelService IPC:%d", aIpc );
    TInt ret( KErrNone );

    // Req handle type
    TPacketRequestType reqHandletype( 
        EMultimodePacketContextReqHandleUnknown );

    switch ( aIpc )
        {
        // TSY has started a request and it is not possible to then cancel 
        // this request. The best thing for the TSY to do in this case is to 
        // proceed as though the Cancel never happened. The server's call to
        // the TSY cancel function will return synchronously. The TSY then 
        // continues to wait for the original acknowledgement and when it 
        // receives it, the TSY will complete the original request.
        case ECustomGetEGprsInfo:
            break;
            
        case ECustomSetAlwaysOnMode:
        	 CancelSetAlwaysOn ( aTsyReqHandle );
            break;

        // Notification Cancels, no special requirements.
        case ECustomNotifyEGprsInfoChange:
            iGprsInformationPckg = NULL;
            reqHandletype = EMultimodePacketContextNotifyEGprsInfoChange;
            break;
        // Cancel methods that are not supported
        // Default case
        default:
            ret = KErrNotSupported;
            break;
        }

    if ( reqHandletype != EMultimodePacketContextReqHandleUnknown )
        {
        // Reset tsy request handle
        iTsyReqHandleStore->ResetTsyReqHandle( reqHandletype );

        // Complete request to client with KErrCancel
        ReqCompleted( aTsyReqHandle, KErrCancel );
        }

    return ret;
    }

// ---------------------------------------------------------------------------
// CMmPacketTsy::ReqCompleted
// Overloads CTelObject::ReqCompleted for logging purposes.
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
void CMmPacketTsy::ReqCompleted(
    const TTsyReqHandle aTsyReqHandle, 
    const TInt aError )
    {
TFLOGSTRING3( "CustomTSY: CMmPacketTsy::ReqCompleted Handle:%d Error:%d", aTsyReqHandle, aError );
    iMmCustomTsy->ReqCompleted( aTsyReqHandle, aError );
    }

// ---------------------------------------------------------------------------
// CMmPacketTsy::NotifyEGprsInfoChange
// Request notification when EGPRS support changes.
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
TInt CMmPacketTsy::NotifyEGprsInfoChange(
    const TTsyReqHandle aTsyReqHandle, 
    TDes8* aGprsInformation )
    {
TFLOGSTRING( "CustomTSY: CMmPacketTsy::NotifyEGprsInfoChange" );

    RMmCustomAPI::TGprsInformation temp;
	RMmCustomAPI::TGprsInformationPckg tempPckg(temp);

	TInt expectedLength = tempPckg.MaxLength();
	TInt paramLength = aGprsInformation->MaxLength();
	
	TInt ret = KErrArgument;
	if (expectedLength == paramLength)
		{
	    // Store pointer of Gprs information package
	    iGprsInformationPckg = 
	        ( RMmCustomAPI::TGprsInformationPckg* ) aGprsInformation;

	    // Store request handle
	    iTsyReqHandleStore->SetTsyReqHandle( 
	        EMultimodePacketContextNotifyEGprsInfoChange, aTsyReqHandle );
		ret = KErrNone;
		}
			
    return ret;
    }

// ---------------------------------------------------------------------------
// CMmPacketTsy::GetEGprsInfo
// Informs client about EGPRS information.
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
TInt CMmPacketTsy::GetEGprsInfo(
    const TTsyReqHandle aTsyReqHandle, 
    TDes8* aGprsInformation )
    {
TFLOGSTRING( "CustomTSY: CMmPacketTsy::GetEGprsInfo" );

    RMmCustomAPI::TGprsInformation temp;
	RMmCustomAPI::TGprsInformationPckg tempPckg(temp);

	TInt expectedLength = tempPckg.MaxLength();
	TInt paramLength = aGprsInformation->MaxLength();
	
	TInt ret = KErrArgument;
	if (expectedLength == paramLength && iMmCustomTsy)
		{			
	    RMmCustomAPI::TGprsInformationPckg* gprsInformationPckg =
	        ( RMmCustomAPI::TGprsInformationPckg* ) aGprsInformation;

	    // Unpack gprsInformationPckg
	    RMmCustomAPI::TGprsInformation& gprsInformation = 
	        ( *gprsInformationPckg )();
	    TBool edgeGprsSupportInCell;
	 
	    if ( !iMmCustomTsy->Phone() 
	    	   || !iMmCustomTsy->Phone()->PacketDataSession() 
	    	   || !iMmCustomTsy->Phone()->PacketDataSession()->
	    		    ActivePacketServiceExtension() )
	        {
	        // returns false if EGPRS support failed
	       	edgeGprsSupportInCell = EFalse;
	        }
	    else
	        {
	        // returns information if EGPRS connection supported
	    	edgeGprsSupportInCell = iMmCustomTsy->Phone()->PacketDataSession()->
	            ActivePacketServiceExtension()->EGprsSupportInCell();
	        }

	    // if gprsSupportInCell is ETrue -> cell is supporting EGPRS connection 
	    if ( edgeGprsSupportInCell )
	        {
	TFLOGSTRING( "CustomTSY: CMmPacketTsy::GetEGprsInfo  RMmCustomAPI::EEdgeGprs" );
	        gprsInformation.iGprsInfo = RMmCustomAPI::EEdgeGprs; 
	        }

	    // else EGPRS connection is not supported
	    else 
	        {
	TFLOGSTRING( "CustomTSY: CMmPacketTsy::GetEGprsInfo  RMmCustomAPI::EGprs" );
	        gprsInformation.iGprsInfo = RMmCustomAPI::EGprs;
	        }

		ret = KErrNone;
		
	    // Complete the client request
	    ReqCompleted( aTsyReqHandle, ret );
		}
		
    return ret;
    }

// ---------------------------------------------------------------------------
// CMmPacketTsy::CompleteNotifyEGprsInfoChange
// Completes EGPRS notification request to Client.
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
void CMmPacketTsy::CompleteNotifyEGprsInfoChange(
    const TBool aGprsSupportInCell )
    {
TFLOGSTRING( "CustomTSY: CMmPacketTsy::CompleteNotifyEGprsInfoChange" );
    TTsyReqHandle reqHandle = iTsyReqHandleStore->ResetTsyReqHandle(
        EMultimodePacketContextNotifyEGprsInfoChange );

    if ( EMultimodePacketContextReqHandleUnknown != reqHandle )
        {
        // Unpack iGprsInformationPckg
        RMmCustomAPI::TGprsInformation& gprsInformation = 
            ( *iGprsInformationPckg )();

        // if aGprsSupportInCell is ETrue -> cell is supporting edge GPRS
        if ( aGprsSupportInCell )
            {
TFLOGSTRING( "CustomTSY: CMmPacketTsy::CompleteNotifyEGprsInfoChange  RMmCustomAPI::EEdgeGprs" );
            gprsInformation.iGprsInfo = RMmCustomAPI::EEdgeGprs;
            }

        // if aGprsSupportInCell is EFalse -> cell is not supporting edge GPRS
        else 
            {
TFLOGSTRING( "CustomTSY: CMmPacketTsy::CompleteNotifyEGprsInfoChange  RMmCustomAPI::EGprs" );
            gprsInformation.iGprsInfo = RMmCustomAPI::EGprs;
            }
                    
        iGprsInformationPckg = NULL;

        // Complete the client request
        ReqCompleted( reqHandle, KErrNone );
        }
    }
    
//-----------------------------------------------------------------------------
// CMmPacketTsy::SetAlwaysOnL
// Requests Set Always On with mode given as parameter aMode
// (other items were commented in a header).
//-----------------------------------------------------------------------------
//
TInt CMmPacketTsy::SetAlwaysOnL( 
	TTsyReqHandle aTsyReqHandle,
	RMmCustomAPI::TSetAlwaysOnMode* aMode )
    {
TFLOGSTRING2( "CMmPacketTsy::SetAlwaysOn Reg Handle = %d", aTsyReqHandle );
	
	TInt ret( KErrGeneral );
	
											
	//Save requested mode 
	iAllwaysOnMode = ( *aMode );
	//Get packetdata session
	CMmPacketServiceTsy* packetDataSession = iMmPhone->PacketDataSession();
	
    if ( NULL != packetDataSession )
        {
        //request set allways on
        ret = packetDataSession->SetAlwaysOnL( aTsyReqHandle, iAllwaysOnMode );
        }
    else
        {
TFLOGSTRING( "CMmPacketTsy::SetAlwaysOn packetDataSession is NULL " );		
        }	
		
    return ret;
    }

//-----------------------------------------------------------------------------
// CMmPacketTsy::CompleteSetAlwaysOn
// Completes Set Always On request 
// (other items were commented in a header).
//-----------------------------------------------------------------------------
//
void CMmPacketTsy::CompleteSetAlwaysOn( 
	TTsyReqHandle aReqHandle, 
	TInt aError )
    {
TFLOGSTRING( "CMmPacketTsy::CompleteSetAlwaysOn" );

	ReqCompleted( aReqHandle, aError );

    }

//-----------------------------------------------------------------------------
// CMmPacketTsy::CancelSetAlwaysOn
// Cancels Set Always On request
// (other items were commented in a header).
//-----------------------------------------------------------------------------
//
void CMmPacketTsy::CancelSetAlwaysOn( TTsyReqHandle aReqHandle )
	{
TFLOGSTRING( "CMmPacketTsy::CancelSetAlwaysOn" );
	
	//Direct request to Service Tsy
	iMmPhone->PacketDataSession()->CancelSetAlwaysOn( aReqHandle );
	
	}
	
#ifdef REQHANDLE_TIMER
// ---------------------------------------------------------------------------
// CMmPacketTsy::SetTypeOfResponse
// Sets the type of response for a given handle.
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
void CMmPacketTsy::SetTypeOfResponse(
    const TInt /*aReqHandleType*/,
    const TTsyReqHandle /*aTsyReqHandle*/)
    {
    }

// ---------------------------------------------------------------------------
// CMmPacketTsy::Complete
// Completes the request due the timer expiration
// (other items were commented in a header).
// ---------------------------------------------------------------------------
//
void CMmPacketTsy::Complete(
    TInt /*aReqHandleType*/, 
    TInt /*aError*/ )
    {
    }
#endif // REQHANDLE_TIMER


//  End of File

