telephonyserverplugins/common_tsy/commontsy/src/mmgsmwcdma/cmmconferencecallgsmwcdmaext.cpp
changeset 0 3553901f7fa8
child 5 7ef16719d8cb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyserverplugins/common_tsy/commontsy/src/mmgsmwcdma/cmmconferencecallgsmwcdmaext.cpp	Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,1613 @@
+// 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:
+//
+
+
+
+//  INCLUDE FILES
+#include "cmmconferencecallgsmwcdmaext.h"
+#include "cmmphonetsy.h"
+#include "cmmconferencecalltsy.h"
+#include "cmmvoicecalltsy.h"
+#include "cmmcalllist.h"
+#include "cmmcallgsmwcdmaext.h"
+#include <ctsy/pluginapi/cmmdatapackage.h>
+#include "cmmmessagemanagerbase.h"
+#include <etelmmerr.h> // etel error codes
+
+// ======== MEMBER FUNCTIONS ========
+
+CMmConferenceCallGsmWcdmaExt::CMmConferenceCallGsmWcdmaExt()
+    {
+    }
+
+CMmConferenceCallGsmWcdmaExt::~CMmConferenceCallGsmWcdmaExt()
+    {
+    iMmConferenceCallTsy = NULL;
+    }
+
+CMmConferenceCallGsmWcdmaExt* CMmConferenceCallGsmWcdmaExt::NewL(
+    CMmConferenceCallTsy* aMmConferenceCallTsy )
+    {
+    CMmConferenceCallGsmWcdmaExt* const conferenceCallGsmWcdmaExt = 
+        new ( ELeave ) CMmConferenceCallGsmWcdmaExt();
+    
+    CleanupStack::PushL( conferenceCallGsmWcdmaExt );
+    conferenceCallGsmWcdmaExt->iMmConferenceCallTsy = aMmConferenceCallTsy;
+    conferenceCallGsmWcdmaExt->ConstructL();
+    CleanupStack::Pop();
+
+    return conferenceCallGsmWcdmaExt;
+    }
+
+void CMmConferenceCallGsmWcdmaExt::ConstructL()
+    {
+    ResetAttributes();
+    }
+
+// ======== LOCAL FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::CreateConferenceL
+// This method allows clients to create the initial conference call.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallGsmWcdmaExt::CreateConferenceL(
+    RMobileConferenceCall::TMobileConferenceStatus aStatus )
+    {
+    TInt ret = KErrNotReady;
+
+    //This method allows clients to create the inital 3-way conference call. 
+    //The phone must be in a state where there are two single voice calls, 
+    //one on hold and the other connected or alerting the remote, called party. 
+    //The TSY will reflect the conference creation capability by setting 
+    //the KCapsJoin flags of the individual calls and the KCapsCreate flag 
+    //of the conference call sub-session.
+    //
+    //In GSM mode, this method will complete when the TSY has received 
+    //confirmation from the network that the conference call service has been 
+    //successfully invoked.
+
+    //This check is required because Add call uses same DOS operation to 
+    //as this one. Therefore we don't want to continue if status is not
+    //Idle.     
+    if ( RMobileConferenceCall::EConferenceIdle == aStatus )
+        {
+        //We have to get 2 active status indications before the conference 
+        //has really gone to active state.
+        iCreateConferenceCounter = 2;
+
+#ifndef USING_CTSY_DISPATCHER
+        //send request to DOS
+		// no packaged parameters for DOS call
+		ret = iMmConferenceCallTsy->Phone()->MessageManager()->
+            HandleRequestL( EMobileConferenceCallCreateConference );
+#else
+		// Pass down the call IDs of the active and held calls to be
+		// joined in the conference.
+		TInt heldCallId = iMmConferenceCallTsy->HeldCall()->CallId();
+		TInt connectedCallId = iMmConferenceCallTsy->ConnectedCall()->CallId();
+		CCallDataPackage package;
+		package.SetCallIdAndMode(heldCallId, iMmConferenceCallTsy->HeldCall()->CallMode());
+		package.PackData(&connectedCallId);
+		ret = iMmConferenceCallTsy->Phone()->MessageManager()->
+			HandleRequestL( EMobileConferenceCallCreateConference, &package);
+#endif   // USING_CTSY_DISPATCHER
+        }
+
+    //return request result
+    return ret;
+
+    }
+
+#ifndef USING_CTSY_DISPATCHER
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::AddCallL
+// Addition of a new call to an existing conference call. If 
+// call object is not found by the name given as input parameter KErrArgument
+// will be returned.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallGsmWcdmaExt::AddCallL(
+    const TName* aCallName,
+    RMobileConferenceCall::TMobileConferenceStatus aStatus,
+    CMmCallList* aCallList )
+    {
+    TInt ret = KErrArgument;
+
+    // Get the call object that should be added to the conference call
+    CMmCallTsy* mmCall = aCallList->GetMmCallByName( aCallName );
+    if ( mmCall ) 
+        {
+        // Fetch the active call extension
+        CMmCallGsmWcdmaExt* mmCallGsmWcdmaExt = static_cast<CMmCallGsmWcdmaExt*>( mmCall->ActiveCallExtension() );
+        // Get the mobile call capabilities
+        RMobileCall::TMobileCallCapsV1 mobileCallCaps;
+        mmCallGsmWcdmaExt->GetMobileCallCapsV1(mobileCallCaps);
+        // Only calls whose call control capabilities include KCapsJoin can be added to a conference call.
+        if( !( RMobileCall::KCapsJoin & mobileCallCaps.iCallControlCaps ))
+        	{ // Do not add the call to the conference since the call doesn't have KCapsJoin capability.
+        	if(KMaxCallsInConference <= iMmConferenceCallTsy->NumberOfCallsInConference())
+        		return KErrMMEtelMaxReached;
+        	return ret;
+        	} 
+
+        RMobileCall::TMobileCallStatus callStatus = 
+            mmCall->MobileCallStatus();
+        //check that this call is not in hold or connected  state and 
+        //conference call is not idle (=no reason to try this)
+        if ( ( ( callStatus == RMobileCall::EStatusHold ) ||
+                ( callStatus == RMobileCall::EStatusConnected ) )
+            && ( RMobileConferenceCall::EConferenceIdle != aStatus ) )
+            {
+            // send request to DOS
+            // only packed parameter for DOS call: Id of the call to be added
+            CCallDataPackage callDataPackage;
+            callDataPackage.SetCallIdAndMode( mmCall->CallId(), 
+                RMobilePhone::EServiceUnspecified ); // service type not needed
+            ret = iMmConferenceCallTsy->Phone()->MessageManager()->
+                    HandleRequestL( EMobileConferenceCallAddCall,
+                    &callDataPackage );
+            }
+        }
+
+    return ret;
+    }
+#endif //USING_CTSY_DISPATCHER
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::SwapL
+// This method can be used to swap the ongoing conference call
+// between active and held status. 
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallGsmWcdmaExt::SwapL(
+	RMobileConferenceCall::TMobileConferenceStatus aStatus,
+    CMmCallList* aCallList )
+    {
+TFLOGSTRING("TSY: CMmConferenceCallGsmWcdmaExt::SwapL");
+	TInt ret = KErrArgument;
+
+	// conference must be active or held
+    if ( aStatus == RMobileConferenceCall::EConferenceIdle )
+        {
+        ret = KErrNotReady;
+        }
+    else
+        {
+        // Init counter
+        iNumberOfCallsToBeSwapped = 0;
+        CMmCallTsy* mmCall = NULL;
+        CMmCallList* callList = iMmConferenceCallTsy->Phone()->CallList();
+
+        // Check from call list the number of calls to be swapped
+        for ( TInt i = 0; i < callList->GetNumberOfObjects(); i++ )
+            {
+            mmCall = callList->GetMmCallByIndex( i );
+
+            if ( mmCall->IsPartOfConference() 
+                && ( mmCall->MobileCallStatus() == RMobileCall::EStatusHold 
+                || mmCall->MobileCallStatus() == RMobileCall::EStatusConnected ) )
+                {
+                // Call found, increase the counter.
+                iNumberOfCallsToBeSwapped++;
+                }
+            }
+TFLOGSTRING2("TSY: CMmConferenceCallGsmWcdmaExt::SwapL - Number of calls in conference: %d", iNumberOfCallsToBeSwapped);
+
+        // Find active and held call objects:
+        CMmCallTsy* mmActiveCall = 
+            aCallList->GetMmCallByStatus( RMobileCall::EStatusConnected );
+        CMmCallTsy* mmHeldCall = 
+            aCallList->GetMmCallByStatus( RMobileCall::EStatusHold ); 
+
+        if ( RMobileConferenceCall::EConferenceActive == aStatus )
+            {
+            // conference is active
+            // if held call is found, swap operation is required
+            if ( mmHeldCall )
+                {
+#ifndef USING_CTSY_DISPATCHER
+                // need to swap
+                // no packed parameters for DOS call
+                ret = iMmConferenceCallTsy->Phone()->MessageManager()->
+                    HandleRequestL( EMobileConferenceCallSwap );
+#else
+                if (mmActiveCall && mmCall)
+                	{
+	                CCallDataPackage callDataPackage;
+	                callDataPackage.SetCallIdAndMode( mmCall->CallId(),
+	                		RMobilePhone::EServiceUnspecified ); // service type not needed
+	                TInt heldCallId = mmHeldCall->CallId();
+	                TInt connectedCallId = mmActiveCall->CallId();
+	                callDataPackage.PackData(&heldCallId, &connectedCallId);
+	                ret = iMmConferenceCallTsy->Phone()->MessageManager()->
+	                		HandleRequestL(EMobileConferenceCallSwap, &callDataPackage);
+                	}
+                else
+                	{
+                	ret = KErrNotReady; // Shouldn't happen
+                	}
+#endif // USING_CTSY_DISPATCHER
+                }
+            // if held call is not found, there should be an active call
+	        // and hold operation is required
+            else if ( mmActiveCall )
+                {
+                // need to hold the active (conference) call
+
+                // create package; set call id and call mode
+                CCallDataPackage package;
+                package.SetCallIdAndMode( mmActiveCall->CallId(),
+                    mmActiveCall->CallMode() );
+
+                // send to DOS
+                ret = iMmConferenceCallTsy->Phone()->MessageManager()->
+                    HandleRequestL( EMobileCallHold, &package );
+                }
+            // we have neither an active nor a held call
+            else
+                {
+                ret = KErrNotReady; // should never happen
+                }
+            }
+        else if ( RMobileConferenceCall::EConferenceHold == aStatus )
+            {
+            // conference is held
+            //if active call is found, swap operation is required
+            if ( mmActiveCall )
+                {
+#ifndef USING_CTSY_DISPATCHER
+                // need to swap
+                // no packed parameters for DOS call
+                ret = iMmConferenceCallTsy->Phone()->MessageManager()->
+                    HandleRequestL( EMobileConferenceCallSwap );
+#else
+                if (mmHeldCall && mmCall)
+                	{
+	                CCallDataPackage callDataPackage;
+	                callDataPackage.SetCallIdAndMode( mmCall->CallId(),
+	                		RMobilePhone::EServiceUnspecified ); // service type not needed
+	                TInt heldCallId = mmHeldCall->CallId();
+	                TInt connectedCallId = mmActiveCall->CallId();
+	                callDataPackage.PackData(&heldCallId, &connectedCallId);
+	                ret = iMmConferenceCallTsy->Phone()->MessageManager()->
+	                		HandleRequestL(EMobileConferenceCallSwap, &callDataPackage);
+                	}
+                else
+                	{
+                	ret = KErrNotReady; // Shouldn't happen
+                	}
+#endif // USING_CTSY_DISPATCHER
+                }
+            // if active call is not found, there should be a held call
+            // and resume operation is required
+            else if ( mmHeldCall )
+                {
+                // need to retrieve (unhold) the held call
+
+                // create package; set call id and call mode
+                CCallDataPackage package;
+                package.SetCallIdAndMode( mmHeldCall->CallId(),
+                    mmHeldCall->CallMode() );
+
+                // send to DOS
+                ret = iMmConferenceCallTsy->Phone()->MessageManager()->
+                    HandleRequestL( EMobileCallResume, &package );
+                }
+            // we have neither an active nor a held call
+            else
+                {
+                ret = KErrNotReady; // should never happen
+                }
+            }
+        }
+
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::CallStatusChanged
+// After the status of a single call has changed, this method decides if
+// the status of the conference call should be changed as well.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TBool CMmConferenceCallGsmWcdmaExt::CallStatusChanged(
+    RMobileCall::TMobileCallStatus aNewStatus,
+    TInt aCallId )
+    {
+TFLOGSTRING3("TSY: CMmConferenceCallGsmWcdmaExt::CallStatusChanged, aNewStatus:%d, aCallId:%d", aNewStatus, aCallId );
+
+    TBool statusChanged( EFalse );
+
+    //get current conference call status
+    RMobileConferenceCall::TMobileConferenceStatus status 
+            = iMmConferenceCallTsy->Status();
+
+TFLOGSTRING2("TSY: CMmConferenceCallGsmWcdmaExt::CallStatusChanged, Current conf call iMmConferenceCallTsy->Status:%d ", status);
+TFLOGSTRING2("TSY: CMmConferenceCallGsmWcdmaExt::CallStatusChanged, Current conference extension iNewStatus:%d ", iNewStatus);
+    //get call list
+    CMmCallList* callList = iMmConferenceCallTsy->Phone()->CallList();
+
+    switch( aNewStatus )
+        {
+        //call has gone to idle state
+        case RMobileCall::EStatusIdle:
+            //If conference call is in active or held state 
+            if ( ( RMobileConferenceCall::EConferenceActive == status ||
+                   RMobileConferenceCall::EConferenceHold == status ) )           
+                {
+                //handle call releasing
+                statusChanged = HandleCallRelease(
+                    status, *callList, aNewStatus, aCallId );
+                }
+            break;
+        //call has gone to held state
+        case RMobileCall::EStatusHold:
+            //if conference call is in active state
+            if ( RMobileConferenceCall::EConferenceActive == status )
+                {
+                //check if swap request is pending
+                if ( iMmConferenceCallTsy->ServiceRequested(
+                        CMmConferenceCallTsy::EMultimodeConferenceCallSwap )
+                     || iCurrentGhostOperation ==
+                        RMobileConferenceCall::EConferenceSwapped )
+                    {
+                    //handle swapping
+                    statusChanged = HandleSwap( status, *callList );
+                    }
+                //is GoOneToOne going on
+                else if ( iGoOneToOneHandlingStarted )
+                    {
+                    statusChanged = HandleGoOneToOne( *callList, aCallId );
+                    }
+                //check that add call request is not pending
+                else if ( !iMmConferenceCallTsy->ServiceRequested( 
+                    CMmConferenceCallTsy::EMultimodeConferenceCallAddCall ) )
+                    {
+                    //Client has requested hold for a single call. If the call is part
+                    //of the conference, all calls participating in the conference
+                    //call will be held.
+                    CMmCallTsy* call = callList->GetMmCallById(aCallId);
+                    if(call != NULL && call->IsPartOfConference())
+                    	{
+                    	statusChanged = HandleSingleCallControl(status, aNewStatus);
+                    	}
+                    }
+                }
+            break;
+        //call has gone to active state
+        case RMobileCall::EStatusConnected:
+            //check if CreateConference request is pending
+            if ( ( iMmConferenceCallTsy->ServiceRequested(
+                    CMmConferenceCallTsy::EMultimodeConferenceCallCreateConference )
+                 || iCurrentGhostOperation == RMobileConferenceCall::EConferenceBuilt ) 
+                 && RMobileConferenceCall::EConferenceIdle == status )
+                {
+                //handle create conference
+                statusChanged = HandleCreateConference(
+                    *callList, aCallId );
+                }
+            //check if AddCall request is pending
+            else if ( ( iMmConferenceCallTsy->ServiceRequested(
+                    CMmConferenceCallTsy::EMultimodeConferenceCallAddCall ) ||
+                iCurrentGhostOperation ==  RMobileConferenceCall::EConferenceBuilt ||
+                iCurrentGhostOperation ==  RMobileConferenceCall::EConferenceCallAdded ) &&
+                ( RMobileConferenceCall::EConferenceActive == status ||
+                RMobileConferenceCall::EConferenceHold == status ) )
+                {
+                //handle add call...
+                statusChanged = HandleAddCall( status, *callList,
+                    aNewStatus );
+                }
+            //check if swap request is pending
+            else if ( iMmConferenceCallTsy->ServiceRequested(
+                    CMmConferenceCallTsy::EMultimodeConferenceCallSwap ) ||
+                iCurrentGhostOperation ==  RMobileConferenceCall::EConferenceSwapped )
+                {
+                //is conference status hold
+                if ( RMobileConferenceCall::EConferenceHold == status )
+                    {
+                    //handle swap...
+                    statusChanged = HandleSwap( status, *callList );
+                    }
+                }
+            // call status might have changed because client has requested it
+            // directly from a call object which is part of the conference
+            // (not from the conference call object).
+            else if ( RMobileConferenceCall::EConferenceHold == status )
+                {
+                CMmCallTsy* mmCall = callList->GetMmCallById( aCallId );
+                if ( mmCall )
+                    {
+                    if ( mmCall->IsPartOfConference() )
+                        {
+                        // if this call is part of the conference, conference
+                        // status is Hold and new call status is Connected, we
+                        // have to get the whole conference into active state
+                        statusChanged = HandleSingleCallControl(
+                            status, aNewStatus );
+                        }
+                    }
+                }
+            break;
+        case RMobileCall::EStatusUnknown:
+        case RMobileCall::EStatusDialling:
+        case RMobileCall::EStatusRinging:
+        case RMobileCall::EStatusAnswering:
+        case RMobileCall::EStatusConnecting:
+        case RMobileCall::EStatusDisconnecting:
+        case RMobileCall::EStatusDisconnectingWithInband:
+        case RMobileCall::EStatusReconnectPending:
+        case RMobileCall::EStatusWaitingAlternatingCallSwitch:
+        case RMobileCall::EStatusTransferring:
+        case RMobileCall::EStatusTransferAlerting:
+        default:
+            break;
+        }
+
+    if ( statusChanged )
+        {
+        // -1 indicates that there is no unhandled ghost operation anymore
+        iCurrentGhostOperation = -1;
+TFLOGSTRING("TSY: CMmConferenceCallGsmWcdmaExt::CallStatusChanged, statusChanged!! ");   
+        }
+TFLOGSTRING2("TSY: CMmConferenceCallGsmWcdmaExt::CallStatusChanged END, current conference extension iNewStatus:%d ", iNewStatus);
+
+    return statusChanged;
+    }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::SetGoOneToOneHandlingStarted
+// Informs the Gsm extension if Go-One-To-One handling
+// has started for any call.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallGsmWcdmaExt::SetGoOneToOneHandlingStarted(
+    TBool aVal,
+    TInt aCallId )
+    {
+    iGoOneToOneHandlingStarted = aVal;
+    iGoOneToOneCallId = aCallId;
+    }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::CheckConferenceCapability
+// Check if conference call creation is possible.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallGsmWcdmaExt::CheckConferenceCapability(
+    RMobileConferenceCall::TMobileConferenceStatus aStatus,
+    CMmCallList* aCallList )
+    {
+TFLOGSTRING2("TSY: CMmConferenceCallGsmWcdmaExt::CheckConferenceCapability. aStatus:%d ", aStatus);     
+    //Check if conference creation is possible. CC has to be in Idle state
+    if ( RMobileConferenceCall::EConferenceIdle == aStatus  )
+        {
+        TUint8 connectedCount( 0 ); //how many calls are in active state
+        TUint8 heldCount( 0 ); //how many calls are in hold state
+        //number of calls in CallList
+        TInt numberOfCallObjects = aCallList->GetNumberOfObjects();
+
+        //check how many calls are in connected and held state
+        for ( TInt i = 0; i < numberOfCallObjects; i++ )
+            {
+            CMmCallTsy* aMmCall = aCallList->GetMmCallByIndex( i );
+            if ( aMmCall->MobileCallStatus() == 
+                    RMobileCall::EStatusConnected )
+                {
+                //increment connected count
+                connectedCount++;
+                }
+            else if ( aMmCall->MobileCallStatus() ==
+                        RMobileCall::EStatusHold )
+                {
+                //increment held count
+                heldCount++;
+                }
+            }
+
+        //If caps were KCapsCreate and conference call creation is not anymore
+        //possible, clear caps.
+        TBool tryToClearConference( EFalse );
+
+        if ( iMmConferenceCallTsy->Caps() == 
+                RMobileConferenceCall::KCapsCreate )
+            {
+            tryToClearConference = ETrue;
+            }
+
+        //Check that exactly one call is on hold and one is active
+        if ( ( 1 == connectedCount && 1 == heldCount ) && 
+            !tryToClearConference )
+            {
+            //Conference call creation is possible -> inform Common part.
+            iMmConferenceCallTsy->
+                CompleteNotifyCapsChange( RMobileConferenceCall::KCapsCreate );
+            }
+        else if ( ( ( 1 == connectedCount && 0 == heldCount ) ||
+            ( 0 == connectedCount && 1 == heldCount ) ) && 
+            tryToClearConference ) 
+            {
+            //Conference call creation is not possible -> inform Common part.
+            iMmConferenceCallTsy->CompleteNotifyCapsChange( KErrNone );
+            }
+        }
+    }
+
+#ifndef USING_CTSY_DISPATCHER
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::HangUpL
+// This method terminates the whole conference call. All calls 
+// participating in the conference call will be disconnected.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallGsmWcdmaExt::HangUpL(
+    RMobileConferenceCall::TMobileConferenceStatus aStatus )
+    {
+    TInt ret( KErrAccessDenied );
+
+    if ( aStatus != RMobileConferenceCall::EConferenceIdle )
+        {
+        //Close all calls that are part of the conference call.
+        //Held call is not released if there is one...
+        // no packed parameters for DOS call
+        ret = iMmConferenceCallTsy->Phone()->MessageManager()->
+            HandleRequestL( EMobileConferenceCallHangUp );
+        }
+
+    return ret;
+    }
+
+#endif //USING_CTSY_DISPATCHER
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::GetMobileCallInfo
+// This method returns a current snapshot of the call information 
+// associated with the call specified by the aIndex parameter. This works in 
+// the following way: depending on the conference call status active/held the
+// call object with the same status is searched from the call list. The index 
+// defines which object's information is searched, for example if index is 2,
+// second call object's information with the same status will be returned.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallGsmWcdmaExt::GetMobileCallInfo(
+    TInt* aIndex,
+    TDes8* aCallInfo,
+    CMmCallList* aCallList,
+    RMobileConferenceCall::TMobileConferenceStatus aConferenceStatus )
+    {
+    TInt ret( KErrNotFound );
+    RMobileCall::TMobileCallStatus searchedStatus( RMobileCall::EStatusIdle );
+    
+    //check if we are trying to find active or held calls
+    if ( aConferenceStatus == RMobileConferenceCall::EConferenceActive )
+        {
+        //active
+        searchedStatus = RMobileCall::EStatusConnected;
+        }
+    else if ( aConferenceStatus == RMobileConferenceCall::EConferenceHold )
+        {
+        //held
+        searchedStatus = RMobileCall::EStatusHold;
+        }
+
+    if ( searchedStatus != RMobileCall::EStatusIdle )
+        {
+        TInt counter( 0 );
+        CMmCallTsy* mobileCall = NULL;
+
+        //search through all objects in call list
+        for ( TInt i = 0; i < aCallList->GetNumberOfObjects(); i++)
+            {
+            //get mobile call
+            mobileCall = static_cast<CMmCallTsy*>(
+                aCallList->GetObjectByIndex( i ) );
+            //if call's status matches with searched status
+            if ( mobileCall->MobileCallStatus() == searchedStatus && 
+                    mobileCall->IsPartOfConference() )
+                {
+                //if index matches
+                if ( counter == *aIndex )
+                    {
+                    //get mobile call info
+                    mobileCall->FillMobileCallInfo( aCallInfo );
+                    ret = KErrNone;
+                    break;
+                    }
+                else
+                    {
+                    //else loop to next item in CallList with same status.
+                    counter++;
+                    }
+                }
+            }
+        }
+    
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::IsGoOneToOneSupported
+// GoOneToOne is only valid if the MS is in GSM mode, the 
+// selected call is a voice call and it is a member of an ongoing conference 
+// call and there are no calls in Hold state.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallGsmWcdmaExt::IsGoOneToOneSupported(
+    TInt  aCallId,
+    RMobileConferenceCall::TMobileConferenceStatus aStatus,
+    CMmCallList* aCallList )
+    {
+    TInt ret( KErrNotSupported );
+
+    //The action is only valid if the MS is in GSM mode, the selected call 
+    //is a voice call and it is a member of an ongoing conference call.
+    if ( aStatus == RMobileConferenceCall::EConferenceActive )
+        {
+        CMmCallTsy* mobileCall = aCallList->GetMmCallById( aCallId );
+        
+        if (mobileCall != NULL)
+            {
+            if ( ( RMobilePhone::EVoiceService == mobileCall->CallMode() ) // is a voice call
+                && ( RMobileCall::EStatusConnected ==  mobileCall->MobileCallStatus()) // is an active call
+                && mobileCall->IsPartOfConference() ) // is a member of an ongoing conference call
+                {
+                ret = KErrNone;
+	
+                //Check that there are no held calls
+                mobileCall = aCallList->GetMmCallByStatus( 
+                                RMobileCall::EStatusHold );
+	
+                if ( mobileCall )
+                    {
+                    //held call found -> GoOneToOne not possible
+                    ret = KErrNotSupported;
+                    }
+                }
+            }
+        }
+
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::HandleSwap
+// This method checks when Swap is ready and can be completed.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TBool CMmConferenceCallGsmWcdmaExt::HandleSwap(
+    RMobileConferenceCall::TMobileConferenceStatus aStatus,
+    CMmCallList& aCallList )
+    {
+TFLOGSTRING2("TSY: CMmConferenceCallGsmWcdmaExt::HandleSwap. aStatus:%d ", aStatus);     
+    TBool statusChanged( EFalse );
+
+    //increment counter telling how many calls will still change state
+    iNumberOfCallsToBeSwapped--;
+
+    //if all have changed state
+    if ( 0 == iNumberOfCallsToBeSwapped )
+        {
+        //if status was active
+        if ( RMobileConferenceCall::EConferenceActive == aStatus )
+            {
+            //new status is hold
+            iNewStatus = RMobileConferenceCall::EConferenceHold;
+            statusChanged = ETrue;            
+            }
+        //else if status was hold
+        else if ( RMobileConferenceCall::EConferenceHold == aStatus )
+            {
+            //new status id active
+            iNewStatus = RMobileConferenceCall::EConferenceActive;
+            statusChanged = ETrue;
+            }
+        //update caps
+        UpdateCapsAfterSwap( aStatus, aCallList );
+        }
+
+    return statusChanged;
+    }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::HandleAddCall
+// This method checks when AddCall is ready and can be completed.
+// It also updates the capability flags of the calls.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TBool CMmConferenceCallGsmWcdmaExt::HandleAddCall(
+    RMobileConferenceCall::TMobileConferenceStatus aStatus,
+    CMmCallList& aCallList,
+    RMobileCall::TMobileCallStatus aNewStatus )
+    {
+TFLOGSTRING2("TSY: CMmConferenceCallGsmWcdmaExt::HandleAddCall. aStatus:%d ", aStatus); 
+TFLOGSTRING2("TSY: CMmConferenceCallGsmWcdmaExt::HandleAddCall. aNewStatus:%d ", aNewStatus); 
+    TBool statusChanged( EFalse );
+
+    //Handle adding a call to conference call
+    if ( RMobileCall::EStatusConnected == aNewStatus ||
+         RMobileCall::EStatusIdle == aNewStatus )
+        {
+        TUint8 heldCount( 0 );
+
+        //calculate how many calls are in hold state.
+        for ( TInt i = 0; i < aCallList.GetNumberOfObjects(); i++ )
+            {
+            if ( aCallList.GetMmCallByIndex(i)->MobileCallStatus() 
+                    == RMobileCall::EStatusHold )
+                {
+                //if a held call is found get out. There will be more active
+                //status indications coming...
+                heldCount++;
+                break;
+                }
+            }
+        //All calls have gone to active state
+        if ( heldCount == 0 )
+            {
+            //This means that the conference call has gone from hold state
+            //to active state in the add call process. AddCall can now be
+            //completed.
+            if ( RMobileConferenceCall::EConferenceHold == aStatus )
+                {
+                iNewStatus = RMobileConferenceCall::EConferenceActive;
+                statusChanged = ETrue;
+                }
+            //Conference call status has not changed but we still have to 
+            //complete the AddCall operation. 
+            else 
+                { 
+                iMmConferenceCallTsy->CompleteAddCall( KErrNone ); 
+                } 
+
+            if ( RMobileConferenceCall::EConferenceBuilt == iCurrentGhostOperation ||
+                 RMobileConferenceCall::EConferenceCallAdded == iCurrentGhostOperation )
+                {
+                TInt callIndex( 0 );
+                CMmCallTsy* mmCall = aCallList.GetMmCallByIndex( callIndex );
+
+                while ( mmCall ) 
+                    { 
+                    if ( !mmCall->IsPartOfConference() &&
+                         ( mmCall->MobileCallStatus() == RMobileCall::EStatusConnected ||
+                         mmCall->MobileCallStatus() == RMobileCall::EStatusHold) )
+                        {
+                        iMmConferenceCallTsy->CompleteNotifyConferenceEvent( 
+                            mmCall->CallName(), 
+                            RMobileConferenceCall::EConferenceCallAdded );
+                        break;
+                        }
+                    callIndex++;
+                    mmCall = aCallList.GetMmCallByIndex( callIndex );
+                    }
+                }
+
+            //Call method that updates the caps of the joined calls
+            UpdateCapsAfterJoin( aCallList );
+            } 
+        }
+TFLOGSTRING2("TSY: CMmConferenceCallGsmWcdmaExt::HandleAddCall. statusChanged:%d ", statusChanged); 
+    
+    return statusChanged;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::HandleCreateConference
+// This method checks when CreateConference is ready and can be completed.
+// This method checks that 2 active status indications are received
+// as a response to the CreateConference request and when this is true, 
+// CreateConference request can be completed.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TBool CMmConferenceCallGsmWcdmaExt::HandleCreateConference(
+    CMmCallList& aCallList,
+    TInt aCallId )
+    {
+    TBool statusChanged ( EFalse );
+    CMmCallTsy* mmCall = NULL;
+
+    //get mmcall
+    mmCall = aCallList.GetMmCallById( aCallId );
+
+    if ( mmCall )
+        {
+        //send call added event...
+        iMmConferenceCallTsy->CompleteNotifyConferenceEvent( 
+            mmCall->CallName(), RMobileConferenceCall::EConferenceCallAdded );
+
+        //decrement counter..
+        iCreateConferenceCounter--;
+
+        //if 2 status indications are received
+        if ( 0 == iCreateConferenceCounter )
+            {
+            //CreateConferece can be completed.
+            iNewStatus = RMobileConferenceCall::EConferenceActive;
+            statusChanged = ETrue;
+
+            //Call method that updates the caps of the joined calls
+            UpdateCapsAfterJoin( aCallList );
+            } 
+        }
+
+    return statusChanged;
+    }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::HandleCallRelease
+// This method is called when status indications are received
+// after HangUp is requested from Conference call object. First this method
+// finds out which call object has gone to idle state. Then if there are
+// less than 2 calls left in the remaining conference call, the rest of
+// the conference call will be put to idle state as well (1 call can't be
+// conference call from TSY's point of view).
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TBool CMmConferenceCallGsmWcdmaExt::HandleCallRelease(
+		RMobileConferenceCall::TMobileConferenceStatus aStatus,
+		CMmCallList& aCallList,
+		RMobileCall::TMobileCallStatus aNewStatus,
+		TInt aCallId )
+	{
+	TBool statusChanged( EFalse );
+	TBool callFound( EFalse );
+	CMmCallTsy* mmCall = NULL;
+
+	TFLOGSTRING3("TSY: CMmConferenceCallGsmWcdmaExt::HandleCallRelease aNewStatus %d, aCallId %d",aNewStatus , aCallId );
+	TFLOGSTRING2("TSY: CMmConferenceCallGsmWcdmaExt::HandleCallRelease Calls in CC %d",iMmConferenceCallTsy->NumberOfCallsInConference());
+
+	//first find the call object which has gone to idle state
+	for ( TInt i = 0; i < aCallList.GetNumberOfObjects(); i++ )
+		{
+		mmCall = aCallList.GetMmCallByIndex( i );
+
+		if(mmCall)
+			{
+			TFLOGSTRING2("TSY: Previous Call ID: %d", mmCall->PreviousCallId() );
+			if ( mmCall->PreviousCallId() == aCallId )
+				{
+				if ( 2 == iMmConferenceCallTsy->NumberOfCallsInConference() && mmCall->IsPartOfConference() &&
+						iMmConferenceCallTsy->ServiceRequested( 
+								CMmConferenceCallTsy::EMultimodeConferenceCallAddCall ) )
+					{
+					TFLOGSTRING("TSY: STOP handling this case");
+					return EFalse;
+					}
+				mmCall->ResetPreviousCallId();
+				callFound = ETrue;
+				break;
+				}
+			}
+		}
+
+	//if call object has been found
+	if ( callFound )
+		{
+		//add Join caps to the call that is not part of conference
+		if ( KMaxCallsInConference == 
+		iMmConferenceCallTsy->NumberOfCallsInConference() )
+			{
+			CMmCallGsmWcdmaExt* mmCallGsmWcdmaExt = NULL;
+			RMobileCall::TMobileCallStatus status( RMobileCall::EStatusIdle );
+
+			if ( RMobileConferenceCall::EConferenceActive == aStatus )
+				{
+				//get the held call
+				status = RMobileCall::EStatusHold;
+				}
+			else if ( RMobileConferenceCall::EConferenceHold == aStatus )
+				{
+				//get the connected call
+				status = RMobileCall::EStatusConnected;
+				}
+
+			if ( status != RMobileCall::EStatusIdle )
+				{
+				CMmCallTsy* nonIdleCall =
+				aCallList.GetMmCallByStatus( status );
+
+				if ( nonIdleCall )
+					{
+					// Fetch the active call extension
+					mmCallGsmWcdmaExt = static_cast<CMmCallGsmWcdmaExt*>(
+							nonIdleCall->ActiveCallExtension() );
+					//add Join caps
+					mmCallGsmWcdmaExt->AddGSMCallCaps( 
+							RMobileCall::KCapsJoin );
+					//complete caps change notification
+					nonIdleCall->CompleteNotifyMobileCallCapsChange( 
+							KErrNone );
+					}
+				}
+			}
+
+		if ( mmCall && mmCall->IsPartOfConference() )
+			{    
+			// if the released call was in the conference, send 
+			// removed from conference indication
+			iMmConferenceCallTsy->CompleteNotifyConferenceEvent( 
+					mmCall->CallName(),
+					RMobileConferenceCall::EConferenceCallRemoved );
+			}
+
+		//If there is only 1 call left in the CC, remove it. 1 call can't be
+		//a conference call from MM API's point of view.
+		if ( ( 1 == iMmConferenceCallTsy->NumberOfCallsInConference() ) &&
+				!iMmConferenceCallTsy->ServiceRequested( 
+						CMmConferenceCallTsy::EMultimodeConferenceCallHangUp ) )
+			{
+			RMobileCall::TMobileCallStatus callStatus( 
+					RMobileCall::EStatusIdle );
+
+			//send removed from conference also to the last call in the 
+			// conference. Single call cannot be a conference call.
+			if ( RMobileConferenceCall::EConferenceActive == aStatus )
+				{
+				//we are trying to find connected call
+				callStatus = RMobileCall::EStatusConnected;
+
+				//Special case when last member is on hold and CC Status is active at this 
+				//point(2 members in CC and one is dropped and MO call is made at the same time)
+				for ( TInt d = 0; d < aCallList.GetNumberOfObjects(); d++ )
+					{
+					CMmCallTsy* remainingCall = aCallList.GetMmCallByIndex(d);
+
+					if( remainingCall->MobileCallStatus() == RMobileCall::EStatusHold )
+						{
+						callStatus = RMobileCall::EStatusHold;
+						TFLOGSTRING("TSY: CMmConferenceCallGsmWcdmaExt::HandleCallRelease Call with Hold status found" );
+						break;
+						}	
+					}
+
+				}
+			else if ( RMobileConferenceCall::EConferenceHold == aStatus )
+				{
+				//we are trying to find a held call
+				callStatus = RMobileCall::EStatusHold;
+				}
+			//now search that call
+			for ( TInt c = 0; c < aCallList.GetNumberOfObjects(); c++ )
+				{
+				CMmCallTsy* remainingCall = aCallList.GetMmCallByIndex(c);
+				if ( remainingCall->MobileCallStatus() == callStatus )
+					{
+					iMmConferenceCallTsy->CompleteNotifyConferenceEvent( 
+							remainingCall->CallName(), 
+							RMobileConferenceCall::EConferenceCallRemoved );
+					break;
+					}                
+				}
+
+			UpdateCapsAfterCallRelease( aCallList );
+			}
+
+		//If there are no calls anymore in the CC, notify it...
+		if ( 0 == iMmConferenceCallTsy->NumberOfCallsInConference() )
+			{
+			iNewStatus = RMobileConferenceCall::EConferenceIdle;
+			statusChanged = ETrue;
+			TName dummyName; //No calls left. Send EConferenceTerminate event. Use an empty placeholder name
+			iMmConferenceCallTsy->CompleteNotifyConferenceEvent(dummyName,RMobileConferenceCall::EConferenceTerminated);
+			}
+		//if add call was going on and there was a call release
+		else if ( iMmConferenceCallTsy->ServiceRequested( 
+				CMmConferenceCallTsy::EMultimodeConferenceCallAddCall ) )
+			{
+			//conference call has not gone to idle state
+			HandleAddCall( aStatus, aCallList, aNewStatus );
+			}
+		//if swap was going on and there was a call release
+		else if ( iMmConferenceCallTsy->ServiceRequested( 
+				CMmConferenceCallTsy::EMultimodeConferenceCallSwap ) )
+			{
+			//conference call has not gone to idle state
+			HandleSwap( aStatus, aCallList );
+			}
+		}
+
+	return statusChanged;
+	}
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::HandleSingleCallControl
+// This method is called when status indication is received
+// and Swap, AddCall, CreateConference or HangUp is not requested from
+// Conference call object. This means that client has requested hold or
+// resume directly from single call object. If Hold has been requested 
+// from single call participating conference call -> all calls in conference
+// call will go to Hold state. Same applies also to the Resume command.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TBool CMmConferenceCallGsmWcdmaExt::HandleSingleCallControl(
+    RMobileConferenceCall::TMobileConferenceStatus aStatus,
+    RMobileCall::TMobileCallStatus aNewStatus )
+    {
+    TBool statusChanged( EFalse );
+
+    if ( !iCallControlStarted )
+        {   
+        //save count, how many indications should be received
+        iCallsToBeControlled = iMmConferenceCallTsy->
+            NumberOfCallsInConference();
+        //Don't come here before all calls have changed their status
+        iCallControlStarted = ETrue;
+        }
+
+    //if CC is in Hold status and we get Active status indication
+    if ( RMobileCall::EStatusConnected == aNewStatus &&
+        RMobileConferenceCall::EConferenceHold == aStatus )
+        {
+        //one call in Conference call has changed its status
+        iCallsToBeControlled--;
+        }
+    //if CC is in Active status and we get Hold status indication
+    else if ( RMobileCall::EStatusHold == aNewStatus &&
+        RMobileConferenceCall::EConferenceActive == aStatus )
+        {
+        //one call in Conference call has changed its status
+        iCallsToBeControlled--;
+        }
+
+    //Have all calls in Conference call changed their status?
+    if ( 0 == iCallsToBeControlled )
+        {
+        //if CC was originally in Hold status we have changed to active state
+        if ( RMobileConferenceCall::EConferenceHold == aStatus )
+            {
+            iNewStatus = RMobileConferenceCall::EConferenceActive;
+            }
+        //if CC was originally in Active status we have changed to hold state
+        else if ( RMobileConferenceCall::EConferenceActive == aStatus )
+            {
+            iNewStatus = RMobileConferenceCall::EConferenceHold;
+            }
+        //reset flag
+        iCallControlStarted = EFalse;
+   
+        statusChanged = ETrue;
+        }   
+
+    return statusChanged;
+    }
+    
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::HandleGoOneToOne
+// This method checks when GoOneToOne is ready and can be completed.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TBool CMmConferenceCallGsmWcdmaExt::HandleGoOneToOne(
+    CMmCallList& aCallList,
+    TInt aCallId )
+    {
+    TBool statusChanged( EFalse );
+    CMmCallTsy* mmCall = NULL;
+
+    // check if the call placed on hold is the one to go one to one with
+    // if so, cancel one to one
+    if (aCallId == iGoOneToOneCallId)
+        {
+        mmCall = aCallList.GetMmCallById( iGoOneToOneCallId );
+        if ( mmCall )
+            {
+            // failure of the Go-One-To-One operation
+            reinterpret_cast<CMmVoiceCallTsy*>( mmCall )->CompleteGoOneToOne(
+                KErrNotReady );
+            }
+        
+        iGoOneToOneHandlingStarted = EFalse;
+        iGoOneToOneCallId = -1;
+        iCallControlStarted = EFalse;
+        return statusChanged;
+        }
+
+    if ( !iCallControlStarted )
+        {   
+        //save count, how many indications should be received. All but one 
+        //call (the one that was splitted) should go to hold state.
+        iCallsToBeControlled = 
+            iMmConferenceCallTsy->NumberOfCallsInConference() - 1;
+
+        //Conference call will go to Idle state
+        if ( 1 == iCallsToBeControlled )
+            {
+            for ( TInt i = 0; i < aCallList.GetNumberOfObjects(); i++ )
+                {
+                mmCall = aCallList.GetMmCallByIndex( i );
+
+                if ( RMobileCall::EStatusConnected == mmCall->MobileCallStatus() 
+                    || RMobileCall::EStatusHold == mmCall->MobileCallStatus() )
+                    {
+                    // The call removed notification event for the call which has
+                    // been split gets completed later when the split event is
+                    // completed. This if stops extra call removed event from being completed.
+                    if (mmCall->CallId() != iGoOneToOneCallId)
+                    	{
+#ifdef USING_CTSY_DISPATCHER
+						iMmConferenceCallTsy->CompleteNotifyConferenceEvent(
+							mmCall->CallName(),
+							RMobileConferenceCall::EConferenceCallRemoved );
+#else // USING_CTSY_DISPATCHER
+                    iMmConferenceCallTsy->CompleteNotifyConferenceEvent( 
+                        mmCall->CallName(), 
+                        RMobileConferenceCall::EConferenceCallRemoved );
+#endif // USING_CTSY_DISPATCHER
+                    	}
+   
+                    CMmCallGsmWcdmaExt* mmCallGsmWcdmaExt = 
+                        static_cast<CMmCallGsmWcdmaExt*>( 
+                            mmCall->ActiveCallExtension() );
+
+                    TUint32 caps = RCall::KCapsHangUp;
+                    caps |= RMobileCall::KCapsJoin |
+                        RMobileCall::KCapsSwap |
+                        RMobileCall::KCapsTransfer;
+
+                    mmCallGsmWcdmaExt->AddGSMCallCaps( caps );
+                    mmCallGsmWcdmaExt->RemoveGSMCallCaps( 
+                        RMobileCall::KCapsOneToOne );
+
+                    mmCall->CompleteNotifyMobileCallCapsChange( KErrNone );  
+                    }
+                }
+
+            //new status is idle (there is no conference anymore)
+            iNewStatus = RMobileConferenceCall::EConferenceIdle;
+            statusChanged = ETrue;
+            }
+
+        // Call control is going on, i.e. we are waiting for other calls'
+        // status indications
+        iCallControlStarted = ETrue;
+        }      
+
+    //decrement counter telling how many calls will still change state
+    iCallsToBeControlled--;
+
+    //All conference related call object have changed their state. Remove 
+    //go-one-to-one call object from conference call.
+    if ( iCallsToBeControlled == 0 && iCallControlStarted )
+        {
+        if ( !statusChanged )
+            {
+            // If conference is created with two other parties, conference
+            // is destructed (status is set to EConferenceIdle, see above)
+            iNewStatus = RMobileConferenceCall::EConferenceHold;
+            statusChanged = ETrue;
+            }
+        iCallControlStarted = EFalse;
+        iGoOneToOneHandlingStarted = EFalse;
+
+        mmCall = aCallList.GetMmCallById( iGoOneToOneCallId );
+        
+        iGoOneToOneCallId = -1;
+
+        if ( mmCall )
+            {
+            iMmConferenceCallTsy->CompleteNotifyConferenceEvent( 
+                    mmCall->CallName(), 
+                    RMobileConferenceCall::EConferenceCallRemoved );  
+                    
+            iMmConferenceCallTsy->CompleteNotifyConferenceEvent( 
+                    mmCall->CallName(), 
+                    RMobileConferenceCall::EConferenceSplit );  
+
+            CMmCallGsmWcdmaExt* mmCallGsmWcdmaExt = 
+                static_cast<CMmCallGsmWcdmaExt*>( 
+                    mmCall->ActiveCallExtension() );
+                    
+            mmCallGsmWcdmaExt->AddGSMCallCaps( RMobileCall::KCapsJoin );
+            mmCallGsmWcdmaExt->AddGSMCallCaps( RMobileCall::KCapsHangUp );
+            mmCallGsmWcdmaExt->RemoveGSMCallCaps( RMobileCall::KCapsOneToOne );  
+            
+            mmCall->CompleteNotifyMobileCallCapsChange( KErrNone );        
+
+            // successful complete of the Go-One-To-One operation
+            reinterpret_cast<CMmVoiceCallTsy*>( mmCall )->CompleteGoOneToOne(
+                KErrNone );
+            }
+        }
+    //Update caps only if call is still part of conference call
+    else if ( iCallControlStarted && iGoOneToOneCallId != aCallId )
+        {        
+        mmCall = aCallList.GetMmCallById( aCallId );
+
+        if ( NULL != mmCall )
+            {
+            CMmCallGsmWcdmaExt* mmCallGsmWcdmaExt = 
+                static_cast<CMmCallGsmWcdmaExt*>(
+                    mmCall->ActiveCallExtension() );
+
+            mmCallGsmWcdmaExt->AddGSMCallCaps( RMobileCall::KCapsHangUp );
+            mmCallGsmWcdmaExt->RemoveGSMCallCaps( 
+                RMobileCall::KCapsOneToOne );
+
+            mmCall->CompleteNotifyMobileCallCapsChange( KErrNone );
+            }
+        }
+
+    return statusChanged;
+    }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::GetNewStatus
+// Called by common Conference call object to get the current
+// conference call status. It will be copied to aNewStatus.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallGsmWcdmaExt::GetNewStatus(
+    RMobileConferenceCall::TMobileConferenceStatus* aNewStatus )
+    {
+TFLOGSTRING2("TSY: CMmConferenceCallGsmWcdmaExt::GetNewStatus. iNewStatus:%d ", iNewStatus );     
+    //copy new status
+    *aNewStatus = iNewStatus;
+    //delete new status from GSM extension
+    iNewStatus = RMobileConferenceCall::EConferenceIdle;
+
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::ResetAttributes
+// Resets internal attributes.
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallGsmWcdmaExt::ResetAttributes()
+    {
+TFLOGSTRING("TSY: CMmConferenceCallGsmWcdmaExt::ResetAttributes. " );     
+    //Flag telling if this is not the first hold/active status indication
+    //caused by client asking hold/resume for a single call.
+    iCallControlStarted = EFalse;
+    //Counter telling how many calls should still change their state before
+    //Conference call changes its' state.
+    iCallsToBeControlled = 0;
+    //Counter telling when Create conference is ready to be completed 
+    iCreateConferenceCounter = 0;
+    //New conference call status
+    iNewStatus = RMobileConferenceCall::EConferenceIdle;
+    //Count, how many calls are to be swapped
+    iNumberOfCallsToBeSwapped = 0;
+    //Flag telling if GoOneToOne handling is going on.
+    iGoOneToOneHandlingStarted = EFalse;
+    //Call id for which GoOneToOne handling is going on.
+    iGoOneToOneCallId = -1;
+    //Operation initiated bypassing the ETel (ghost operetion).
+    iCurrentGhostOperation = -1;
+    }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::UpdateCapsAfterJoin
+// Updates call capabilities of all calls after a Join operation
+// has been executed (CreateConference or AddCall).
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallGsmWcdmaExt::UpdateCapsAfterJoin(
+    CMmCallList& aCallList ) const
+    {
+    //update flags of all joined calls
+    for ( TInt i = 0; i < aCallList.GetNumberOfObjects(); i++ )
+        {
+        //Get call object
+        CMmCallTsy* mmCall = aCallList.GetMmCallByIndex(i);
+
+        if ( mmCall )
+            {
+            if ( mmCall->MobileCallStatus() == RMobileCall::EStatusConnected )
+                {
+                // Fetch the active call extension
+                CMmCallGsmWcdmaExt* mmCallGsmWcdmaExt = 
+                    static_cast<CMmCallGsmWcdmaExt*>(
+                        mmCall->ActiveCallExtension() );
+
+                //set caps to be removed;
+                TUint32 caps =  
+                    RMobileCall::KCapsJoin 
+                    | RMobileCall::KCapsSwap;
+                //remove Join and Swap caps
+                mmCallGsmWcdmaExt->RemoveGSMCallCaps( caps );
+                //Add GoOneToOne caps
+                mmCallGsmWcdmaExt->AddGSMCallCaps( 
+                    RMobileCall::KCapsOneToOne );
+                //complete caps change notification
+                mmCall->CompleteNotifyMobileCallCapsChange( KErrNone );
+                }
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::UpdateCapsAfterCallRelease
+// Updates call capabilities of all calls after a call participating in
+// the conference call has gone to idle state.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallGsmWcdmaExt::UpdateCapsAfterCallRelease(
+    CMmCallList& aCallList ) const
+    {
+    TUint32 caps( 0 );
+
+    //try to find connected call
+    CMmCallTsy* connectedCall = aCallList.GetMmCallByStatus( 
+        RMobileCall::EStatusConnected );
+    //try to find a held call
+    CMmCallTsy* heldCall = aCallList.GetMmCallByStatus( 
+        RMobileCall::EStatusHold );
+
+    CMmCallGsmWcdmaExt* mmCallGsmWcdmaExt = NULL;
+
+    if ( connectedCall )
+        {
+        // Fetch the active call extension
+        mmCallGsmWcdmaExt = static_cast<CMmCallGsmWcdmaExt*>(
+            connectedCall->ActiveCallExtension() );
+
+        //add HangUp caps
+        mmCallGsmWcdmaExt->AddGSMCallCaps( 
+            RMobileCall::KCapsHangUp );
+
+        //update caps of connected call
+        if ( heldCall )
+            {
+            //set caps to be added;
+            caps = RMobileCall::KCapsJoin 
+                | RMobileCall::KCapsTransfer
+                | RMobileCall::KCapsSwap;
+            //add Join, Transfer and Swap caps
+            mmCallGsmWcdmaExt->AddGSMCallCaps( caps );
+            }
+        else
+            {
+            //set caps to be removed;
+            caps = RMobileCall::KCapsJoin 
+                | RMobileCall::KCapsTransfer
+                | RMobileCall::KCapsSwap;
+            //remove Join, Transfer and Swap caps
+            mmCallGsmWcdmaExt->RemoveGSMCallCaps( caps );
+            }
+
+        //complete caps change notification
+        connectedCall->CompleteNotifyMobileCallCapsChange( KErrNone );
+        }
+
+    if ( heldCall )
+        {
+        // Fetch the active call extension
+        mmCallGsmWcdmaExt = static_cast<CMmCallGsmWcdmaExt*>(
+            heldCall->ActiveCallExtension() );
+
+        //add HangUp caps
+        mmCallGsmWcdmaExt->AddGSMCallCaps( 
+            RMobileCall::KCapsHangUp );
+
+        //update caps of connected call
+        if ( connectedCall )
+            {
+            //set caps to be added;
+            caps = RMobileCall::KCapsJoin 
+                | RMobileCall::KCapsTransfer
+                | RMobileCall::KCapsSwap;
+            //add Join, Transfer and Swap caps
+            mmCallGsmWcdmaExt->AddGSMCallCaps( caps );
+            }
+        else
+            {
+            //set caps to be removed;
+            caps = RMobileCall::KCapsJoin 
+                | RMobileCall::KCapsTransfer
+                | RMobileCall::KCapsSwap;
+            //remove Join, Transfer and Swap caps
+            mmCallGsmWcdmaExt->RemoveGSMCallCaps( caps );
+            }
+
+        //complete caps change notification
+        heldCall->CompleteNotifyMobileCallCapsChange( KErrNone );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::UpdateCapsAfterSwap
+// Updates call capabilities of all calls after a Swap operation has
+// been executed.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallGsmWcdmaExt::UpdateCapsAfterSwap(
+    RMobileConferenceCall::TMobileConferenceStatus aStatus,
+    CMmCallList& aCallList ) const
+    {
+    CMmCallTsy* mmCall = NULL;
+    CMmCallGsmWcdmaExt* mmCallGsmWcdmaExt = NULL;
+
+    //if status was active
+    if ( aStatus == RMobileConferenceCall::EConferenceActive )
+        {
+        //update caps of all calls participating conference
+        //loop through all call objects searching the held calls
+        for ( TInt i = 0; i < aCallList.GetNumberOfObjects(); i++ )
+            {
+            mmCall = aCallList.GetMmCallByIndex( i );
+
+            if ( mmCall->MobileCallStatus() == RMobileCall::EStatusHold )
+                {
+                // Fetch the active call extension
+                mmCallGsmWcdmaExt = static_cast<CMmCallGsmWcdmaExt*>(
+                    mmCall->ActiveCallExtension() );
+
+                //remove GoOneToOne caps
+                mmCallGsmWcdmaExt->RemoveGSMCallCaps( 
+                    RMobileCall::KCapsOneToOne );
+                //complete caps change notification
+                mmCall->CompleteNotifyMobileCallCapsChange( KErrNone );
+                }
+            }
+        }
+    //else if status was hold
+    else if ( aStatus == RMobileConferenceCall::EConferenceHold )
+        {
+        TInt numberOfNonIdleCalls( 0 );
+
+        //find out the number of non idle calls
+        for ( TInt i = 0; i < aCallList.GetNumberOfObjects(); i++ )
+            {
+            mmCall = aCallList.GetMmCallByIndex( i );
+            if ( mmCall->MobileCallStatus() != RMobileCall::EStatusIdle )
+                {
+                numberOfNonIdleCalls++;
+                }
+            }
+
+        //check that all non idle calls belong to conference call
+        //-> GoOneToOne can be activated.
+        if ( numberOfNonIdleCalls <=
+            iMmConferenceCallTsy->NumberOfCallsInConference() )
+            {
+            //update caps of all calls participating conference
+            //loop through all call objects searching the held calls
+            for ( TInt i = 0; i < aCallList.GetNumberOfObjects(); i++ )
+                {
+                mmCall = aCallList.GetMmCallByIndex( i );
+
+                if ( mmCall->MobileCallStatus() 
+                    == RMobileCall::EStatusConnected )
+                    {
+                    // Fetch the active call extension
+                    mmCallGsmWcdmaExt = static_cast<CMmCallGsmWcdmaExt*>(
+                        mmCall->ActiveCallExtension() );
+
+                    //add GoOneToOne caps
+                    mmCallGsmWcdmaExt->AddGSMCallCaps( 
+                        RMobileCall::KCapsOneToOne );
+                    //complete caps change notification
+                    mmCall->CompleteNotifyMobileCallCapsChange( KErrNone );
+                    }
+                }
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallGsmWcdmaExt::CompleteNotifyConferenceEvent
+// Informs the Gsm extension if there is conference call
+// operation performed that has been initiated bypassing the ETel.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallGsmWcdmaExt::CompleteNotifyConferenceEvent(
+    CMmDataPackage* aDataPackage )
+    {
+    TInt callId( -1 );
+    RMobilePhone::TMobileService callMode(
+        RMobilePhone::EServiceUnspecified );
+    TInt confEvent = -1;
+
+    CCallDataPackage* callDataPackage = 
+        reinterpret_cast<CCallDataPackage*>(aDataPackage);
+
+    callDataPackage->GetCallIdAndMode( callId, callMode );
+    callDataPackage->UnPackData( confEvent );
+
+    //get current conference call status
+    RMobileConferenceCall::TMobileConferenceStatus status 
+            = iMmConferenceCallTsy->Status();
+TFLOGSTRING2("TSY: CMmConferenceCallGsmWcdmaExt::CompleteNotifyConferenceEvent. iMmConferenceCallTsy->Status():%d ", status );
+
+    switch( confEvent )
+        {
+        case RMobileConferenceCall::EConferenceBuilt:
+            //if createConference has not been requested using ETel API
+            //and conference status is idle
+            if ( RMobileConferenceCall::EConferenceIdle == status && 
+                !iMmConferenceCallTsy->ServiceRequested( CMmConferenceCallTsy::
+                    EMultimodeConferenceCallCreateConference ) )
+                {
+TFLOGSTRING("TSY: CMmConferenceCallGsmWcdmaExt::CompleteNotifyConferenceEvent - Build");
+                //We have to get 2 active status indications before the 
+                //conference has really gone to active state.
+                iCreateConferenceCounter = 2;
+                iCurrentGhostOperation = confEvent;
+                }
+            //if addCall has not been requested using ETel API
+            //and conference status is Hold or Active
+            else if ( RMobileConferenceCall::EConferenceIdle != status &&
+                !iMmConferenceCallTsy->ServiceRequested( CMmConferenceCallTsy::
+                    EMultimodeConferenceCallAddCall ) )
+                {
+TFLOGSTRING("TSY: CMmConferenceCallGsmWcdmaExt::CompleteNotifyConferenceEvent - Build/Add");
+                iCurrentGhostOperation = confEvent;
+                }
+            break;
+        case RMobileConferenceCall::EConferenceCallAdded:
+            //if addCall has not been requested using ETel API
+            //and conference status is Hold or Active
+            if ( RMobileConferenceCall::EConferenceIdle != status &&
+                !iMmConferenceCallTsy->ServiceRequested( CMmConferenceCallTsy::
+                    EMultimodeConferenceCallAddCall ) )
+                {
+TFLOGSTRING("TSY: CMmConferenceCallGsmWcdmaExt::CompleteNotifyConferenceEvent - Add");
+                iCurrentGhostOperation = confEvent;
+                }
+            break;
+        case RMobileConferenceCall::EConferenceSwapped:
+            //if swap has not been requested using ETel API
+            if ( RMobileConferenceCall::EConferenceIdle != status &&
+                !iMmConferenceCallTsy->ServiceRequested( 
+                CMmConferenceCallTsy::EMultimodeConferenceCallSwap ) )
+                {
+TFLOGSTRING("TSY: CMmConferenceCallGsmWcdmaExt::CompleteNotifyConferenceEvent - Swap");
+                iNumberOfCallsToBeSwapped 
+                    = iMmConferenceCallTsy->NumberOfCallsInConference();
+
+                iCurrentGhostOperation = confEvent;
+                }
+            break;
+        //GoOneToOne has been requested
+        case RMobileConferenceCall::EConferenceSplit:
+            if ( !iGoOneToOneHandlingStarted )
+                {
+TFLOGSTRING("TSY: CMmConferenceCallGsmWcdmaExt::CompleteNotifyConferenceEvent - Split");
+                iGoOneToOneHandlingStarted = ETrue;
+                iCurrentGhostOperation = confEvent;
+                iGoOneToOneCallId = callId;
+                }
+            break;
+        default:
+TFLOGSTRING("TSY: CMmConferenceCallGsmWcdmaExt::CompleteNotifyConferenceEvent - No Actions");
+            break;
+        }
+    }
+
+
+//  End of File