diff -r 000000000000 -r 3553901f7fa8 telephonyserverplugins/common_tsy/commontsy/src/mmtsy/cmmlinetsy.cpp --- /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 +#include +#include + + +// ======== 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 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(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