telephonyserverplugins/common_tsy/commontsy/src/mmtsy/cmmlinetsy.cpp
changeset 0 3553901f7fa8
child 24 6638e7f4bd8f
child 42 3adadc800673
--- /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