--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyserverplugins/common_tsy/commontsy/src/mmtsy/cmmlinetsy.cpp Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,1262 @@
+// 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 "cmmlinetsy.h"
+#include "cmmphonetsy.h"
+#include "cmmcalltsy.h"
+#include "cmmlinelist.h"
+#include "cmmcalllist.h"
+#include "cmmtsyreqhandlestore.h"
+#include "MmTsy_numberOfSlots.h"
+#include <ctsy/tflogger.h>
+#include <ctsy/pluginapi/cmmdatapackage.h>
+#include <et_struct.h>
+
+
+// ======== MEMBER FUNCTIONS ========
+
+CMmLineTsy::CMmLineTsy()
+ {
+ }
+
+void CMmLineTsy::ConstructL()
+ {
+ TFLOGSTRING("TSY: CMmLineTsy::ConstructL");
+ //Initialise miscellaneous internal attributes
+ InitInternalAttributesL();
+
+ // Create and store a Call Object for incoming calls.
+ TInt ret = CreateCallObjectForIncomingCall();
+
+ if ( KErrNone != ret )
+ {
+ //if this fails, incoming calls cannot be called -> leave
+ User::Leave( KErrNoMemory );
+ }
+
+ //create req handle store
+ iTsyReqHandleStore = CMmTsyReqHandleStore::NewL(
+ EMultimodeLineMaxNumOfRequests, iLineReqHandles );
+ }
+
+CMmLineTsy::~CMmLineTsy()
+ {
+ TFLOGSTRING2("TSY: CMmLineTsy::~CMmLineTsy. Line name: %S", &iLineName);
+
+ //delete req handle store
+ delete iTsyReqHandleStore;
+
+ //delete incoming call object
+ if ( iCallForIncomingCall )
+ {
+ iCallForIncomingCall->Close();
+ }
+
+ // Remove all calls still open from this line
+ iMmPhone->CallList()->RemoveCallsByLine( &iLineName );
+
+ //Inform phone that this line has been removed.
+ iMmPhone->RemoveLine( iLineName );
+
+ iMmPhone = NULL;
+ iCallForIncomingCall = NULL;
+ iRetLineStatus = NULL;
+ iRetCaps = NULL;
+ iRetIncomingCallName = NULL;
+ iRetCallAdded = NULL;
+ iRetMobileLineStatus = NULL;
+ iTsyReqHandleStore = NULL;
+ iMessageManager = NULL;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::OpenNewObjectByNameL
+// Returns a pointer to an existing call. The TSY classes must not use this
+// method. This method is called when the client uses RCall::OpenExistingCall
+// method.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+CTelObject* CMmLineTsy::OpenNewObjectByNameL(
+ const TDesC& aName )
+ {
+ TFLOGSTRING2("TSY: CMmLineTsy::OpenNewObjectByNameL %S", &aName);
+
+ TName mmCallName( aName );
+ CMmCallTsy* mmCall = iMmPhone->CallList()->GetMmCallByName( &mmCallName );
+
+ //if not found, Leave...
+ if ( NULL == mmCall )
+ {
+ User::Leave( KErrNotFound );
+ }
+ else
+ {
+ //Update iUnownedCallObject flag
+ mmCall->SetUnownedCallObjectFlag( EFalse );
+ }
+
+ return mmCall;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::InitInternalAttributesL
+// Initialises miscellaneous internal attributes.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmLineTsy::InitInternalAttributesL()
+ {
+ // Set object attributes
+ iLineStatus = RCall::EStatusIdle;
+ iMobileLineStatus = RMobileCall::EStatusIdle;
+
+ //reset the name for answering call
+ iNameOfCallForAnswering.Zero();
+
+ iNumCalls = 0; // Number of calls created from line;
+ iCallSequenceNumber = 0; // The sequence number for the calls
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::CallObjectForIncomingCall
+// This method returns a Call object that is used for a new incoming call.
+// If there are no incoming calls this method creates a new call object.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+CMmCallTsy* CMmLineTsy::CallObjectForIncomingCall()
+ {
+ CMmCallTsy* callForIncomingCall = NULL;
+
+ if ( iCallForIncomingCall == NULL )
+ {
+ CreateCallObjectForIncomingCall();
+ }
+
+ callForIncomingCall = iCallForIncomingCall;
+
+ return callForIncomingCall;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::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 CMmLineTsy::ReqModeL(
+ const TInt aIpc )
+ {
+ TFLOGSTRING2("TSY: CMmLineTsy::ReqModeL IPC:%d",aIpc);
+
+ CTelObject::TReqMode ret( 0 ); // default return value
+
+ switch( aIpc )
+ {
+ // Non-flow control requests
+ // 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 EEtelLineGetStatus:
+ case EEtelLineGetCaps:
+ case EEtelLineGetCallInfo:
+ case EEtelLineGetInfo:
+ case EEtelLineGetHookStatus:
+ case EMobileLineGetMobileLineStatus:
+
+ //Other methods that do not use DOS and return immediately.
+ //Flow control not required.
+ case EEtelLineEnumerateCall:
+
+ //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.
+ break;
+ // Flow Controlled Services
+ // KReqModeFlowControlObeyed
+ // Commands that change the state of the phone, e.g. clearing the AoC
+ // counter; are commands that the TSY should only deal with one at
+ // a time.
+
+ // ret = KReqModeFlowControlObeyed;
+ // break;
+
+ // ReqModePostImmediately
+ // Requests that notify a client about a change of state, where the
+ // TSY needs to distinguish between different clients.
+ //ret=KReqModeRePostImmediately;
+ //break;
+
+ // 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;
+ //break;
+
+ // KReqModeMultipleCompletionEnabled | KReqModeFlowControlObeyed
+ // A command that may take some time and which the TSY can only deal
+ // with one at a time.
+ //ret = KReqModeMultipleCompletionEnabled |
+ // KReqModeFlowControlObeyed;
+ //break;
+
+ // Notification Requests
+ // 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 EEtelLineNotifyStatusChange:
+ case EEtelLineNotifyCallAdded:
+ case EETelLineCapsChangeNotification:
+ case EEtelLineNotifyHookChange:
+ case EEtelLineNotifyIncomingCall:
+ case EMobileLineNotifyMobileLineStatusChange:
+ 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: Call CLineBase's ReqModeL.
+ default:
+ ret = CLineBase::ReqModeL( aIpc );
+ break;
+ }
+
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::ExtFunc
+// TRAP's all CMmLineTsy related MM API requests in cases that they fail. This
+// method functions only as a centralized TRAP for the DoExtFuncL method that
+// does the actual mapping of IPC number to TSY method call.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::ExtFunc(
+ const TTsyReqHandle aTsyReqHandle,
+ const TInt aIpc,
+ const TDataPackage& aPackage )
+ {
+ TInt ret( KErrNone );
+ TInt trapError( KErrNone );
+
+ //reset last tsy request type
+ iReqHandleType = EMultimodeLineReqHandleUnknown;
+
+ //Original code continues here.
+ TRAP( trapError, ret = DoExtFuncL( aTsyReqHandle, aIpc, aPackage ); );
+
+ if ( trapError != KErrNone )
+ {
+ // Object cannot be created.
+ ReqCompleted( aTsyReqHandle, trapError );
+ }
+ else if ( ret != KErrNone )
+ {
+ ReqCompleted( aTsyReqHandle, ret );
+ }
+
+ //save request handle
+ if ( EMultimodeLineReqHandleUnknown != iReqHandleType )
+ {
+ iTsyReqHandleStore->SetTsyReqHandle( iReqHandleType, aTsyReqHandle );
+ }
+
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::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 CMmLineTsy::DoExtFuncL(
+ const TTsyReqHandle aTsyReqHandle,
+ const TInt aIpc,
+ const TDataPackage& aPackage )
+ {
+ TFLOGSTRING3("TSY: CMmLineTsy::DoExtFuncL IPC:%d Handle:%d", aIpc, \
+ aTsyReqHandle);
+
+ TInt ret ( KErrNone );
+
+ 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 )
+ {
+ // Mobile Line Status
+ // Get Mobile Line Status
+ case EMobileLineGetMobileLineStatus:
+ ret = GetMobileLineStatus( aTsyReqHandle,
+ REINTERPRET_CAST( RMobileCall::TMobileCallStatus*, dataPtr ) );
+ break;
+ //Notify Change of Mobile Line Status
+ case EMobileLineNotifyMobileLineStatusChange:
+ ret = NotifyMobileLineStatusChange(
+ REINTERPRET_CAST( RMobileCall::TMobileCallStatus*, dataPtr ) );
+ break;
+ default:
+ ret = KErrNotSupported;
+ break;
+ }
+
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::CreateNewCallName
+// Creates a new name for the call, which is the name of the line followed by
+// a call sequence number.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::CreateNewCallName(
+ TDes& aNewName )
+ {
+ // buffer for the name
+ TBuf<KMaxName> buf;
+ // append line name first
+ buf.Append( iLineName );
+ // append call sequence number next
+ buf.AppendNum( IncrementCallSequenceNumber() );
+ // copy the created name
+ aNewName.Copy( buf );
+
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::IncrementCallSequenceNumber
+// Returns the sequence number of the call created from this line. This
+// sequence number will be resetted when this line object is deleted. TInt
+// allows the value to increment to the value 2^32.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TUint CMmLineTsy::IncrementCallSequenceNumber()
+ {
+ // increment call sequence number
+ iCallSequenceNumber++;
+ return iCallSequenceNumber;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::EnumerateCall
+// This CORE API method returns the number of calls opened from a line. The
+// number of calls will be stored in the aCount pointer.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::EnumerateCall(
+ const TTsyReqHandle aTsyReqHandle,
+ TInt* aCount )
+ {
+ *aCount = iNumCalls;
+ ReqCompleted( aTsyReqHandle, KErrNone );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::DecrementNumberOfCalls
+// Decrements number of calls opened from a line by one.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmLineTsy::DecrementNumberOfCalls()
+ {
+ if ( iNumCalls > 0 )
+ {
+ iNumCalls--;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::NotifyStatusChange
+// This CORE API method provides notification about a change in the line
+// status
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::NotifyStatusChange(
+ const TTsyReqHandle aTsyReqHandle,
+ RCall::TStatus* aLineStatus )
+ {
+ iRetLineStatus = aLineStatus;
+ iTsyReqHandleStore->SetTsyReqHandle( EMultimodeLineNotifyStatusChange,
+ aTsyReqHandle );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::NotifyStatusChangeCancel
+// This CORE API method cancels an outstanding line status change notification
+// request, placed using the NotifyStatusChange() method.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::NotifyStatusChangeCancel(
+ const TTsyReqHandle aTsyReqHandle )
+ {
+ iRetLineStatus = NULL;
+ iTsyReqHandleStore->ResetTsyReqHandle( EMultimodeLineNotifyStatusChange );
+ ReqCompleted( aTsyReqHandle, KErrCancel );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::CompleteNotifyStatusChange
+// This method is used to notify to the client about the line status change.
+// This method should only be called by the CMmCallTsy's
+// CompleteNotifyStatusChange method to guaratee that this is functioning
+// right.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmLineTsy::CompleteNotifyStatusChange()
+ {
+ TInt ret( KErrNone );
+ TBool coreStatusChanged( EFalse );
+ TBool mobileStatusChanged( EFalse );
+ RCall::TStatus tempCoreStatus( RCall::EStatusIdle );
+ RMobileCall::TMobileCallStatus tempMobileStatus(
+ RMobileCall::EStatusIdle );
+ TInt numberOfObjectsInCallList = iMmPhone->CallList()->
+ GetNumberOfObjects();
+
+ for ( TInt i = 0; i < numberOfObjectsInCallList; i++ )
+ {
+ CMmCallTsy* mmCall = iMmPhone->CallList()->GetMmCallByIndex(i);
+
+ //check that the call object has been opened from this line
+ if ( mmCall->Line() == this )
+ {
+ RMobileCall::TMobileCallStatus mobileStatus
+ = mmCall->MobileCallStatus();
+ switch( mobileStatus )
+ {
+ case RMobileCall::EStatusUnknown:
+ tempCoreStatus = RCall::EStatusUnknown;
+ tempMobileStatus = RMobileCall::EStatusUnknown;
+ //get out of loop, resulting status is unknown...
+ i = numberOfObjectsInCallList;
+ break;
+ case RMobileCall::EStatusConnected:
+ tempCoreStatus = RCall::EStatusConnected;
+ tempMobileStatus = RMobileCall::EStatusConnected;
+ //get out of loop, resulting status is unknown...
+ i = numberOfObjectsInCallList;
+ break;
+ case RMobileCall::EStatusRinging:
+ //update core status
+ if ( tempCoreStatus == RCall::EStatusIdle )
+ {
+ tempCoreStatus = RCall::EStatusRinging;
+ }
+ //update mobile status
+ if ( tempMobileStatus == RMobileCall::EStatusIdle ||
+ tempMobileStatus == RMobileCall::EStatusHold)
+ {
+ tempMobileStatus = mobileStatus;
+ }
+ break;
+ case RMobileCall::EStatusDialling:
+ if ( tempCoreStatus == RCall::EStatusIdle )
+ {
+ tempCoreStatus = RCall::EStatusDialling;
+ }
+ //update mobile status
+ if ( tempMobileStatus == RMobileCall::EStatusIdle ||
+ tempMobileStatus == RMobileCall::EStatusHold)
+ {
+ tempMobileStatus = mobileStatus;
+ }
+ break;
+ case RMobileCall::EStatusAnswering:
+ if ( tempCoreStatus == RCall::EStatusIdle ||
+ tempCoreStatus == RCall::EStatusRinging )
+ {
+ tempCoreStatus = RCall::EStatusAnswering;
+ }
+ //update mobile status
+ if ( tempMobileStatus == RMobileCall::EStatusIdle ||
+ tempMobileStatus == RMobileCall::EStatusRinging ||
+ tempMobileStatus == RMobileCall::EStatusHold )
+ {
+ tempMobileStatus = mobileStatus;
+ }
+ break;
+ case RMobileCall::EStatusConnecting:
+ if ( tempCoreStatus == RCall::EStatusIdle ||
+ tempCoreStatus == RCall::EStatusDialling )
+ {
+ tempCoreStatus = RCall::EStatusConnecting;
+ }
+ //update mobile status
+ if ( tempMobileStatus == RMobileCall::EStatusIdle ||
+ tempMobileStatus == RMobileCall::EStatusDialling ||
+ tempMobileStatus == RMobileCall::EStatusHold )
+ {
+ tempMobileStatus = mobileStatus;
+ }
+ break;
+ case RMobileCall::EStatusDisconnecting:
+ //update core status
+ if ( tempCoreStatus == RCall::EStatusIdle )
+ {
+ tempCoreStatus = RCall::EStatusHangingUp;
+ }
+ if ( tempMobileStatus == RMobileCall::EStatusIdle )
+ {
+ tempMobileStatus = mobileStatus;
+ }
+ break;
+ case RMobileCall::EStatusWaitingAlternatingCallSwitch:
+ if ( tempMobileStatus == RMobileCall::EStatusIdle )
+ {
+ tempMobileStatus = mobileStatus;
+ }
+ break;
+ case RMobileCall::EStatusHold:
+ if ( tempMobileStatus == RMobileCall::EStatusIdle ||
+ tempMobileStatus ==
+ RMobileCall::EStatusDisconnecting )
+ {
+ tempCoreStatus = iLineStatus;
+ tempMobileStatus = mobileStatus;
+ }
+ break;
+ case RMobileCall::EStatusIdle:
+ case RMobileCall::EStatusReconnectPending:
+ case RMobileCall::EStatusDisconnectingWithInband:
+ case RMobileCall::EStatusTransferring:
+ case RMobileCall::EStatusTransferAlerting:
+ default:
+ break;
+ }
+ }
+ }
+
+ //check if core status has changed
+ if ( tempCoreStatus != iLineStatus )
+ {
+ coreStatusChanged = ETrue;
+ iLineStatus = tempCoreStatus;
+ }
+
+ //check if mobile status has changed
+ if ( tempMobileStatus != iMobileLineStatus )
+ {
+ mobileStatusChanged = ETrue;
+ iMobileLineStatus = tempMobileStatus;
+ }
+
+ //get core status change notification req handle
+ TTsyReqHandle iNotifyStatusChangeHandle = iTsyReqHandleStore->
+ GetTsyReqHandle( EMultimodeLineNotifyStatusChange );
+
+ //if req handle available and status changed
+ if ( ( iNotifyStatusChangeHandle > 0 ) && coreStatusChanged )
+ {
+ *iRetLineStatus = iLineStatus;
+ iTsyReqHandleStore->ResetTsyReqHandle(
+ EMultimodeLineNotifyStatusChange );
+ ReqCompleted( iNotifyStatusChangeHandle, ret );
+ }
+
+ //get mobile status change notification req handle
+ TTsyReqHandle iNotifyMobileLineStatusChangeHandle = iTsyReqHandleStore->
+ GetTsyReqHandle( EMultimodeLineMobileLineStatusChange );
+
+ //if req handle available and status changed
+ if ( iNotifyMobileLineStatusChangeHandle > 0
+ && ( coreStatusChanged || mobileStatusChanged ) )
+ {
+ *iRetMobileLineStatus = iMobileLineStatus;
+ iTsyReqHandleStore->ResetTsyReqHandle(
+ EMultimodeLineMobileLineStatusChange );
+ ReqCompleted( iNotifyMobileLineStatusChangeHandle, ret );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::GetHookStatus
+// This CORE API method retrieves the current hook status. Method is not
+// currently supported,
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::GetHookStatus(
+ const TTsyReqHandle aTsyReqHandle,
+ RCall::THookStatus* )
+ {
+ ReqCompleted( aTsyReqHandle, KErrNotSupported );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::GetInfo
+// This CORE API method retrieves the current line information.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::GetInfo(
+ const TTsyReqHandle aTsyReqHandle,
+ RLine::TLineInfo* aLineInfo )
+ {
+ // The current hook status.
+ aLineInfo->iHookStatus = RCall::EHookStatusUnknown;
+ // The current line status.
+ aLineInfo->iStatus = iLineStatus;
+ // The name of the last call created on the line.
+ aLineInfo->iNameOfLastCallAdded = iNameOfLastCallAdded;
+ // The name of the call to which a new incoming call will be directed.
+ aLineInfo->iNameOfCallForAnswering = iNameOfCallForAnswering;
+
+ ReqCompleted( aTsyReqHandle, KErrNone );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::LineInfo
+// This method retrieves the current line information. The method is used by
+// MmPhone object.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+RPhone::TLineInfo CMmLineTsy::LineInfo() const
+ {
+ // Line info
+ RPhone::TLineInfo lineInfo;
+ // The current line status.
+ lineInfo.iStatus = iLineStatus;
+ // line capabilities
+ lineInfo.iLineCapsFlags = iLineCaps.iFlags;
+ // line name
+ lineInfo.iName = iLineName;
+
+ return lineInfo;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::NotifyCapsChange
+// This CORE API method provides notification of a change in the line
+// capabilities.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::NotifyCapsChange(
+ const TTsyReqHandle aTsyReqHandle,
+ RLine::TCaps* aCaps )
+ {
+ // On return, contains the new line capabilities
+ iRetCaps = aCaps;
+ iTsyReqHandleStore->SetTsyReqHandle( EMultimodeLineCapsChangeNotification,
+ aTsyReqHandle );
+
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::NotifyCapsChangeCancel
+// This CORE API method cancels an "line capabilities change" notification
+// request, placed using the NotifyCapsChange() method.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::NotifyCapsChangeCancel(
+ const TTsyReqHandle aTsyReqHandle )
+ {
+ iRetCaps = NULL;
+ iTsyReqHandleStore->ResetTsyReqHandle(
+ EMultimodeLineCapsChangeNotification );
+ ReqCompleted( aTsyReqHandle, KErrCancel );
+
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::CompleteNotifyCapsChange
+// This method is used to notify to the client about the capabilities change.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmLineTsy::CompleteNotifyCapsChange()
+ {
+ //reset req handle. Returns the deleted req handle
+ TTsyReqHandle reqHandle = iTsyReqHandleStore->ResetTsyReqHandle(
+ EMultimodeLineCapsChangeNotification );
+
+ if ( EMultimodeLineReqHandleUnknown != reqHandle )
+ {
+ *iRetCaps = iLineCaps;
+ ReqCompleted( reqHandle, KErrNone );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::NotifyIncomingCall
+// This CORE API method is used to notify a client when an incoming call is
+// detected.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::NotifyIncomingCall(
+ const TTsyReqHandle aTsyReqHandle,
+ TName* aName )
+ {
+ // On notification, contains the name of the incoming call.
+ iRetIncomingCallName = aName;
+ iTsyReqHandleStore->SetTsyReqHandle( EMultimodeLineNotifyIncomingCall,
+ aTsyReqHandle );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::NotifyIncomingCallCancel
+// This CORE API method cancels an outstanding incoming call notification,
+// placed with the NotifyIncomingCall() method.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::NotifyIncomingCallCancel(
+ const TTsyReqHandle aTsyReqHandle )
+ {
+ iRetIncomingCallName = NULL;
+ iTsyReqHandleStore->ResetTsyReqHandle( EMultimodeLineNotifyIncomingCall );
+ ReqCompleted( aTsyReqHandle, KErrCancel );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::NotifyCallAdded
+// This CORE API method provides notification that a new call has been added
+// to the line.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::NotifyCallAdded(
+ const TTsyReqHandle aTsyReqHandle,
+ TName* aName )
+ {
+ TFLOGSTRING2("TSY: CMmLineTsy::NotifyCallAdded requested by client, \
+ lineMode:%d", iLineMode);
+ // On return, contains the name of the new call.
+ iRetCallAdded = aName;
+ iTsyReqHandleStore->SetTsyReqHandle( EMultimodeLineNotifyCallAdded,
+ aTsyReqHandle );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::NotifyCallAddedCancel
+// This CORE API method cancels an outstanding "new call added" notification
+// request, placed using the NotifyCallAdded() method.(other items were
+// commented in a header).
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::NotifyCallAddedCancel(
+ const TTsyReqHandle aTsyReqHandle )
+ {
+ TFLOGSTRING("TSY: CMmLineTsy::NotifyCallAddedCancel requested by client");
+ iRetCallAdded = NULL;
+ iTsyReqHandleStore->ResetTsyReqHandle( EMultimodeLineNotifyCallAdded );
+ ReqCompleted( aTsyReqHandle, KErrCancel );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::CompleteNotifyCallAdded
+// This CORE API method is used to notify to the client that a call has been
+// added to the line. NOTE: Type is not defined because this method may be
+// called when incoming call occurs or when a call object has been created.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmLineTsy::CompleteNotifyCallAdded(const TDesC& aName )
+ {
+ TFLOGSTRING3("TSY: CMmLineTsy::CompleteNotifyCallAdded entered, \
+ CALL ADDED, Call name: %S, Call mode: %d", &aName, iLineMode );
+
+ //reset req handle. Returns the deleted req handle
+ TTsyReqHandle reqHandle = iTsyReqHandleStore->ResetTsyReqHandle(
+ EMultimodeLineNotifyCallAdded );
+
+ iNumCalls++;
+
+ if ( EMultimodeLineReqHandleUnknown != reqHandle )
+ {
+ TFLOGSTRING("TSY: CMmLineTsy::CompleteNotifyCallAdded, Completed!");
+ *iRetCallAdded = aName;
+ ReqCompleted( reqHandle, KErrNone );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::GetCaps
+// This CORE API method retrieves the line capabilities.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::GetCaps(
+ const TTsyReqHandle aTsyReqHandle,
+ RLine::TCaps* aCaps )
+ {
+ *aCaps = iLineCaps;
+ ReqCompleted( aTsyReqHandle, KErrNone );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::GetStatus
+// This CORE API method returns core line status information.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::GetStatus(
+ const TTsyReqHandle aTsyReqHandle,
+ RCall::TStatus* aStatus )
+ {
+ *aStatus = iLineStatus;
+ ReqCompleted( aTsyReqHandle, KErrNone );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::NotifyHookChange
+// This CORE API method provides notification when the hook status changes.
+// Feature is not supported.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::NotifyHookChange(
+ const TTsyReqHandle aTsyReqHandle,
+ RCall::THookStatus* )
+ {
+ ReqCompleted( aTsyReqHandle, KErrNotSupported );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::NotifyHookChangeCancel
+// This CORE API method cancels an outstanding hook change notification req
+// placed using the NotifyHookChange() method. Feature is not supported.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::NotifyHookChangeCancel(
+ const TTsyReqHandle aTsyReqHandle )
+ {
+ ReqCompleted( aTsyReqHandle, KErrNotSupported );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::GetCallInfo
+// This CORE API method returns information about a call.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::GetCallInfo(
+ const TTsyReqHandle aTsyReqHandle,
+ TCallInfoIndex* aCallInfoIndex )
+ {
+ TFLOGSTRING3("TSY: CMmLineTsy::GetCallInfo - Line name: %S, Index: %d",
+ &iLineName, aCallInfoIndex->iIndex );
+
+ TInt ret( KErrNotFound );
+
+ // Check if the call object can be found from call list by index
+ CMmCallTsy* mmCall = REINTERPRET_CAST( CMmCallTsy*,
+ iMmPhone->CallList()->GetMmCallByIndexAndLine(
+ aCallInfoIndex->iIndex, &iLineName ) );
+
+ // If call object was found, fill the client pointer with call information
+ if ( mmCall )
+ {
+ aCallInfoIndex->iInfo.iCallName = mmCall->CallName();
+ aCallInfoIndex->iInfo.iStatus = mmCall->Status();
+ aCallInfoIndex->iInfo.iCallCapsFlags = mmCall->CallCaps();
+
+ TFLOGSTRING3("TSY: CMmLineTsy::GetCallInfo - Call name: %S, Status: %d",
+ &aCallInfoIndex->iInfo.iCallName, aCallInfoIndex->iInfo.iStatus );
+
+ ret = KErrNone;
+ }
+
+ ReqCompleted( aTsyReqHandle, ret );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::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. Core API requests are directed to the
+// LineBase.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::CancelService(
+ const TInt aIpc,
+ const TTsyReqHandle aTsyReqHandle )
+ {
+ TInt ret( KErrNone );
+
+ // When the clients close their sub-sessions (eg. by calling RLine::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
+ // request numbers, one at a time, to the CancelService method in the TSY.
+
+ 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 XXX
+ // break;
+
+ //Cancel methods that are not supported
+ //case XXX:
+ // ret = KErrNotSupported;
+ // break;
+
+ //Notification Cancels, no special requirements.
+ case EMobileLineNotifyMobileLineStatusChange:
+ ret = NotifyMobileLineStatusChangeCancel( aTsyReqHandle );
+ break;
+ //Everything is taken care in the method implementation.
+ //Just direct the request to the method.
+ //case XXX:
+ // ret = XXXCancel( aTsyReqHandle );
+ // break;
+
+ default:
+ return CLineBase::CancelService( aIpc, aTsyReqHandle );
+ }
+
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::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 CMmLineTsy::RegisterNotification(
+ const TInt aIpc )
+ {
+ TInt ret( KErrNone );
+
+ switch ( aIpc )
+ {
+ case EEtelLineNotifyStatusChange:
+ case EEtelLineNotifyCallAdded:
+ case EETelLineCapsChangeNotification:
+ case EEtelLineNotifyHookChange:
+ case EEtelLineNotifyIncomingCall:
+ case EMobileLineNotifyMobileLineStatusChange:
+ ret = KErrNone;
+ break;
+ default:
+ // Unknown or invalid IPC
+ ret = KErrNotSupported;
+ }
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::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
+// 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 CMmLineTsy::DeregisterNotification(
+ const TInt aIpc )
+ {
+ TInt ret( KErrNone );
+
+ switch ( aIpc )
+ {
+ case EEtelLineNotifyStatusChange:
+ case EEtelLineNotifyCallAdded:
+ case EETelLineCapsChangeNotification:
+ case EEtelLineNotifyHookChange:
+ case EEtelLineNotifyIncomingCall:
+ case EMobileLineNotifyMobileLineStatusChange:
+ ret = KErrNone;
+ break;
+ default:
+ // Unknown or invalid IPC
+ ret = KErrNotSupported;
+ }
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::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 CMmLineTsy::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 a 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 EEtelLineNotifyStatusChange:
+ numberOfSlots = KMmLineStatusChangeSlots;
+ break;
+ case EEtelLineNotifyCallAdded:
+ numberOfSlots = KMmLineCallAddedSlots;
+ break;
+ case EETelLineCapsChangeNotification:
+ numberOfSlots = KMmLineCapsChangeSlots;
+ break;
+ case EEtelLineNotifyHookChange:
+ numberOfSlots = KMmLineHookChangeSlots;
+ break;
+ case EEtelLineNotifyIncomingCall:
+ numberOfSlots = KMmLineIncomingCallSlots;
+ break;
+ case EMobileLineNotifyMobileLineStatusChange:
+ numberOfSlots = KMmLineMobileLineStatusChangeSlots;
+ break;
+ default:
+ // Unknown or invalid Line IPC
+ User::Leave( KErrNotSupported );
+ break;
+ }
+ return numberOfSlots;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::LineMode
+// Returns line mode.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+RMobilePhone::TMobileService CMmLineTsy::LineMode() const
+ {
+ return iLineMode;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::LineName
+// Returns line name.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TName CMmLineTsy::LineName() const
+ {
+ return iLineName;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::GetMobileLineStatus
+// Returns the current status of the line through the aStatus argument. The
+// possible line states map to the call states (see MM API spec) so that a
+// line that has one or more calls opened from it will have a status defined
+// by this table.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::GetMobileLineStatus(
+ const TTsyReqHandle aTsyReqHandle,
+ RMobileCall::TMobileCallStatus* aStatus )
+ {
+ *aStatus = iMobileLineStatus;
+ ReqCompleted( aTsyReqHandle, KErrNone );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::NotifyMobileLineStatusChange
+// Allows a client to be notified when the mobile line changes state. The
+// request completes when the line changes state, the new state being copied
+// to the aStatus parameter.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::NotifyMobileLineStatusChange(
+ RMobileCall::TMobileCallStatus* aStatus )
+ {
+ iRetMobileLineStatus = aStatus;
+ iReqHandleType = EMultimodeLineMobileLineStatusChange;
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::NotifyMobileLineStatusChangeCancel
+// Cancels an outstanding asynchronous NotifyMobileLineStatusChange request.
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CMmLineTsy::NotifyMobileLineStatusChangeCancel(
+ const TTsyReqHandle aTsyReqHandle )
+ {
+ iRetMobileLineStatus = NULL;
+ iTsyReqHandleStore->ResetTsyReqHandle(
+ EMultimodeLineMobileLineStatusChange );
+ ReqCompleted( aTsyReqHandle, KErrCancel );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CMmLineTsy::CompleteNotifyAddBypassingCall
+// Handles ghost call object creation and initialisation. Also notifies
+// clients about the ghost call (using NotifyCallAdded method)
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CMmLineTsy::CompleteNotifyAddBypassingCall(
+ CMmDataPackage* aDataPackage )
+ {
+ TInt callId( -1 );
+ RMobilePhone::TMobileService callMode( RMobilePhone::EVoiceService );
+ RMobileCall::TMobileCallInfoV1* mobileCallInfo;
+
+ const CCallDataPackage* callData =
+ reinterpret_cast<const CCallDataPackage*>(aDataPackage);
+
+ callData->GetCallIdAndMode( callId, callMode );
+ callData->UnPackData ( &mobileCallInfo );
+
+ if ( mobileCallInfo->iStatus == RMobileCall::EStatusDialling ||
+ mobileCallInfo->iStatus == RMobileCall::EStatusConnecting ||
+ mobileCallInfo->iStatus == RMobileCall::EStatusConnected )
+ {
+ TFLOGSTRING2("TSY: CMmLineTsy::CompleteNotifyAddBypassingCall, \
+ CALL INITIATED - NOT REQUESTED BY ETEL's CLIENT, Call ID: %d",
+ callId );
+
+ //create new call object
+ CMmCallTsy* mmGhostCall = CreateGhostCallObject(
+ callId, callMode, mobileCallInfo->iStatus );
+
+ if ( mmGhostCall )
+ {
+ // Add the new call to the list of calls
+ TInt ret( iMmPhone->CallList()->AddObject( mmGhostCall ) );
+
+ if ( KErrNone == ret )
+ {
+ mmGhostCall->CompleteNotifyMobileCallInfoChange(
+ aDataPackage );
+ CompleteNotifyStatusChange();
+ //inform ETel client that someone is creating a MO call
+ CompleteNotifyCallAdded( mmGhostCall->CallName() );
+ mmGhostCall->SetGhostCall( ETrue );
+ }
+ else
+ {
+ delete mmGhostCall;
+ }
+ }
+ }
+ else
+ {
+ TFLOGSTRING3("TSY: CMmLineTsy::CompleteNotifyAddBypassingCall, \
+ CALL NOT INITIATED - Call ID:%d, Call status:%d",
+ callId, mobileCallInfo->iStatus);
+ }
+ }
+
+#ifdef TF_LOGGING_ENABLED
+// ---------------------------------------------------------------------------
+// CMmLineTsy::ReqCompleted
+// Overloads CTelObject::ReqCompleted for 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 CMmLineTsy::ReqCompleted(
+ const TTsyReqHandle aTsyReqHandle,
+ const TInt aError )
+ {
+ TFLOGSTRING3("TSY: CMmLineTsy::ReqCompleted Handle:%d Error:%d",
+ aTsyReqHandle, aError);
+
+ CTelObject::ReqCompleted(aTsyReqHandle,aError);
+ }
+
+#endif
+
+
+// End of File