--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyserverplugins/common_tsy/commontsy/src/mmtsy/cmmconferencecalltsy.cpp Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,1762 @@
+// 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 FILES
+#include "cmmconferencecalltsy.h"
+#include "cmmphonetsy.h"
+#include "cmmtsyreqhandlestore.h"
+#include "MmTsy_numberOfSlots.h"
+#include "CMmCommonStaticUtility.h"
+#include "cmmconferencecallgsmwcdmaext.h"
+#include "cmmvoicecalltsy.h"
+#include "cmmcallgsmwcdmaext.h"
+#include "cmmcalllist.h"
+#include "cmmmessagemanagerbase.h"
+#include <ctsy/serviceapi/gsmerror.h>
+#include <etelmmerr.h> // etel error codes
+
+
+// ======== MEMBER FUNCTIONS ========
+
+CMmConferenceCallTsy::CMmConferenceCallTsy()
+ {
+ }
+
+CMmConferenceCallTsy* CMmConferenceCallTsy::NewL(
+ CMmPhoneTsy* aMmPhone )
+ {
+ CMmConferenceCallTsy* conferenceCallTsy = NULL;
+
+ if ( aMmPhone != NULL )
+ {
+ conferenceCallTsy = new (ELeave) CMmConferenceCallTsy();
+ CleanupClosePushL( *conferenceCallTsy );
+ conferenceCallTsy->iMmPhone = aMmPhone;
+ conferenceCallTsy->ConstructL();
+ CleanupStack::Pop();
+ }
+
+ return conferenceCallTsy;
+
+ }
+
+
+void CMmConferenceCallTsy::ConstructL()
+ {
+
+#ifdef REQHANDLE_TIMER
+ //create req handle store
+ iTsyReqHandleStore = CMmTsyReqHandleStore::NewL( this, iMmPhone,
+ EMultimodeConferenceCallMaxNumOfRequests, iConferenceCallReqHandles );
+#else
+ //create req handle store
+ iTsyReqHandleStore = CMmTsyReqHandleStore::NewL(
+ EMultimodeConferenceCallMaxNumOfRequests, iConferenceCallReqHandles );
+#endif
+
+ //Create conference call extension
+ iMmConferenceCallExtInterface =
+ CMmConferenceCallGsmWcdmaExt::NewL( this );
+
+ //Initialise internal attributes...
+ ResetAttributes();
+
+ //Check if conference call creation is already possible. If possible,
+ //capabilities are updated by the extension.
+ CheckConferenceCapability();
+
+ //register conference call tsy in the message manager
+ iMmPhone->MessageManager()->RegisterTsyObject(
+ CMmMessageManagerBase::EConferenceCallTsy, this );
+
+ }
+
+CMmConferenceCallTsy::~CMmConferenceCallTsy()
+ {
+
+ TFLOGSTRING("TSY: CMmConferenceCallTsy::~CMmConferenceCallTsy");
+
+ if ( iMmPhone )
+ {
+ // deregister tsy object from message manager
+ iMmPhone->MessageManager()->DeregisterTsyObject(this);
+ //set phone tsy's pointer to CC object to NULL
+ iMmPhone->SetConferenceCall( NULL );
+ }
+
+ //if conference is active, close all calls that are part of the conference
+ //call. send request using transaction id 0x00.
+ if ( RMobileConferenceCall::EConferenceIdle != iStatus )
+ {
+ //We can't do nothing if release request fails here, because CC
+ //sub-session is closing down.
+ TInt trapError = KErrNone;
+ TRAP( trapError,
+ iMmConferenceCallExtInterface->HangUpL( iStatus );
+ );
+ }
+
+ if ( iTsyReqHandleStore )
+ {
+ delete iTsyReqHandleStore;
+ }
+
+ //delete conference call extensions
+ if ( iMmConferenceCallExtInterface )
+ {
+ delete iMmConferenceCallExtInterface;
+ }
+ iMmConferenceCallExtInterface = NULL;
+
+ iMmPhone = NULL;
+ iTsyReqHandleStore = NULL;
+ iRetCaps = NULL;
+ iRetStatus = NULL;
+ iRetConferenceEventCallName = NULL;
+ iRetConferenceEvent = NULL;
+ iConnectedCall = NULL;
+ iHoldCall = NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::OpenNewObjectByNameL
+// This method is not supported.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+CTelObject* CMmConferenceCallTsy::OpenNewObjectByNameL(
+ const TDesC& )
+ {
+ User::Leave( KErrNotSupported );
+ //lint -e{527} "unreachable code"
+ return NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::OpenNewObjectL
+// This method is not supported.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+CTelObject* CMmConferenceCallTsy::OpenNewObjectL(
+ TDes& )
+ {
+ User::Leave( KErrNotSupported );
+ return NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::ExtFunc
+// Dispatches extension function requests. All functions that are not
+// part of the core function set, are routed via the ExtFunc method.
+// At the beginning of this method, packaged pointers are unpacked. Then
+// the correct function is selected using the IPC number.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::ExtFunc(
+ const TTsyReqHandle aTsyReqHandle,
+ const TInt aIpc,
+ const TDataPackage& aPackage )
+ {
+ TInt ret( KErrNone );
+ TInt trapError( KErrNone );
+
+ //reset last tsy request type
+ iReqHandleType = EMultimodeConferenceCallReqHandleUnknown;
+
+ //Original code continues here.
+ TRAP( trapError, ret = DoExtFuncL( aTsyReqHandle, aIpc, aPackage ); );
+
+ if ( trapError != KErrNone )
+ {
+ //error handling. Object cannot be created.
+ ReqCompleted( 0, trapError );
+ }
+ //if return value is not KErrNone
+ else if ( ret != KErrNone )
+ {
+ //Complete request with this error value
+ ReqCompleted( aTsyReqHandle, ret );
+ }
+
+ //save request handle
+ if ( EMultimodeConferenceCallReqHandleUnknown != iReqHandleType )
+ {
+#ifdef REQHANDLE_TIMER
+ SetTypeOfResponse ( iReqHandleType, aTsyReqHandle );
+#else
+ iTsyReqHandleStore->SetTsyReqHandle( iReqHandleType, aTsyReqHandle );
+#endif
+ }
+
+ return KErrNone;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::DoExtFuncL
+// ExtFunc is called by the server when it has a "extended",
+// i.e. non-core ETel request for the TSY. To process a request handle,
+// request type and request data are passed to the TSY.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::DoExtFuncL(
+ const TTsyReqHandle aTsyReqHandle,
+ const TInt aIpc,
+ const TDataPackage& aPackage )
+ {
+ TFLOGSTRING3("TSY: CMmConferenceCallTsy::DoExtFuncL.\n \t\t\t IPC:%d\n \t\t\t Handle:%d",
+ aIpc, aTsyReqHandle);
+
+ TInt ret( KErrNotSupported );
+
+ TAny* dataPtr = aPackage.Ptr1();
+
+ // The request data has to extracted from TDataPackage and the TAny*
+ // pointers have to be "cast" to the expected request data type
+ switch( aIpc )
+ {
+ case EMobileConferenceCallGetCaps:
+ ret = GetCaps( aTsyReqHandle,
+ reinterpret_cast<TUint32*>( dataPtr ) );
+ break;
+ case EMobileConferenceCallNotifyCapsChange:
+ ret = NotifyCapsChange( reinterpret_cast<TUint32*>( dataPtr ) );
+ break;
+ case EMobileConferenceCallCreateConference:
+ ret = CreateConferenceL( aTsyReqHandle );
+ break;
+ case EMobileConferenceCallAddCall:
+ ret = AddCallL( aTsyReqHandle,
+ reinterpret_cast<TName*>( aPackage.Des1u() ) );
+ break;
+ case EMobileConferenceCallSwap:
+ ret = SwapL( aTsyReqHandle );
+ break;
+ case EMobileConferenceCallHangUp:
+ ret = HangUpL( aTsyReqHandle );
+ break;
+ case EMobileConferenceCallEnumerateCalls:
+ ret = EnumerateCalls( aTsyReqHandle,
+ reinterpret_cast<TInt*>( dataPtr ) );
+ break;
+ case EMobileConferenceCallGetMobileCallInfo:
+ ret = GetMobileCallInfo( aTsyReqHandle,
+ reinterpret_cast<TInt*>( dataPtr ),
+ aPackage.Des2n() );
+ break;
+ case EMobileConferenceCallGetConferenceStatus:
+ ret = GetConferenceStatus( aTsyReqHandle,
+ reinterpret_cast<RMobileConferenceCall::TMobileConferenceStatus*>(
+ dataPtr ) );
+ break;
+ case EMobileConferenceCallNotifyConferenceStatusChange:
+ ret = NotifyConferenceStatusChange(
+ reinterpret_cast<RMobileConferenceCall::TMobileConferenceStatus*>(
+ dataPtr ) );
+ break;
+ case EMobileConferenceCallNotifyConferenceEvent:
+ ret = NotifyConferenceEvent(
+ reinterpret_cast<RMobileConferenceCall::TMobileConferenceEvent*>(
+ dataPtr ), reinterpret_cast<TName*>( aPackage.Des2u() ) );
+ break;
+ default:
+ ret = KErrNotSupported;
+ break;
+ }
+
+ return ret;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::ReqModeL
+// ReqModeL is called from the server's CTelObject::ReqAnalyserL
+// in order to check the type of request it has.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+CTelObject::TReqMode CMmConferenceCallTsy::ReqModeL(
+ const TInt aIpc )
+ {
+ CTelObject::TReqMode ret( 0 ); // default return value
+
+ switch ( aIpc )
+ {
+ // No Flow Control
+ // All disabled
+ // TSYs wishing to implement their own buffering algorithm will place
+ // all requests in this category.
+ // This category will also be used by the RecoverDataPort request that
+ // must be passed to the TSY to indicate that it may use the
+ // communications port after a loan.
+
+ //Get methods that do not use DOS and return immediately.
+ //Flow control not required.
+ case EMobileConferenceCallGetCaps:
+ case EMobileConferenceCallGetMobileCallInfo:
+ case EMobileConferenceCallGetConferenceStatus:
+ //Other methods that do not use DOS and return immediately.
+ //Flow control not required.
+ case EMobileConferenceCallEnumerateCalls:
+
+ //Methods that can propably take a long time and cannot therefore be
+ //flow controlled. Solution: All these methods must check req handle
+ //table before handling the request. In case that the request table
+ //indicates that same method has been called and has not been
+ //completed, the method should return KErrServerBusy.
+ case EMobileConferenceCallHangUp:
+ break;
+
+ // Flow Controlled Services
+ // KReqModeFlowControlObeyed
+ // Commands that change the state of the phone, e.g. clearing the AoC
+ // counter; are commands that TSY should only deal with one at a time.
+
+ //Voice call related methods that should be handled only
+ //one at the time.
+ case EMobileConferenceCallCreateConference:
+ case EMobileConferenceCallSwap:
+ case EMobileConferenceCallAddCall:
+ ret = KReqModeFlowControlObeyed;
+ break;
+ // ReqModePostImmediately
+ // Requests that notify a client about a change of state, where the
+ // TSY needs to distinguish between different clients.
+ //*******************************************************************
+ // (TAN) DO NOT USE THIS if not absolutely certain how to handle the
+ // corresponding method in TSY. Differs from all other situations!!!
+ //********************************************************************
+ //ret=KReqModeRePostImmediately;
+
+ // KReqModeMultipleCompletionEnabled
+ // (a) commands that may take some time, but which the TSY can handle
+ // more than one of concurrently, or
+ // (b) notifications that the TSY does not wish to be re-posted
+ // immediately, so the server does no buffering.
+ //ret=KReqModeMultipleCompletionEnabled;
+
+ // KReqModeMultipleCompletionEnabled | KReqModeFlowControlObeyed
+ // A command that may take some time and which the TSY can only deal
+ // with one at a time.
+ //case EEtelCallSetFaxSettings:
+ // ret = KReqModeMultipleCompletionEnabled |
+ // KReqModeFlowControlObeyed;
+ // break;
+
+ //Notifications
+ //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 per CTelObject
+ case EMobileConferenceCallNotifyCapsChange:
+ case EMobileConferenceCallNotifyConferenceStatusChange:
+ case EMobileConferenceCallNotifyConferenceEvent:
+ ret = KReqModeMultipleCompletionEnabled |
+ KReqModeRePostImmediately;
+ break;
+ //Cancel Requests
+ //It is not necessary to include the Cancel methods in ReqModeL at all
+ //The ETel server never calls ReqModeL with a Cancel IPC.
+
+ // Other variations of return values are unusable
+ default:
+ // Unknown or invalid Call IPC
+ User::Leave( KErrNotSupported );
+ break;
+ }
+
+ return ret;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::NumberOfSlotsL
+// NumberOfSlotsL is called by the server when it is registering a
+// new NOTIFICATION. It enables the TSY to tell the server
+// how many buffer slots to allocate for "repost immediately" notifications
+// that may trigger before clients collect them.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::NumberOfSlotsL(
+ const TInt aIpc )
+ {
+ // There is a buffer in the ETel server for each type of NOTIFICATION and
+ // the size of the buffer is determined by the TSY. When the ETel server
+ // discovers that a request is "repost immediately" it will ask the TSY
+ // how big a buffer it wants by calling CTelObject::NumberOfSlotsL( ).
+ //
+ // It is up to the TSY developer's judgement how many buffer slots this
+ // method returns for each notification. If there is a danger that a
+ // particular notification could trigger frequently and in rapid
+ // succession (e.g. call group change notification) then at least 10 or 20
+ // slots may be required. For a notification that triggers rarely, perhaps
+ // 1 or 2 slots is enough.
+ //
+ // So if the ETel server has stored a few occurrences of a particular
+ // notification, when client subsequently calls that notification request,
+ // the ETel server will complete the client's request with the saved data.
+
+ TInt numberOfSlots = 1;
+
+ switch ( aIpc )
+ {
+ case EMobileConferenceCallNotifyCapsChange:
+ numberOfSlots = KMmConferenceCallCapsChangeSlots;
+ break;
+ case EMobileConferenceCallNotifyConferenceStatusChange:
+ numberOfSlots = KMmConferenceCallStatusChangeSlots;
+ break;
+ case EMobileConferenceCallNotifyConferenceEvent:
+ numberOfSlots = KMmConferenceCallEventSlots;
+ break;
+ default:
+ // Unknown or invalid Call IPC
+ User::Leave( KErrNotSupported );
+ break;
+ }
+
+ return numberOfSlots;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::CancelService
+// CancelService is called by the server when it is
+// "cleaning-up" any still outstanding asynchronous requests before closing
+// a client's sub-session. This will happen if a client closes its R-class
+// handle without cancelling outstanding asynchronous requests. Only
+// Mobile API requests are handled here.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::CancelService(
+ const TInt aIpc,
+ const TTsyReqHandle aTsyReqHandle )
+ {
+ //When the clients close their sub-sessions (eg. by calling RPhone::Close)
+ //they may not have cancelled all their outstanding asynchronous requests
+ //before closing. It is up to the ETel server to clean up in this
+ //situation, so the server will find the list of outstanding requests
+ //related to that sub-session object and pass these outstanding IPC req.
+ //numbers, one at a time, to the CancelService function in the TSY.
+
+ TInt ret( KErrNone );
+
+ 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 EMobileConferenceCallCreateConference:
+ case EMobileConferenceCallAddCall:
+ case EMobileConferenceCallSwap:
+ case EMobileConferenceCallHangUp:
+ break;
+
+
+ //Cancel methods that are not supported
+ //case XXX
+ // ret = KErrNotSupported;
+ // break;
+
+ //Notification Cancels, no special requirements.
+ case EMobileConferenceCallNotifyCapsChange:
+ ret = NotifyCapsChangeCancel( aTsyReqHandle );
+ break;
+ case EMobileConferenceCallNotifyConferenceStatusChange:
+ ret = NotifyConferenceStatusChangeCancel( aTsyReqHandle );
+ break;
+ case EMobileConferenceCallNotifyConferenceEvent:
+ ret = NotifyConferenceEventCancel( aTsyReqHandle );
+ break;
+ //Everything is taken care in the method implementation.
+ //Just direct the request to the method.
+ //case
+ // none
+
+ //Default case
+ default:
+ ret = KErrNotFound;
+ break;
+ }
+
+ return ret;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::Init
+// Initialisation method that is called from ETel Server.
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallTsy::Init()
+ {
+
+ // None
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::RegisterNotification
+// RegisterNotification is called when the server recognises
+// that this notification is being posted for the first time on this
+// sub-session object. It enables the TSY to "turn on" any regular
+// notification messages that it may receive from DOS. Currently does not
+// really do anything but returns KErrNone to ETel server in case of known
+// notification request type.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::RegisterNotification(
+ const TInt aIpc )
+ {
+ TInt ret( KErrNotSupported );
+
+ switch( aIpc )
+ {
+ case EMobileConferenceCallNotifyCapsChange:
+ case EMobileConferenceCallNotifyConferenceStatusChange:
+ case EMobileConferenceCallNotifyConferenceEvent:
+ ret = KErrNone;
+ break;
+ default:
+ // Unknown or invalid IPC
+ ret = KErrNotSupported;
+ break;
+ }
+
+ return ret;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::DeregisterNotification
+// DeregisterNotification is called when the 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. Currently does not really do anything but returns
+// KErrNone to ETel server in case of known notification request type.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::DeregisterNotification(
+ const TInt aIpc )
+ {
+ TInt ret( KErrNotSupported );
+
+ switch( aIpc )
+ {
+ case EMobileConferenceCallNotifyCapsChange:
+ case EMobileConferenceCallNotifyConferenceStatusChange:
+ case EMobileConferenceCallNotifyConferenceEvent:
+ ret = KErrNone;
+ break;
+ default:
+ // Unknown or invalid IPC
+ ret = KErrNotSupported;
+ break;
+ }
+
+ return ret;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::GetCaps
+// This method returns the current capabilities of the conference call.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::GetCaps(
+ const TTsyReqHandle aTsyReqHandle,
+ TUint32* aCaps )
+ {
+ //Conference caps
+ *aCaps = iConferenceCaps;
+ //Complete the request
+ ReqCompleted( aTsyReqHandle, KErrNone );
+
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::NotifyCapsChange
+// This method allows clients to be notified when the conference
+// call capabilities change.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::NotifyCapsChange(
+ TUint32* aCaps )
+ {
+ //save pointer where to copy the changed value
+ iRetCaps = aCaps;
+ //save req handle type
+ iReqHandleType = EMultimodeConferenceCallCapsChangeNotification;
+
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::NotifyCapsChangeCancel
+// Cancels an outstanding asynchronous NotifyCapsChange request.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::NotifyCapsChangeCancel(
+ const TTsyReqHandle aTsyReqHandle )
+ {
+ //set pointer to NULL
+ iRetCaps = NULL;
+ //reset req handle
+ iTsyReqHandleStore->ResetTsyReqHandle(
+ EMultimodeConferenceCallCapsChangeNotification );
+
+ //Complete request
+ ReqCompleted( aTsyReqHandle, KErrCancel );
+
+ return KErrNone;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::CompleteNotifyCapsChange
+// Completes NotifyCapsChange request when capabilities change.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallTsy::CompleteNotifyCapsChange(
+ TUint32 aCaps )
+ {
+ //update internal capabilities
+ iConferenceCaps = aCaps;
+
+ //reset req handle. Returns the deleted req handle
+ TTsyReqHandle reqHandle = iTsyReqHandleStore->ResetTsyReqHandle(
+ EMultimodeConferenceCallCapsChangeNotification );
+
+ //if req handle was found
+ if ( EMultimodeConferenceCallReqHandleUnknown != reqHandle )
+ {
+ //copy conference caps to requested location
+ *iRetCaps = iConferenceCaps;
+ //complete request
+ ReqCompleted( reqHandle, KErrNone );
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::CreateConferenceL
+// Allows clients to create the initial conference call.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::CreateConferenceL(
+ const TTsyReqHandle aTsyReqHandle )
+ {
+TFLOGSTRING("TSY: CMmConferenceCallTsy::CreateConferenceL");
+ //Store call object with status connected
+ iConnectedCall =
+ iMmPhone->CallList()->GetMmCallByStatus( RMobileCall::EStatusConnected );
+
+ //Store call object with status hold
+ iHoldCall =
+ iMmPhone->CallList()->GetMmCallByStatus( RMobileCall::EStatusHold );
+
+ //Let extension try to create conference call
+ TInt ret = iMmConferenceCallExtInterface->CreateConferenceL( iStatus );
+
+ if ( ret != KErrNone )
+ {
+ //request failed.
+ ReqCompleted( aTsyReqHandle, ret );
+ }
+ else
+ {
+ //save req handle type
+ iReqHandleType = EMultimodeConferenceCallCreateConference;
+ }
+
+ return KErrNone;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::CompleteCreateConference
+// Complete creation of conference call.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallTsy::CompleteCreateConference(
+ TInt aResult )
+ {
+TFLOGSTRING("TSY: CMmConferenceCallTsy::CompleteCreateConference");
+ //reset req handle. Returns the deleted req handle
+ TTsyReqHandle reqHandle = iTsyReqHandleStore->ResetTsyReqHandle(
+ EMultimodeConferenceCallCreateConference );
+
+ //if req handle was available
+ if ( EMultimodeConferenceCallReqHandleUnknown != reqHandle )
+ {
+ //complete caps after successfully creating conference
+ if ( KErrNone == aResult )
+ {
+ //hangup and swap are now possible
+ iConferenceCaps = RMobileConferenceCall::KCapsSwap |
+ RMobileConferenceCall::KCapsHangUp;
+
+ //set flag telling that caps have changed
+ iCapsChanged = ETrue;
+
+ if( iConnectedCall && iHoldCall )
+ {
+ TName connectedCall = iConnectedCall->CallName();
+ TName holdCall = iHoldCall->CallName();
+
+ if( connectedCall.Length() != 0 && holdCall.Length() != 0 )
+ {
+ // Create object including call names
+ // wich were first ones in conference
+ TName callsInConference;
+ callsInConference.Zero();
+ callsInConference.Append( connectedCall );
+ callsInConference.Append( KDelimiter );
+ callsInConference.Append( holdCall );
+ //Complete event
+ CompleteNotifyConferenceEvent( callsInConference,
+ RMobileConferenceCall::EConferenceBuilt );
+ }
+
+ }
+ }
+
+ //complete request
+ ReqCompleted( reqHandle, aResult );
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::AddCallL
+// Adds the single voice call specified by the aCallName parameter
+// to an existing conference call
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::AddCallL(
+ const TTsyReqHandle aTsyReqHandle,
+ const TName* aCallName )
+ {
+TFLOGSTRING("TSY: CMmConferenceCallTsy::AddCallL");
+ //set return value to KErrNotFound
+ TInt ret( KErrNotFound );
+
+ //copy the name of the call to be added, will be used when request is
+ //later completed
+ iAddCallName = *aCallName;
+
+ //start adding a call to conference call
+ ret = iMmConferenceCallExtInterface->AddCallL(
+ &iAddCallName, iStatus, iMmPhone->CallList() );
+
+ if ( ret != KErrNone )
+ {
+ //request failed, complete with error value
+ ReqCompleted( aTsyReqHandle, ret );
+ }
+ else
+ {
+ // Store the request handle
+ iReqHandleType = EMultimodeConferenceCallAddCall;
+ }
+
+ return KErrNone;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::CompleteAddCall
+// Complete addition of a new call to the conference call
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallTsy::CompleteAddCall(
+ TInt aResult )
+ {
+TFLOGSTRING2("TSY: CMmConferenceCallTsy::CompleteAddCall, Result: %d", aResult );
+
+ //reset req handle. Returns the deleted req handle
+ TTsyReqHandle reqHandle = iTsyReqHandleStore->ResetTsyReqHandle(
+ EMultimodeConferenceCallAddCall );
+
+ //successful case, call added to the conference call.
+ if ( EMultimodeConferenceCallReqHandleUnknown != reqHandle )
+ {
+ if ( (KErrNone == aResult) && (iAddCallName.Length() > 0) )
+ {
+TFLOGSTRING("TSY: AddCall succeeded. AddCall request completed");
+ //notify call added using the call name received with AddCall
+ //request
+ CompleteNotifyConferenceEvent( iAddCallName,
+ RMobileConferenceCall::EConferenceCallAdded );
+
+ //Name of the call to be added to Conference call
+ iAddCallName.Zero();
+
+ RemoveNonParticipatingCall();
+ }
+ else
+ {
+ //something special is needed here to handle a case where
+ //CompleteAddCall fails
+ TFLOGSTRING("TSY: AddCall failed");
+ TFLOGSTRING2("TSY: # of CC participants: %d", iNumOfCallsInConferenceCall );
+ if ( 2 == iNumOfCallsInConferenceCall )
+ {
+ TFLOGSTRING("TSY: FIX FOR A ADDCALL & MT RELEASE CASE");
+ CMmCallTsy* mmCall = NULL;
+ CMmCallList* callList = iMmPhone->CallList();
+ CMmCallGsmWcdmaExt* mmCallGsmWcdmaExt = NULL;
+ RMobileCall::TMobileCallStatus status( RMobileCall::EStatusIdle );
+
+ //now check all calls
+ for ( TInt i = 0; i < callList->GetNumberOfObjects(); i++ )
+ {
+ mmCall = callList->GetMmCallByIndex(i);
+ status = mmCall->MobileCallStatus();
+
+ TFLOGSTRING2("TSY: Handling call, Call ID: %d", mmCall->CallId() );
+
+ if ( status == RMobileCall::EStatusHold ||
+ status == RMobileCall::EStatusConnected )
+ {
+ TFLOGSTRING("TSY: Status was Held or Connected, reconstructing capabilities");
+
+ // Fetch the active call extension
+ mmCallGsmWcdmaExt = static_cast<CMmCallGsmWcdmaExt*>(
+ mmCall->ActiveCallExtension() )
+ ;
+ //set caps to be added;
+ TUint32 caps = RMobileCall::KCapsHangUp
+ | RMobileCall::KCapsJoin
+ | RMobileCall::KCapsTransfer
+ | RMobileCall::KCapsSwap;
+ //add Join caps
+ mmCallGsmWcdmaExt->AddGSMCallCaps( caps );
+ //complete caps change notification
+ mmCall->CompleteNotifyMobileCallCapsChange( KErrNone );
+ }
+ }
+ //Clear conference call
+ //Check if conference call is possible to build
+ CheckConferenceCapability();
+ //rebuild capabilities of individual calls
+ }
+ else
+ {
+ TFLOGSTRING("TSY: normal AddCall failure");
+ }
+ }
+ ReqCompleted( reqHandle, aResult );
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::RemoveNonParticipatingCall()
+// Removes call wich is not participant in conference
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+
+void CMmConferenceCallTsy::RemoveNonParticipatingCall()
+ {
+
+ TFLOGSTRING("TSY: CMmConferenceCallTsy::RemoveNonParticipatingCall");
+
+ RMobileCall::TMobileCallStatus statusOfCallsInConference(
+ RMobileCall::EStatusConnected);
+ CMmCallTsy* mmCall = NULL;
+ CMmCallList* callList = iMmPhone->CallList();
+ RMobileCall::TMobileCallStatus status (RMobileCall::EStatusIdle);
+ TInt numberOfCallInConference(0);
+ TBool callReleased = EFalse;
+
+ TFLOGSTRING2("TSY: Conference status: %d", iStatus);
+
+ if ( iStatus == RMobileConferenceCall::EConferenceHold )
+ {
+ statusOfCallsInConference = RMobileCall::EStatusHold;
+ }
+
+ //now check all calls
+ for ( TInt c = 0; c < callList->GetNumberOfObjects(); c++ )
+ {
+ mmCall = callList->GetMmCallByIndex(c);
+ status = mmCall->MobileCallStatus();
+
+ if ( mmCall->IsPartOfConference() &&
+ status != statusOfCallsInConference )
+ {
+ //send removed event
+ CompleteNotifyConferenceEvent(
+ mmCall->CallName(),
+ RMobileConferenceCall::EConferenceCallRemoved );
+TFLOGSTRING("TSY: Call removed from conference." );
+ }
+ else if ( status == statusOfCallsInConference )
+ {
+ numberOfCallInConference++;
+
+ }
+ if ( mmCall->IsRemoteReleasedCall() )
+ {
+TFLOGSTRING("TSY: One call is remote released");
+ callReleased = ETrue;
+ }
+ }
+ if ( numberOfCallInConference == 2 &&
+ iNumOfCallsInConferenceCall == 3 && callReleased )
+ {
+ iNumOfCallsInConferenceCall--;
+ TFLOGSTRING("TSY: number of calls in conference decremented");
+ }
+
+ }
+
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::SwapL
+// Allows a client to switch a conference call between "Active" and
+// "Hold" states.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::SwapL(
+ const TTsyReqHandle aTsyReqHandle )
+ {
+TFLOGSTRING("TSY: CMmConferenceCallTsy::SwapL");
+ //direct request to extension
+ TInt ret = iMmConferenceCallExtInterface->SwapL(
+ iStatus, iMmPhone->CallList() );
+
+ if ( ret != KErrNone )
+ {
+ //complete request with error value
+ ReqCompleted( aTsyReqHandle, ret );
+ }
+ else
+ {
+ // Store the request handle
+ iReqHandleType = EMultimodeConferenceCallSwap;
+ }
+
+ return KErrNone;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::CompleteSwap
+// Complete the ongoing swap request.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallTsy::CompleteSwap(
+ TInt aResult )
+ {
+TFLOGSTRING("TSY: CMmConferenceCallTsy::CompleteSwap");
+ //reset req handle. Returns the deleted req handle
+ TTsyReqHandle reqHandle = iTsyReqHandleStore->ResetTsyReqHandle(
+ EMultimodeConferenceCallSwap );
+
+ if ( EMultimodeConferenceCallReqHandleUnknown != reqHandle )
+ {
+#ifdef USING_CTSY_DISPATCHER
+ if (aResult == KErrNone) // Conference event should only be completed if swap was successful
+ {
+#endif // USING_CTSY_DISPATCHER
+ TName emptyBuf;
+ emptyBuf.Zero();
+ CompleteNotifyConferenceEvent( emptyBuf,
+ RMobileConferenceCall::EConferenceSwapped );
+#ifdef USING_CTSY_DISPATCHER
+ }
+#endif // USING_CTSY_DISPATCHER
+ //complete request
+ ReqCompleted( reqHandle, aResult );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::HangUpL
+// Terminates the whole conference call (all calls participating in the
+// conference call)
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::HangUpL(
+ const TTsyReqHandle aTsyReqHandle )
+ {
+ TInt ret( KErrServerBusy );
+
+ // Check if request handle already exists
+ TTsyReqHandle conferenceCallHangUpHandle = iTsyReqHandleStore->
+ GetTsyReqHandle( EMultimodeConferenceCallHangUp );
+
+ if ( conferenceCallHangUpHandle != EMultimodeConferenceCallReqHandleUnknown )
+ {
+ ReqCompleted( aTsyReqHandle, ret );
+ }
+ else
+ {
+ //Close all calls that are part of the conference call. Held call
+ //is not released if there is one...
+ ret = iMmConferenceCallExtInterface->HangUpL( iStatus );
+
+ //if request failed
+ if ( ret != KErrNone )
+ {
+ //complete request with error value
+ ReqCompleted( aTsyReqHandle, ret );
+ }
+ else
+ {
+ //save last request type
+ iReqHandleType = EMultimodeConferenceCallHangUp;
+ }
+ }
+
+ //Reset pointer
+ iHoldCall = NULL;
+ //Reset pointer
+ iConnectedCall = NULL;
+
+ return KErrNone;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::CompleteHangUp
+// Completes call hangup.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallTsy::CompleteHangUp(
+ TInt aResult )
+ {
+ //reset req handle. Returns the deleted req handle
+ TTsyReqHandle reqHandle = iTsyReqHandleStore->ResetTsyReqHandle(
+ EMultimodeConferenceCallHangUp );
+
+ if ( EMultimodeConferenceCallReqHandleUnknown != reqHandle )
+ {
+ // ignore KErrGsmReleaseByUser, which means that the call ended
+ // because the local user released the call, and must be treated
+ // as a normal return code from the LTSY
+ TInt ret = ( (aResult == KErrGsmReleaseByUser) ? KErrNone : aResult );
+
+ //complete request
+ ReqCompleted( reqHandle, ret );
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::EnumerateCalls
+// This method returns the number of calls that are currently
+// part of the conference call.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::EnumerateCalls(
+ const TTsyReqHandle aTsyReqHandle,
+ TInt* aCount )
+ {
+ *aCount = iNumOfCallsInConferenceCall;
+
+ ReqCompleted( aTsyReqHandle, KErrNone );
+ return KErrNone;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::GetMobileCallInfo
+// This method returns a current snapshot of the call
+// information associated with the call specified by the aIndex parameter.
+// NOTE! Conference call has to be in active state (Held or Active) before
+// this method can return anything. Idle conference call is not considered
+// to contain any calls.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::GetMobileCallInfo(
+ const TTsyReqHandle aTsyReqHandle,
+ TInt* aIndex,
+ TDes8* aCallInfo )
+ {
+ TInt ret( KErrNotReady );
+
+ if ( RMobileConferenceCall::EConferenceIdle != iStatus )
+ {
+ //Let extension get the information
+ ret = iMmConferenceCallExtInterface->GetMobileCallInfo(
+ aIndex, aCallInfo, iMmPhone->CallList(), iStatus );
+ }
+
+ ReqCompleted( aTsyReqHandle, ret );
+ return KErrNone;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::GetConferenceStatus
+// Allows clients to retrieve the current status of the conference call.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::GetConferenceStatus(
+ const TTsyReqHandle aTsyReqHandle,
+ RMobileConferenceCall::TMobileConferenceStatus* aStatus )
+ {
+TFLOGSTRING2("TSY: CMmConferenceCallTsy::GetConferenceStatus. iStatus:%d", iStatus );
+ *aStatus = iStatus;
+
+ ReqCompleted( aTsyReqHandle, KErrNone );
+ return KErrNone;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::Status
+// This function returns conference call status. For internal use.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+RMobileConferenceCall::TMobileConferenceStatus CMmConferenceCallTsy::Status() const
+ {
+
+ //return conference call status
+ return iStatus;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::NotifyConferenceStatusChange
+// Allows clients to be notified of a change in the status of a
+// conference call.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::NotifyConferenceStatusChange(
+ RMobileConferenceCall::TMobileConferenceStatus* aStatus )
+ {
+ iRetStatus = aStatus;
+ iReqHandleType = EMultimodeConferenceCallStatusChangeNotification;
+
+ return KErrNone;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::NotifyConferenceStatusChangeCancel
+// Cancels an outstanding asynchronous NotifyConferenceStatusChange request.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::NotifyConferenceStatusChangeCancel(
+ const TTsyReqHandle aTsyReqHandle )
+ {
+ iRetStatus = NULL;
+
+ iTsyReqHandleStore->ResetTsyReqHandle(
+ EMultimodeConferenceCallStatusChangeNotification );
+
+ ReqCompleted( aTsyReqHandle, KErrCancel );
+ return KErrNone;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::CompleteNotifyConferenceStatusChange
+// Completes conference status change notification. Extension
+// should already have updated status so this method retrieves the new
+// status from the extension and does the actions required by new and old
+// statuses.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallTsy::CompleteNotifyConferenceStatusChange()
+ {
+ TBool conferenceStatusChanged( EFalse );
+
+ RMobileConferenceCall::TMobileConferenceStatus oldStatus = iStatus;
+TFLOGSTRING2("TSY: CMmConferenceCallTsy::CompleteNotifyConferenceStatusChange. oldStatus:%d", oldStatus );
+ iMmConferenceCallExtInterface->GetNewStatus( &iStatus );
+
+ switch( iStatus )
+ {
+ //new status is EConferenceIdle
+ case RMobileConferenceCall::EConferenceIdle:
+ //This might be caused by HangUp
+ CompleteHangUp( KErrNone );
+ //caps have changed
+ iCapsChanged = ETrue;
+ //status has changed
+ conferenceStatusChanged = ETrue;
+ //reset internal attributes
+ ResetAttributes();
+ break;
+ //new status is EConferenceActive
+ case RMobileConferenceCall::EConferenceActive:
+ // if previous status was EConferenceIdle
+ if ( oldStatus == RMobileConferenceCall::EConferenceIdle )
+ {
+ //is CreateConference request pending
+ if ( iTsyReqHandleStore->GetTsyReqHandle(
+ EMultimodeConferenceCallCreateConference ) > 0 )
+ {
+ //CreateConference handling
+ CompleteCreateConference( KErrNone );
+ }
+ //status has changed
+ conferenceStatusChanged = ETrue;
+ }
+ //if previous state was EConferenceHold
+ else if ( oldStatus == RMobileConferenceCall::EConferenceHold )
+ {
+ //is AddCall request pending
+ if ( iTsyReqHandleStore->
+ GetTsyReqHandle( EMultimodeConferenceCallAddCall ) > 0 )
+ {
+ //AddCall handling
+ CompleteAddCall ( KErrNone );
+ }
+ //is Swap request pending.
+ else if ( iTsyReqHandleStore->
+ GetTsyReqHandle( EMultimodeConferenceCallSwap ) > 0 )
+ {
+ //resuming held conference call.
+ CompleteSwap ( KErrNone );
+ }
+ //status has changed
+ conferenceStatusChanged = ETrue;
+ }
+ break;
+ //new status is EConferenceHold
+ case RMobileConferenceCall::EConferenceHold:
+ //Complete Swap
+ CompleteSwap ( KErrNone );
+ //status has changed
+ conferenceStatusChanged = ETrue;
+ break;
+ default:
+ //nothing to do
+ break;
+ }
+
+ //get TSY req handle.
+ TTsyReqHandle reqHandle = iTsyReqHandleStore->GetTsyReqHandle(
+ EMultimodeConferenceCallStatusChangeNotification );
+
+ if ( ( EMultimodeConferenceCallReqHandleUnknown != reqHandle ) &&
+ conferenceStatusChanged )
+ {
+TFLOGSTRING2("TSY: CMmConferenceCallTsy::CompleteNotifyConferenceStatusChange. Cur. iStatus:%d", iStatus );
+ //reset req handle.
+ iTsyReqHandleStore->ResetTsyReqHandle(
+ EMultimodeConferenceCallStatusChangeNotification );
+ *iRetStatus = iStatus;
+ ReqCompleted( reqHandle, KErrNone );
+ }
+
+ if ( iCapsChanged )
+ {
+ //if conference caps are not 0, notify it
+ if ( 0 != iConferenceCaps )
+ {
+ CompleteNotifyCapsChange( iConferenceCaps );
+ }
+ else
+ {
+ //Otherwise we still have to check that is Conference creation
+ //now possible
+ CheckConferenceCapability();
+ //If CreateConference is now possible, iConferenceCaps is not 0.
+ //Completion has already been done.
+ if ( 0 == iConferenceCaps )
+ {
+ //Otherwise we have to complete the caps change with 0 value.
+ CompleteNotifyCapsChange( iConferenceCaps );
+ }
+ }
+
+ iCapsChanged = EFalse;
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::NotifyConferenceEvent
+// Allows a client to be notified when a conference call event occurs.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::NotifyConferenceEvent(
+ RMobileConferenceCall::TMobileConferenceEvent* aEvent,
+ TName* aCallName )
+ {
+ iRetConferenceEventCallName = aCallName;
+ iRetConferenceEvent = aEvent;
+
+ iReqHandleType = EMultimodeConferenceCallConferenceEventNotification;
+
+ return KErrNone;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::NotifyConferenceEventCancel
+// Cancels an outstanding asynchronous NotifyConferenceEvent request.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::NotifyConferenceEventCancel(
+ const TTsyReqHandle aTsyReqHandle )
+ {
+ iRetConferenceEventCallName = NULL;
+ iRetConferenceEvent = NULL;
+
+ iTsyReqHandleStore->ResetTsyReqHandle(
+ EMultimodeConferenceCallConferenceEventNotification );
+
+ ReqCompleted( aTsyReqHandle, KErrCancel );
+ return KErrNone;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::CompleteNotifyConferenceEvent
+// Completes conference event notification.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallTsy::CompleteNotifyConferenceEvent(
+ const TName& aName,
+ RMobileConferenceCall::TMobileConferenceEvent aEvent )
+ {
+TFLOGSTRING2("TSY: CMmConferenceCallTsy::CompleteNotifyConferenceEvent.aEvent:%d", aEvent );
+ //reset req handle. Returns the deleted req handle
+ TTsyReqHandle reqHandle = iTsyReqHandleStore->ResetTsyReqHandle(
+ EMultimodeConferenceCallConferenceEventNotification );
+
+ //if req handle was set
+ if ( EMultimodeConferenceCallReqHandleUnknown != reqHandle )
+ {
+ //copy name of the call to which the event happened to the requested
+ //address
+ iRetConferenceEventCallName->Copy( aName );
+ //copy event to the requested address
+ *iRetConferenceEvent = aEvent;
+
+ ReqCompleted( reqHandle, KErrNone );
+ }
+
+ //if event was add
+ if ( aEvent == RMobileConferenceCall::EConferenceCallAdded )
+ {
+
+ // inform the call object that it is now part of the conference
+ CMmCallTsy* addedCall = iMmPhone->CallList()-> GetMmCallByName(
+ &aName );
+ if ( addedCall )
+ {
+ addedCall->SetPartOfConference( ETrue );
+ }
+
+ //increment iNumOfCallsInConferenceCall
+ iNumOfCallsInConferenceCall++;
+ }
+
+ //if event was removed
+ else if ( aEvent == RMobileConferenceCall::EConferenceCallRemoved )
+ {
+
+ // inform the call object that it is not part of the conference anymore
+ CMmCallTsy* removedCall = iMmPhone->CallList()->GetMmCallByName(
+ &aName );
+ if ( removedCall )
+ {
+ removedCall->SetPartOfConference( EFalse );
+ }
+
+ //decrement iNumOfCallsInConferenceCall
+ iNumOfCallsInConferenceCall--;
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::IsGoOneToOneSupported
+// Checks if given call can be splitted from the conference call.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TBool CMmConferenceCallTsy::IsGoOneToOneSupported(
+ TInt aCallId )
+ {
+ TBool supported( EFalse );
+
+ //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.
+ TInt ret = iMmConferenceCallExtInterface->IsGoOneToOneSupported(
+ aCallId, iStatus, iMmPhone->CallList() );
+
+ if ( KErrNone == ret )
+ {
+ //GoOneToOne is supported to this call
+ supported = ETrue;
+ }
+
+ return supported;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::GetActiveConferenceCallExtension
+// Returns a pointer to the active conference call extension.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+CMmConferenceCallExtInterface* CMmConferenceCallTsy::GetActiveConferenceCallExtension()
+ {
+
+ return iMmConferenceCallExtInterface;
+
+ }
+
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::SetActiveConferenceCallExtension
+// Sets active Conference call extension.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::SetActiveConferenceCallExtension(
+ CMmConferenceCallExtInterface* aMmConferenceCallExt )
+ {
+ // Used if active conference call extension pointer is NULL
+ TInt ret( KErrGeneral );
+
+ //if not null
+ if ( aMmConferenceCallExt )
+ {
+ //set pointer
+ iMmConferenceCallExtInterface = aMmConferenceCallExt;
+ ret = KErrNone;
+ }
+
+ return ret;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::CheckConferenceCapability
+// Checks if conference call creation is possible. The request
+// is directed to the active extension which can make the decision.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallTsy::CheckConferenceCapability()
+ {
+
+ //Let extension decide if conference call creation is possible.
+ iMmConferenceCallExtInterface->CheckConferenceCapability(
+ iStatus, iMmPhone->CallList() );
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::NumberOfCallsInConference
+// This method returns the number of calls that are currently part of
+// the conference call. For internal use.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmConferenceCallTsy::NumberOfCallsInConference() const
+ {
+
+ return iNumOfCallsInConferenceCall;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::ServiceRequested
+// Returns ETrue if this service is pending on conference call object
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TBool CMmConferenceCallTsy::ServiceRequested(
+ CMmConferenceCallTsy::TConferenceCallRequestTypes aReqType )
+ {
+ TBool ret( EFalse );
+
+ //if req handle is found from req handle store
+ if ( CMmConferenceCallTsy::EMultimodeConferenceCallReqHandleUnknown !=
+ iTsyReqHandleStore->GetTsyReqHandle( aReqType ) )
+ {
+ //set value to ETrue -> request is pending
+ ret = ETrue;
+ }
+
+ return ret;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::CallStatusChanged
+// After the status of a single call has changed, extension decides if
+// the status of the conference call should be changed as well.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallTsy::CallStatusChanged(
+ RMobileCall::TMobileCallStatus aNewStatus,
+ TInt aCallId )
+ {
+ // only releasing, holding and connecting a call can cause a change
+ // of conference status
+ if ( ( RMobileCall::EStatusIdle == aNewStatus ) ||
+ ( RMobileCall::EStatusHold == aNewStatus ) ||
+ ( RMobileCall::EStatusConnected == aNewStatus ) )
+ {
+ TBool conferenceStatusChanged = iMmConferenceCallExtInterface->
+ CallStatusChanged( aNewStatus, aCallId );
+
+ if ( conferenceStatusChanged )
+ {
+ CompleteNotifyConferenceStatusChange();
+ }
+ }
+
+ //conference call creation might be possible, check it.
+ CheckConferenceCapability();
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::Phone
+// Returns pointer to the Multimode Phone object. For internal use.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+CMmPhoneTsy* CMmConferenceCallTsy::Phone()
+ {
+
+ return iMmPhone;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::ResetAttributes
+// Resets internal attributes of Conference call object. Calls also protocol
+// extension to do the same.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallTsy::ResetAttributes()
+ {
+TFLOGSTRING("TSY: CMmConferenceCallTsy::ResetAttributes." );
+ //Name of the call to be added to Conference call
+ iAddCallName.Zero();
+ //Conference call capabilities
+ iConferenceCaps = 0;
+ //Number of calls in conference call
+ iNumOfCallsInConferenceCall = 0;
+ //Last used req handle type
+ iReqHandleType = EMultimodeConferenceCallReqHandleUnknown;
+ //Conference call status
+ iStatus = RMobileConferenceCall::EConferenceIdle;
+ //Reset pointer
+ iHoldCall = NULL;
+ //Reset pointer
+ iConnectedCall = NULL;
+
+ if ( 0 != iTsyReqHandleStore->GetTsyReqHandle(
+ EMultimodeConferenceCallAddCall ) )
+ {
+ TInt error = CMmCommonStaticUtility::EpocErrorCode(
+ KErrEtelCallNotActive, KErrMMEtelCallTerminated );
+ CompleteAddCall( error );
+ }
+ if ( 0 != iTsyReqHandleStore->GetTsyReqHandle(
+ EMultimodeConferenceCallCreateConference ) )
+ {
+ TInt error = CMmCommonStaticUtility::EpocErrorCode(
+ KErrEtelCallNotActive, KErrMMEtelCallTerminated );
+ CompleteCreateConference( error );
+ }
+ if ( 0 != iTsyReqHandleStore->GetTsyReqHandle(
+ EMultimodeConferenceCallSwap ) )
+ {
+ TInt error = CMmCommonStaticUtility::EpocErrorCode(
+ KErrEtelCallNotActive, KErrMMEtelCallTerminated );
+ CompleteSwap( error );
+ }
+
+ //Direct reset also to the extension
+ iMmConferenceCallExtInterface->ResetAttributes();
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::Caps
+// This function returns conference call capabilities. For internal use.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TUint32 CMmConferenceCallTsy::Caps() const
+ {
+
+ //return conference call caps
+ return iConferenceCaps;
+
+ }
+
+#ifdef REQHANDLE_TIMER
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::SetTypeOfResponse
+// Sets the type of response for a given Handle. Automatic
+// mode includes an automatic response in case of no response
+// from the DOS in a specified time
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallTsy::SetTypeOfResponse(
+ const TInt aReqHandleType,
+ const TTsyReqHandle aTsyReqHandle )
+ {
+ TInt timeOut( 0 );
+
+ switch ( aReqHandleType )
+ {
+ case EMultimodeConferenceCallCreateConference:
+ timeOut = KMmConferenceCallCreateConferenceTimeOut;
+ break;
+ case EMultimodeConferenceCallAddCall:
+ timeOut = KMmConferenceCallAddCallTimeOut;
+ break;
+ case EMultimodeConferenceCallSwap:
+ timeOut = KMmConferenceCallSwapTimeOut;
+ break;
+ case EMultimodeConferenceCallHangUp:
+ timeOut = KMmConferenceCallHangUpTimeOut;
+ break;
+ //Can't use timer:
+ // - all notifications
+ //case EMultimodeConferenceCallStatusChangeNotification:
+ //case EMultimodeConferenceCallCapsChangeNotification:
+ //case EMultimodeConferenceCallConferenceEventNotification:
+ default:
+ iTsyReqHandleStore->SetTsyReqHandle(
+ aReqHandleType, aTsyReqHandle );
+ break;
+ }
+
+ //if timeout is requested
+ if ( timeOut > 0 )
+ {
+ //set time out
+ iTsyReqHandleStore->SetTsyReqHandle(
+ aReqHandleType, aTsyReqHandle, timeOut );
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::Complete
+// Completes the request due timer expiration.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallTsy::Complete(
+ TInt aReqHandleType,
+ TInt aError )
+ {
+ //All possible TSY req handle types of Conference call are listed in the
+ //switch case below.
+
+ switch( aReqHandleType )
+ {
+ case EMultimodeConferenceCallCreateConference:
+ CompleteCreateConference( aError );
+ break;
+ case EMultimodeConferenceCallAddCall:
+ CompleteAddCall( aError );
+ break;
+ case EMultimodeConferenceCallSwap:
+ CompleteSwap( aError );
+ break;
+ case EMultimodeConferenceCallHangUp:
+ CompleteHangUp( aError );
+ break;
+ //Can't use timer:
+ // - all notifications
+ //case EMultimodeConferenceCallStatusChangeNotification:
+ //case EMultimodeConferenceCallCapsChangeNotification:
+ //case EMultimodeConferenceCallConferenceEventNotification:
+ default:
+ ReqCompleted( iTsyReqHandleStore->ResetTsyReqHandle(
+ aReqHandleType ), aError );
+ break;
+ }
+
+ }
+#endif // REQHANDLE_TIMER
+
+#ifdef TF_LOGGING_ENABLED
+// ---------------------------------------------------------------------------
+// CMmConferenceCallTsy::ReqCompleted
+// Overrides CTelObject::ReqCompleted for test logging purposes.
+// It prints the aTsyReqHandle and aError variable in the log file and then
+// calls CTelObject::ReqCompleted.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmConferenceCallTsy::ReqCompleted(
+ const TTsyReqHandle aTsyReqHandle,
+ const TInt aError )
+ {
+ TFLOGSTRING3("TSY: CMmConferenceCallTsy::Request Completed. \n\t\t\tHandle:%d\n\t\t\t Error:%d",
+ aTsyReqHandle, aError);
+
+ //call original ReqCompleted from CTelObject
+ CTelObject::ReqCompleted( aTsyReqHandle, aError );
+
+ }
+#endif // TF_LOGGING_ENABLED
+
+
+// End of File