--- a/telephonyserverplugins/common_tsy/commontsy/src/mmtsy/cmmconferencecalltsy.cpp Mon May 03 13:37:20 2010 +0300
+++ b/telephonyserverplugins/common_tsy/commontsy/src/mmtsy/cmmconferencecalltsy.cpp Thu May 06 15:10:38 2010 +0100
@@ -1,1769 +1,1769 @@
-// 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():
- iReqHandleType(EMultimodeConferenceCallReqHandleUnknown)
- {
- }
-
-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 );
-
- // Ensure the ReqHandleType is unset.
- // This will detect cases where this method indirectly calls itself
- // (e.g. servicing a client call that causes a self-reposting notification to complete and thus repost).
- // Such cases are not supported because iReqHandleType is in the context of this class instance,
- // not this request, and we don't want the values set by the inner request and the outer request
- // interfering with each other.
- __ASSERT_DEBUG(iReqHandleType==EMultimodeConferenceCallReqHandleUnknown, User::Invariant());
-
- //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
- // We've finished with this value now. Clear it so it doesn't leak
- // up to any other instances of this method down the call stack
- iReqHandleType = EMultimodeConferenceCallReqHandleUnknown;
- }
-
- 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;
- //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
+// 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():
+ iReqHandleType(EMultimodeConferenceCallReqHandleUnknown)
+ {
+ }
+
+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 );
+
+ // Ensure the ReqHandleType is unset.
+ // This will detect cases where this method indirectly calls itself
+ // (e.g. servicing a client call that causes a self-reposting notification to complete and thus repost).
+ // Such cases are not supported because iReqHandleType is in the context of this class instance,
+ // not this request, and we don't want the values set by the inner request and the outer request
+ // interfering with each other.
+ __ASSERT_DEBUG(iReqHandleType==EMultimodeConferenceCallReqHandleUnknown, User::Invariant());
+
+ //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
+ // We've finished with this value now. Clear it so it doesn't leak
+ // up to any other instances of this method down the call stack
+ iReqHandleType = EMultimodeConferenceCallReqHandleUnknown;
+ }
+
+ 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;
+ //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