--- a/telephonyserverplugins/simtsy/src/CSimLine.cpp Mon May 03 13:37:20 2010 +0300
+++ b/telephonyserverplugins/simtsy/src/CSimLine.cpp Thu May 06 15:10:38 2010 +0100
@@ -1,927 +1,927 @@
-
-// Copyright (c) 2001-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:
-// This file contains the implementation for the functionality common to all
-// the specific line classes, such as CSimVoiceLine and CSimDataline.
-//
-//
-
-/**
- @file
-*/
-
-#include <testconfigfileparser.h>
-#include "CSimLine.h"
-#include "CSimPhone.h"
-#include "CSimCall.h"
-#include "Simlog.h"
-#include "CSimPubSub.h"
-
-void CSimLine::CloseLine(TAny* aObj)
-/**
-* Utility func for cleanup stack
-*
-* @param aObj a pointer to the CObject to close
-*/
- {
- ((CObject*)aObj)->Close();
- }
-
-CSimLine::CSimLine(CSimPhone* aPhone)
- :iPhone(aPhone), iState(RMobileCall::EStatusIdle),
- iHookState(ConvertStateToHook(iState))
- {
- iNameOfLastCallAdded.Zero();
- iNotifyStatusChange.iNotifyPending = EFalse;
- iNotifyMobileStatusChange.iNotifyPending = EFalse;
- }
-
-void CSimLine::ConstructL(const TName& aName)
-/**
-* Second phase of two phase constructor.
-* Creates the System Agent object for incoming call notification and other notifications.
-*
-* @param aName name of the Line to be created.
-*/
- {
- LOGLINE2(">>CSimLine::ConstructL [aLineName=%S]", &aName);
- iLineName = aName;
- iSimPubSubIC = CSimPubSub::NewL(this,iICProperty);
- iSimPubSubIC->Start();
-
- iSimPubSubRH = CSimPubSub::NewL(this,iRHProperty);
- iSimPubSubRH->Start();
-
- iNotifyIncomingCallPause=this->CfgFile()->ItemValue(KNotifyIncomingCallPauseDuration,KDefaultNotifyIncomingCallPauseDuration);
-
- iTimer = CSimTimer::NewL(iPhone);
- LOGLINE1("<<CSimLine::ConstructL");
-}
-
-CSimLine::~CSimLine()
-/**
-* Standard destructor.
-*/
- {
- delete iSimPubSubIC;
- delete iSimPubSubRH;
- iTimer->Cancel();
- delete iTimer;
- }
-
-
-void CSimLine::UpdatePhoneNotifiers(CSimCall* aCall,TUint /*aStatus*/)
- {
- TInt count= iCalls->Count();
- TInt i=0;
- while(i<count)
- {
- if(iCalls->At(i) != aCall && (iCalls->At(i)->iState == RMobileCall::EStatusHold || iCalls->At(i)->iState == RMobileCall::EStatusConnected))
- iCalls->At(i)->UpdateNotifiers();
- i++;
- }
- }
-
-CTelObject::TReqMode CSimLine::ReqModeL(const TInt aIpc)
-/**
-* This function returns the Request Mode for the request with the passed IPC value.
-* The ETel Server provides a function for returning the standard request modes for
-* the Core API requests.
-* Multimode API requests mode are handled here.
-*
-* @param aIpc the IPc number representing the client request
-* @return CTelObject::TReqMode the request mode to be used for this IPc number
-* @leave Leaves if the IPc number is not found
-*/
- {
- // ReqModeL is called from the server's CTelObject::ReqAnalyserL
- // in order to check the type of request it has
-
- CTelObject::TReqMode reqMode=0;
- switch (aIpc)
- {
-//
-// No Flow Control NOR Multiple Completion
-//
- case EMobileLineGetMobileLineStatus:
- break;
-
-//
-// Multiple Completion Services with Immediate Server Repost
-// (Usually Notifications)
-//
- case EMobileLineNotifyMobileLineStatusChange:
- reqMode=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately;
- break;
-//
-// Must be a core API request so get request mode from Etel
-//
- default:
- reqMode=CLineBase::ReqModeL(aIpc);
- break;
- }
-
- return reqMode;
- }
-
-
-TInt CSimLine::NumberOfSlotsL(const TInt aIpc)
-/**
-* 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
-*
-* @param aIpc the IPc number representing the client request
-* @return TInt the number of slots required
-* @leave Leaves if the IPc number is not found
-*/
- {
- switch (aIpc)
- {
- case EMobileLineNotifyMobileLineStatusChange:
- LOGLINE1("CLineMobile: Registered with the default number of slots");
- return KDefaultNumberOfSlots;
-
- default:
- LOGLINE1("CSimLine::NumberOfSlotsL: No match for IPC, defering to base function");
- break;
- }
- return CLineBase::NumberOfSlotsL(aIpc);
- }
-
-
-TInt CSimLine::RegisterNotification(const TInt /*aIpc*/)
-/**
-* The ETel Server calls this function when the first client makes a notification request.
-* If supported by the underlying protocol controlling the signalling stack,
-* this can be used to start requesting updates for the relevant service.
-*/
- {
- return KErrNone;
- }
-
-TInt CSimLine::DeregisterNotification(const TInt /*aIpc*/)
-/**
-* The ETel Server calls this function when the last client that had previously
-* made a notification request closes its ETel Server handle. If supported by
-* the underlying protocol controlling the signalling stack, this can be used
-* to stop requesting updates for the relevant service.
-*/
- {
- return KErrNone;
- }
-
-void CSimLine::Init()
-/**
-* This function can be used to perform any necessary synchronous initialisation.
-*/
- {}
-
-TInt CSimLine::NotifyIncomingCall(const TTsyReqHandle aTsyReqHandle, TName* aName)
-/**
-* Register a client's interest in an incoming call notification.
-* Core ETel API Request.
-*
-* @param aTsyReqHandle Tsy Request handle for the client request
-* @param aName pointer to the name of the call
-* @return KErrNone
-*/
- {
- LOGLINE1(">>CSimLine::NotifyIncomingCall");
- iNotifyIncomingCall.iNotifyPending=ETrue;
- iNotifyIncomingCall.iNotifyHandle=aTsyReqHandle;
- iNotifyIncomingCall.iNotifyData=(TAny*)aName;
- LOGLINE1("<<CSimLine::NotifyIncomingCall");
- return KErrNone;
- }
-
-TInt CSimLine::NotifyIncomingCallCancel(const TTsyReqHandle /*aTsyReqHandle*/)
-/**
-* Cancels a client's interest in an incoming call.
-* Core ETel API Request.
-*
-* @param aTsyReqHandle Tsy Request handle for the client cancel request
-* @return KErrNone
-*/
- {
- LOGLINE1(">>CSimLine::NotifyIncomingCallCancel");
- if(iNotifyIncomingCall.iNotifyPending)
- {
- iTimer->Cancel();
- iNotifyIncomingCall.iNotifyPending=EFalse;
- ReqCompleted(iNotifyIncomingCall.iNotifyHandle, KErrCancel);
- }
- LOGLINE1("<<CSimLine::NotifyIncomingCallCancel");
- return KErrNone;
- }
-
-TInt CSimLine::NotifyHookChange(const TTsyReqHandle aTsyReqHandle, RCall::THookStatus* aHookStatus)
-/**
-* Record a client's interst in being notified when the line hook changes state.
-* Core ETel API Request.
-*
-* @param aTsyReqHandle Tsy Request handle for the client request
-* @param aHookStatus pointer to the line hook
-* @return KErrNone
-*/
- {
- LOGLINE1(">>CSimLine::NotifyHookChange");
- iNotifyHookChange.iNotifyPending=ETrue;
- iNotifyHookChange.iNotifyHandle=aTsyReqHandle;
- iNotifyHookChange.iNotifyData=(TAny*)aHookStatus;
- LOGLINE1("<<CSimLine::NotifyHookChange");
- return KErrNone;
- }
-
-TInt CSimLine::NotifyHookChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
-/**
-* Cancel a client's interest in being notified when the line hook changes state.
-* Core ETel API Request.
-*
-* @param aTsyReqHandle Tsy Request handle for the client cancel request
-* @return KErrNone
-*/
- {
- LOGLINE1(">>CSimLine::NotifyHookChangeCancel");
- if(iNotifyHookChange.iNotifyPending)
- {
- iNotifyHookChange.iNotifyPending=EFalse;
- ReqCompleted(iNotifyHookChange.iNotifyHandle,KErrCancel);
- }
- LOGLINE1("<<CSimLine::NotifyHookChangeCancel");
- return KErrNone;
- }
-
-
-TInt CSimLine::NotifyMobileLineStatusChange(const TTsyReqHandle aTsyReqHandle, RMobileCall::TMobileCallStatus* aStatus)
-/**
-* Record a client's interst in being notified when the line changes state. (Multimode)
-* MM ETel API Request.
-*
-* @param aTsyReqHandle Tsy Request handle for the client request
-* @param aStatus pointer to the line status
-* @return KErrNone
-*/
- {
- LOGLINE1(">>CSimLine::NotifyMobileLineStatusChange");
- iNotifyMobileStatusChange.iNotifyPending=ETrue;
- iNotifyMobileStatusChange.iNotifyHandle=aTsyReqHandle;
- iNotifyMobileStatusChange.iNotifyData=aStatus;
- LOGLINE1("<<CSimLine::NotifyMobileLineStatusChange");
- return KErrNone;
- }
-
-TInt CSimLine::NotifyMobileLineStatusChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
-/**
-* Cancel a client's interest in being notified when the line changes state.(Multimode Request)
-* MM ETel API Request.
-*
-* @param aTsyReqHandle Tsy Request handle for the client cancel request
-* @return KErrNone
-*/
- {
- LOGLINE1(">>CSimLine::NotifyMobileLineStatusChangeCancel");
- if(iNotifyMobileStatusChange.iNotifyPending)
- {
- iNotifyMobileStatusChange.iNotifyPending=EFalse;
- ReqCompleted(iNotifyMobileStatusChange.iNotifyHandle,KErrCancel);
- }
- LOGLINE1("<<CSimLine::NotifyMobileLineStatusChangeCancel");
- return KErrNone;
- }
-
-TInt CSimLine::NotifyStatusChange(const TTsyReqHandle aTsyReqHandle, RCall::TStatus* aStatus)
-/**
-* Record a client's interst in being notified when the line changes state. (Core)
-* Core ETel API Request.
-*
-* @param aTsyReqHandle Tsy Request handle for the client request
-* @param aStatus pointer to the line status
-* @return KErrNone
-*/
- {
- LOGLINE1(">>CSimLine::NotifyStatusChange");
- iNotifyStatusChange.iNotifyPending=ETrue;
- iNotifyStatusChange.iNotifyHandle=aTsyReqHandle;
- iNotifyStatusChange.iNotifyData=aStatus;
- LOGLINE1("<<CSimLine::NotifyStatusChange");
- return KErrNone;
- }
-
-TInt CSimLine::NotifyStatusChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
-/**
-* Cancel a client's interest in being notified when the line changes state.(Multimode Request)
-* Core ETel API Request.
-*
-* @param aTsyReqHandle Tsy Request handle for the client cancel request
-* @return KErrNone
-*/
- {
- LOGLINE1(">>CSimLine::NotifyStatusChangeCancel");
- if(iNotifyStatusChange.iNotifyPending)
- {
- iNotifyStatusChange.iNotifyPending=EFalse;
- ReqCompleted(iNotifyStatusChange.iNotifyHandle,KErrCancel);
- }
- LOGLINE1("<<CSimLine::NotifyStatusChangeCancel");
- return KErrNone;
- }
-
-TInt CSimLine::NotifyCallAdded(const TTsyReqHandle aTsyReqHandle,TName* aName)
-/**
-* Record a client's interest in being notified when a new call is added.
-* Core ETel API Request.
-*
-* @param aTsyReqHandle Tsy Request handle for the client request
-* @param aName pointer to the name of the call
-* @return KErrNone
-*/
- {
- LOGLINE1(">>CSimLine::NotifyCallAdded");
- iNotifyCallAdded.iNotifyPending=ETrue;
- iNotifyCallAdded.iNotifyHandle=aTsyReqHandle;
- iNotifyCallAdded.iNotifyData=(TAny*)aName;
- LOGLINE1("<<CSimLine::NotifyCallAdded");
- return KErrNone;
- }
-
-TInt CSimLine::NotifyCallAddedCancel(const TTsyReqHandle /*aTsyReqHandle*/)
-/**
-* Cancel a client's interest in being notified when a new call is added.
-* Core ETel API Request.
-*
-* @param aTsyReqHandle Tsy Request handle for the client cancel request
-* @return KErrNone
-*/
- {
- LOGLINE1(">>CSimLine::NotifyCallAddedCancel");
- if(iNotifyCallAdded.iNotifyPending)
- {
- iNotifyCallAdded.iNotifyPending=EFalse;
- ReqCompleted(iNotifyCallAdded.iNotifyHandle,KErrCancel);
- }
- LOGLINE1("<<CSimLine::NotifyCallAddedCancel");
- return KErrNone;
- }
-
-
-void CSimLine::HandleNewCallAddedNotification(const TDesC& aNewName)
-/**
-* Process a potential "New Call Added Notification" completion.
-*/
- {
- LOGLINE1(">>CSimLine::HandleNewCallAddedNotification");
- iNameOfLastCallAdded.Copy(aNewName);
- if(iNotifyCallAdded.iNotifyPending)
- {
- iNotifyCallAdded.iNotifyPending=EFalse;
- ((TName*)iNotifyCallAdded.iNotifyData)->Copy(aNewName);
- ReqCompleted(iNotifyCallAdded.iNotifyHandle,KErrNone);
- }
- LOGLINE1("<<CSimLine::HandleNewCallAddedNotification");
- }
-
-TInt CSimLine::GetCaps(const TTsyReqHandle aTsyReqHandle, RLine::TCaps* aCaps)
-/**
- * Retrieve the current line capabilities.
- * Core ETel API Request.
- *
- * @param aTsyReqHandle TSY request handle associated with this request.
- * @param aCaps Point to capability structure that will be populated with the caps.
- * @return TInt Standard return value.
- */
- {
- aCaps->iFlags=iCaps;
- ReqCompleted(aTsyReqHandle,KErrNone);
- return KErrNone;
- }
-
-TInt CSimLine::NotifyCapsChange(const TTsyReqHandle aTsyReqHandle, RLine::TCaps* aCaps)
-/**
-* Register a client's interest in being notified when the line caps change.
-* Core ETel API Request.
-*
-* @param aTsyReqHandle The TSY handle associated with this request.
-* @param aCaps The capability structure that will be populated with the new capability
-* information.
-* @return TInt Standard error code.
-*/
- {
- __ASSERT_ALWAYS(!iNotifyCapsChange.iNotifyPending,SimPanic(ENotificationReqAlreadyOutstanding));
- iNotifyCapsChange.iNotifyPending=ETrue;
- iNotifyCapsChange.iNotifyHandle=aTsyReqHandle;
- iNotifyCapsChange.iNotifyData=aCaps;
- return KErrNone;
- }
-
-TInt CSimLine::NotifyCapsChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
-/**
-* Cancel a client's interest in being notified when the call capabilities change.
-* Core ETel API Request.
-*/
- {
- if(iNotifyCapsChange.iNotifyPending)
- {
- iNotifyCapsChange.iNotifyPending=EFalse;
- ReqCompleted(iNotifyCapsChange.iNotifyHandle,KErrCancel);
- }
- return KErrNone;
- }
-
-TInt CSimLine::GetInfo(const TTsyReqHandle aTsyReqHandle, RMobileLine::TLineInfo* aLineInfo)
-/**
-* Retrieve the Line Information
-* Core ETel API Request.
-*
-* @param aTsyReqHandle
-* @param aLineInfo pointer to the line information to be returned to client
-* @return KErrNone
-*/
- {
- LOGLINE1(">>CSimLine::GetInfo");
- aLineInfo->iHookStatus=iHookState;
- aLineInfo->iStatus=(RCall::TStatus)iState;
- aLineInfo->iNameOfLastCallAdded.Copy(iNameOfLastCallAdded);
- if(iAnswerNextIncomingCall)
- aLineInfo->iNameOfCallForAnswering.Copy(iAnswerNextIncomingCall->iName);
- else
- aLineInfo->iNameOfCallForAnswering.Zero();
-
- ReqCompleted(aTsyReqHandle,KErrNone);
- LOGLINE1("<<CSimLine::GetInfo");
- return KErrNone;
- }
-
-
-RCall::TStatus CSimLine::GetCoreLineStatus()
-/**
-* Converts Multimode call status (RMobileCall::TMobileCallStatus) to
-* Core call Status (RCall::TStatus)
-*
-* @return RCall::TStatus The core call status
-*/
- {
-// All status enums with values of Disconnecting and below are identical in
-// ETelMM and Core, so the mapping function is simple.
- RCall::TStatus coreStatus;
- if (iState <= RMobileCall::EStatusDisconnecting)
- coreStatus = (RCall::TStatus)iState;
- else
- switch (iState)
- {
- case RMobileCall::EStatusReconnectPending:
- case RMobileCall::EStatusHold:
- coreStatus = RCall::EStatusConnected;
- break;
- case RMobileCall::EStatusWaitingAlternatingCallSwitch:
- coreStatus = RCall::EStatusIdle;
- break;
- default:
- coreStatus = RCall::EStatusUnknown;
- break;
- }
- return coreStatus;
- }
-
-TInt CSimLine::GetStatus(const TTsyReqHandle aTsyReqHandle,RCall::TStatus* aLineStatus)
-/**
-* Return the current line state. (Core API request)
-* Core ETel API Request.
-*
-* @param aTsyReqHandle
-* @param aLineStatus pointer to the line status
-* @return KErrNone
-*/
- {
- LOGLINE1(">>CSimLine::GetStatus");
- *aLineStatus=GetCoreLineStatus();
- ReqCompleted(aTsyReqHandle,KErrNone);
- LOGLINE1("<<CSimLine::GetStatus");
- return KErrNone;
- }
-
-TInt CSimLine::GetMobileLineStatus(const TTsyReqHandle aTsyReqHandle,RMobileCall::TMobileCallStatus* aLineStatus)
-/**
-* Return the current line state. (MultiMode API request)
-* MM ETel API Request.
-*
-* @param aTsyReqHandle
-* @param aLineStatus pointer to the line status
-* @return KErrNone
-*/
- {
- LOGLINE1(">>CSimLine::GetMobileLineStatus");
- *aLineStatus=iState;
- ReqCompleted(aTsyReqHandle,KErrNone);
- LOGLINE1("<<CSimLine::GetMobileLineStatus");
- return KErrNone;
- }
-
-TInt CSimLine::GetHookStatus(const TTsyReqHandle aTsyReqHandle,RCall::THookStatus* aHookStatus)
-/**
-* Return the current Hook state.
-* Core ETel API Request.
-*
-* @param aTsyReqHandle
-* @param aHookStatus pointer to the hook status
-* @return KErrNone
-*/
- {
- LOGLINE1(">>CSimLine::GetHookStatus");
- *aHookStatus=iHookState;
- ReqCompleted(aTsyReqHandle,KErrNone);
- LOGLINE1("<<CSimLine::GetHookStatus");
- return KErrNone;
- }
-
-const CTestConfigSection* CSimLine::CfgFile()
-/**
-* Returns a pointer to the config file section
-*
-* @return CTestConfig a pointer to the configuration file data section
-*/
- {
- LOGLINE1(">>CSimLine::CfgFile");
- return iPhone->CfgFile();
- }
-
-TInt CSimLine::ChangeStateL(RMobileCall::TMobileCallStatus aNewState,TBool aSwap,CSimCall* aOriginatingCall)
-/**
-* Validate and change the Line State
-*
-* @param aNewState the new state to change to
-* @param aSwap indicates whether change comes from swap operation on the call
-* @param aOriginatingCall original call that change comes from
-* @return Error indication if change of state is successful or not
-*/
- {
- __ASSERT_ALWAYS(aNewState!=RMobileCall::EStatusUnknown,SimPanic(ECallStatusUnknownIllegal));
- __ASSERT_ALWAYS(iState!=RMobileCall::EStatusUnknown,SimPanic(ECallStatusUnknownIllegal));
- CSimCall* swappedCall=NULL;
- TInt i=0;
- TInt count=iCalls->Count();
- for(i=0;i<count;i++)
- {
- LOGLINE3(">>CSimLine::ChangeState0 0x%08x %d",iCalls->At(i),iCalls->At(i)->iState);
- }
-
- TInt ret=KErrGeneral;
- const TStateChangeValidity* stateChangePnt=KLineStateChangeValidity;
- while(stateChangePnt->iOldState!=KStateTableTerminator)
- {
- if((stateChangePnt->iOldState==iState) &&
- ((stateChangePnt->iNewState==aNewState) || aNewState==RMobileCall::EStatusIdle))
- {
- ret=stateChangePnt->iError;
- break;
- }
- stateChangePnt++;
- }
-
- //coverity[cannot_single]
- if(ret!=KErrNone && !(aSwap && iState==RMobileCall::EStatusConnected && aNewState==RMobileCall::EStatusConnected))
- return ret;
-
- LOGLINE2(">>CSimLine::ChangeState 0x%08x",aOriginatingCall);
- if(aNewState==RMobileCall::EStatusIdle)
- {
- if(iState==RMobileCall::EStatusIdle)
- return KErrAlreadyExists;
- else if(iState==RMobileCall::EStatusDisconnecting || iState==RMobileCall::EStatusDialling)
- {
- TInt i=0;
- TInt count=iCalls->Count();
- for(i=0;i<count;i++)
- {
- LOGLINE3(">>CSimLine::ChangeState1 0x%08x %d",iCalls->At(i),iCalls->At(i)->iState);
-
- if(aOriginatingCall!=iCalls->At(i) && iCalls->At(i)->iState != RMobileCall::EStatusIdle)
- {
- aNewState=iCalls->At(i)->iState;
- break;
- }
- }
- }
- }
- else if(aNewState==RMobileCall::EStatusHold)
- {
- if((iState == RMobileCall::EStatusRinging) &&
- (aNewState == RMobileCall::EStatusHold))
- {
- if(aOriginatingCall->iState != RMobileCall::EStatusConnected)
- return KErrGeneral;
- aNewState=RMobileCall::EStatusRinging;
- }
- TInt i=0;
- TInt count=iCalls->Count();
- for(i=0;i<count;i++)
- {
- LOGLINE3(">>CSimLine::ChangeState1 0x%08x %d",iCalls->At(i),iCalls->At(i)->iState);
- if(iCalls->At(i) != aOriginatingCall && iCalls->At(i)->iState == RMobileCall::EStatusHold)
- {
- if(aSwap)
- {
- swappedCall=iCalls->At(i);
- swappedCall->iState=RMobileCall::EStatusConnected;
- aNewState=RMobileCall::EStatusConnected;
- }
- else
- return KErrAlreadyExists;
- }
- }
- }
- else if(aNewState==RMobileCall::EStatusConnected)
- {
- TInt i=0;
- TInt count=iCalls->Count();
- for(i=0;i<count;i++)
- {
- LOGLINE3(">>CSimLine::ChangeState1 0x%08x %d",iCalls->At(i),iCalls->At(i)->iState);
- if(iCalls->At(i) != aOriginatingCall)
- {
- if(iCalls->At(i)->iState == RMobileCall::EStatusConnected)
- {
- //coverity[dead_error_condition]
- if(aSwap)
- {
- swappedCall=iCalls->At(i);
- swappedCall->iState=RMobileCall::EStatusHold;
- aNewState=RMobileCall::EStatusConnected;
- break;
- }
- else
- //coverity[dead_error_line]
- return KErrAlreadyExists;
- }
- }
- }
- }
-
- // Actually change the state.
- LOGLINE3(">>CSimLine::ChangeState [oldState=%d] [newState=%d]", iState, aNewState);
-
- if(iState != aNewState)
- {
- iState=aNewState;
-
- // Check for a pending line state notification (core)
- if(iNotifyStatusChange.iNotifyPending)
- {
- iNotifyStatusChange.iNotifyPending=EFalse;
- *(RCall::TStatus*)iNotifyStatusChange.iNotifyData=GetCoreLineStatus();
- ReqCompleted(iNotifyStatusChange.iNotifyHandle,KErrNone);
- }
-
- // Check for a pending line state notification (multimode)
- if(iNotifyMobileStatusChange.iNotifyPending)
- {
- iNotifyMobileStatusChange.iNotifyPending=EFalse;
- *(RMobileCall::TMobileCallStatus*)iNotifyMobileStatusChange.iNotifyData=iState;
- ReqCompleted(iNotifyMobileStatusChange.iNotifyHandle,KErrNone);
- }
-
- // Check for a pending hook state notification.
- if(iHookState!=ConvertStateToHook(iState))
- {
- iHookState=ConvertStateToHook(iState);
- if(iNotifyHookChange.iNotifyPending)
- {
- iNotifyHookChange.iNotifyPending=EFalse;
- *(RCall::THookStatus*)iNotifyHookChange.iNotifyData=iHookState;
- ReqCompleted(iNotifyHookChange.iNotifyHandle,KErrNone);
- }
- }
- }
- // Check for a possible change in capabilities.
- TUint caps=Caps();
- if(iCaps!=caps)
- {
- iCaps=caps;
- if(iNotifyCapsChange.iNotifyPending)
- {
- iNotifyCapsChange.iNotifyPending=EFalse;
- ((RLine::TCaps*)iNotifyCapsChange.iNotifyData)->iFlags=iCaps;
- ReqCompleted(iNotifyCapsChange.iNotifyHandle,KErrNone);
- }
- }
-
- if(aSwap && swappedCall)
- swappedCall->UpdateNotifiers();
- // Request that the phone change its state, to ensure its in step.
- if((ret = iPhone->ValidateChangeState(this,aNewState)) != KErrNone)
- return ret;
-
- for(i=0;i<iCalls->Count();i++)
- {
- LOGLINE3(">>CSimLine::ChangeState5 0x%08x %d",iCalls->At(i),iCalls->At(i)->iState);
- }
-
- LOGLINE1("<<CSimLine::ChangeState");
- return KErrNone;
- }
-
-void CSimLine::SimPSEvent(const CSimPubSub::TPubSubProperty aProperty, TInt /*aStatus*/)
-/**
-Handles the P&S notifications for the Line class
-
-@param aProperty The property key representing the notification.
-*/
- {
- LOGLINE1(">>CSimLine::SimPSEvent");
- if(aProperty==iICProperty) // check for this here still, start the timer for amount specified in config file.
- ProcessIncomingCallEvent();
- if(aProperty==iRHProperty)
- ProcessRemoteHangupEvent();
- LOGLINE1("<<CSimLine::SimPSEvent");
- }
-
-TInt CSimLine::SetAutoAnswerCallObject(CSimCall* aCallObject)
-/**
-* Attempt to set the call object that will be used to answer the next incoming
-* call. If there is already an AnswerIncomingCall registered, then
-* return with the relevant error.
-*
-* @param aCallObject pointer to the call object
-* @return KErrNone if successful
-*/
- {
- LOGLINE1(">>CSimLine::SetAnswerCallObject");
- if(iAnswerIncomingCallReqPending) // Is there a request already outstanding?
- return KErrEtelAnswerAlreadyOutstanding;
-
- iAnswerIncomingCallReqPending=ETrue;
- if (iAnswerNextIncomingCall!=aCallObject)
- {
- if (iSpareCall != iAnswerNextIncomingCall)
- {
- iAnswerNextIncomingCall->Close();
- }
- iAnswerNextIncomingCall=aCallObject; // Set the "answer next call" object
- iAnswerNextIncomingCall->Open();
- }
- LOGLINE1("<<CSimLine::SetAnswerCallObject");
- return KErrNone;
- }
-
-void CSimLine::ResetAutoAnswerCallObject(CSimCall* aCallObject)
-/**
-* This function is used to reset, or effectively cancel, the call object that
-* was to be used to automatically answer the next incoming call.
-*
-* @param aCallObject pointer to the call object
-*/
- {
- LOGLINE1(">>CSimLine::ResetAnswerCallObject");
- __ASSERT_ALWAYS(iAnswerNextIncomingCall==aCallObject,SimPanic(EIllegalAnswerNextIncomingCallInconsistancy));
- iAnswerNextIncomingCall->Close();
- iAnswerNextIncomingCall=iSpareCall;
- iAnswerIncomingCallReqPending=EFalse;
- }
-
-void CSimLine::ProcessIncomingCallEvent()
-/**
-* Process an incoming call event.
-*/
- {
- LOGLINE1(">>CSimLine::ProcessIncomingCallEvent ");
-
- if (iSpareCall == iAnswerNextIncomingCall)
- {
- TName callName;
- TRAPD(err,iAnswerNextIncomingCall=CreateNewCallL(callName,ECallTypeNormalCall));
- if (err!=KErrNone)
- {
- SimPanic(EOjectNotConstructed);
- }
- }
-
- // Delay sending the notification of an incoming call if
- // one has been set.
- iTimer->Start(iNotifyIncomingCallPause, this);
-
- __ASSERT_ALWAYS(iAnswerNextIncomingCall->ActionEvent(CSimCall::ECallEventIncomingCall,KErrNone) == KErrNone, SimPanic(EGeneral));
- LOGLINE1("<<CSimLine::ProcessIncomingCallEvent");
- }
-
-TInt CSimLine::SetRemoteHangupCallObject(CSimCall* aCallObject)
-/**
-* Attempt to set the call object that will be hung up remotely
-* If there is already a RemoteHangup registered, then
-* return with the relevant error.
-*
-* @param aCallObject pointer to the call object
-* @return KErrNone if successful
-*/
- {
- LOGLINE1(">>CSimLine::SetRemoteHangupCallObject");
- if(iRemoteHangupCallReqPending) // Is there a request already outstanding?
- return KErrEtelInitialisationFailure;
-
- iRemoteHangupCallReqPending=ETrue;
- if (iRemoteHangupCall!=aCallObject)
- {
- iRemoteHangupCall=aCallObject; // Set the "remote hang up" object
- }
- LOGLINE1("<<CSimLine::SetRemoteHangupCallObject");
- return KErrNone;
- }
-
-void CSimLine::ResetRemoteHangupCallObject(CSimCall* aCallObject)
-/**
-* This function is used to reset, or effectively cancel, the call object that
-* was to be remotely hung up.
-*
-* @param aCallObject pointer to the call object
-*/
- {
- LOGLINE1(">>CSimLine::ResetRemoteHangupCallObject");
- __ASSERT_ALWAYS(iRemoteHangupCall==aCallObject,SimPanic(EIllegalAnswerRemoteHangupCallInconsistency));
- iRemoteHangupCallReqPending=EFalse;
- }
-
-void CSimLine::ProcessRemoteHangupEvent()
-/**
-* Process a remote hangup event.
-*/
- {
- LOGLINE1(">>CSimLine::ProcessRemoteHangupEvent");
-
- if (iRemoteHangupCall == NULL)
- {
- TInt err = FindActiveCall(iRemoteHangupCall);
- if(err == KErrNone)
- {
- err = iRemoteHangupCall->ActionEvent(CSimCall::ECallEventRemoteHangup,KErrNone);
- if(err != KErrNone)
- {
- LOGLINE2("ERROR: CSimLine::ProcessRemoteHangupEvent returned: %d", err);
- }
- }
- else
- {
- LOGLINE1("No outstanding call to hang up remotely");
- }
- }
- LOGLINE1("<<CSimLine::ProcessRemoteHangupEvent");
- }
-
-void CSimLine::CallDestructor(CSimCall* aCall)
-/**
- * This function is called from a call's destructor.
- * It must delete the call from its list. If the call cannot be found, an unacceptable
- * inconsistancy must have developed, and the TSY will panic.
- */
- {
- for(TInt i=0;i<iCalls->Count();i++)
- {
- if(iCalls->At(i)==aCall)
- {
- iCalls->Delete(i);
- return;
- }
- }
- SimPanic(EIllegalCallNotRegisteredWithLine);
- }
-
-TBool CSimLine::IsAnswerCallObjectSpare()
-/**
- * Is the "answer" call object actually the spare object.
- */
- {
- return (iSpareCall==iAnswerNextIncomingCall);
- }
-
-/**
-Called when iTimer has delayed the sending of the notification of the incoming call.
-*/
-void CSimLine::TimerCallBack(TInt /*aId*/)
- {
- ProcessNotifyIncomingCallEvent();
- }
-
-/**
-Send notification of an incoming call.
-*/
-void CSimLine::ProcessNotifyIncomingCallEvent()
- {
- LOGLINE1(">>CSimLine::ProcessNotifyIncomingCallEvent");
- if(iNotifyIncomingCall.iNotifyPending)
- {
- iNotifyIncomingCall.iNotifyPending=EFalse;
- ((TName*)iNotifyIncomingCall.iNotifyData)->Copy(iAnswerNextIncomingCall->iName);
- ReqCompleted(iNotifyIncomingCall.iNotifyHandle,KErrNone);
- }
- LOGLINE1("<<CSimLine::ProcessNotifyIncomingCallEvent");
- }
-
+
+// Copyright (c) 2001-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:
+// This file contains the implementation for the functionality common to all
+// the specific line classes, such as CSimVoiceLine and CSimDataline.
+//
+//
+
+/**
+ @file
+*/
+
+#include <testconfigfileparser.h>
+#include "CSimLine.h"
+#include "CSimPhone.h"
+#include "CSimCall.h"
+#include "Simlog.h"
+#include "CSimPubSub.h"
+
+void CSimLine::CloseLine(TAny* aObj)
+/**
+* Utility func for cleanup stack
+*
+* @param aObj a pointer to the CObject to close
+*/
+ {
+ ((CObject*)aObj)->Close();
+ }
+
+CSimLine::CSimLine(CSimPhone* aPhone)
+ :iPhone(aPhone), iState(RMobileCall::EStatusIdle),
+ iHookState(ConvertStateToHook(iState))
+ {
+ iNameOfLastCallAdded.Zero();
+ iNotifyStatusChange.iNotifyPending = EFalse;
+ iNotifyMobileStatusChange.iNotifyPending = EFalse;
+ }
+
+void CSimLine::ConstructL(const TName& aName)
+/**
+* Second phase of two phase constructor.
+* Creates the System Agent object for incoming call notification and other notifications.
+*
+* @param aName name of the Line to be created.
+*/
+ {
+ LOGLINE2(">>CSimLine::ConstructL [aLineName=%S]", &aName);
+ iLineName = aName;
+ iSimPubSubIC = CSimPubSub::NewL(this,iICProperty);
+ iSimPubSubIC->Start();
+
+ iSimPubSubRH = CSimPubSub::NewL(this,iRHProperty);
+ iSimPubSubRH->Start();
+
+ iNotifyIncomingCallPause=this->CfgFile()->ItemValue(KNotifyIncomingCallPauseDuration,KDefaultNotifyIncomingCallPauseDuration);
+
+ iTimer = CSimTimer::NewL(iPhone);
+ LOGLINE1("<<CSimLine::ConstructL");
+}
+
+CSimLine::~CSimLine()
+/**
+* Standard destructor.
+*/
+ {
+ delete iSimPubSubIC;
+ delete iSimPubSubRH;
+ iTimer->Cancel();
+ delete iTimer;
+ }
+
+
+void CSimLine::UpdatePhoneNotifiers(CSimCall* aCall,TUint /*aStatus*/)
+ {
+ TInt count= iCalls->Count();
+ TInt i=0;
+ while(i<count)
+ {
+ if(iCalls->At(i) != aCall && (iCalls->At(i)->iState == RMobileCall::EStatusHold || iCalls->At(i)->iState == RMobileCall::EStatusConnected))
+ iCalls->At(i)->UpdateNotifiers();
+ i++;
+ }
+ }
+
+CTelObject::TReqMode CSimLine::ReqModeL(const TInt aIpc)
+/**
+* This function returns the Request Mode for the request with the passed IPC value.
+* The ETel Server provides a function for returning the standard request modes for
+* the Core API requests.
+* Multimode API requests mode are handled here.
+*
+* @param aIpc the IPc number representing the client request
+* @return CTelObject::TReqMode the request mode to be used for this IPc number
+* @leave Leaves if the IPc number is not found
+*/
+ {
+ // ReqModeL is called from the server's CTelObject::ReqAnalyserL
+ // in order to check the type of request it has
+
+ CTelObject::TReqMode reqMode=0;
+ switch (aIpc)
+ {
+//
+// No Flow Control NOR Multiple Completion
+//
+ case EMobileLineGetMobileLineStatus:
+ break;
+
+//
+// Multiple Completion Services with Immediate Server Repost
+// (Usually Notifications)
+//
+ case EMobileLineNotifyMobileLineStatusChange:
+ reqMode=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately;
+ break;
+//
+// Must be a core API request so get request mode from Etel
+//
+ default:
+ reqMode=CLineBase::ReqModeL(aIpc);
+ break;
+ }
+
+ return reqMode;
+ }
+
+
+TInt CSimLine::NumberOfSlotsL(const TInt aIpc)
+/**
+* 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
+*
+* @param aIpc the IPc number representing the client request
+* @return TInt the number of slots required
+* @leave Leaves if the IPc number is not found
+*/
+ {
+ switch (aIpc)
+ {
+ case EMobileLineNotifyMobileLineStatusChange:
+ LOGLINE1("CLineMobile: Registered with the default number of slots");
+ return KDefaultNumberOfSlots;
+
+ default:
+ LOGLINE1("CSimLine::NumberOfSlotsL: No match for IPC, defering to base function");
+ break;
+ }
+ return CLineBase::NumberOfSlotsL(aIpc);
+ }
+
+
+TInt CSimLine::RegisterNotification(const TInt /*aIpc*/)
+/**
+* The ETel Server calls this function when the first client makes a notification request.
+* If supported by the underlying protocol controlling the signalling stack,
+* this can be used to start requesting updates for the relevant service.
+*/
+ {
+ return KErrNone;
+ }
+
+TInt CSimLine::DeregisterNotification(const TInt /*aIpc*/)
+/**
+* The ETel Server calls this function when the last client that had previously
+* made a notification request closes its ETel Server handle. If supported by
+* the underlying protocol controlling the signalling stack, this can be used
+* to stop requesting updates for the relevant service.
+*/
+ {
+ return KErrNone;
+ }
+
+void CSimLine::Init()
+/**
+* This function can be used to perform any necessary synchronous initialisation.
+*/
+ {}
+
+TInt CSimLine::NotifyIncomingCall(const TTsyReqHandle aTsyReqHandle, TName* aName)
+/**
+* Register a client's interest in an incoming call notification.
+* Core ETel API Request.
+*
+* @param aTsyReqHandle Tsy Request handle for the client request
+* @param aName pointer to the name of the call
+* @return KErrNone
+*/
+ {
+ LOGLINE1(">>CSimLine::NotifyIncomingCall");
+ iNotifyIncomingCall.iNotifyPending=ETrue;
+ iNotifyIncomingCall.iNotifyHandle=aTsyReqHandle;
+ iNotifyIncomingCall.iNotifyData=(TAny*)aName;
+ LOGLINE1("<<CSimLine::NotifyIncomingCall");
+ return KErrNone;
+ }
+
+TInt CSimLine::NotifyIncomingCallCancel(const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+* Cancels a client's interest in an incoming call.
+* Core ETel API Request.
+*
+* @param aTsyReqHandle Tsy Request handle for the client cancel request
+* @return KErrNone
+*/
+ {
+ LOGLINE1(">>CSimLine::NotifyIncomingCallCancel");
+ if(iNotifyIncomingCall.iNotifyPending)
+ {
+ iTimer->Cancel();
+ iNotifyIncomingCall.iNotifyPending=EFalse;
+ ReqCompleted(iNotifyIncomingCall.iNotifyHandle, KErrCancel);
+ }
+ LOGLINE1("<<CSimLine::NotifyIncomingCallCancel");
+ return KErrNone;
+ }
+
+TInt CSimLine::NotifyHookChange(const TTsyReqHandle aTsyReqHandle, RCall::THookStatus* aHookStatus)
+/**
+* Record a client's interst in being notified when the line hook changes state.
+* Core ETel API Request.
+*
+* @param aTsyReqHandle Tsy Request handle for the client request
+* @param aHookStatus pointer to the line hook
+* @return KErrNone
+*/
+ {
+ LOGLINE1(">>CSimLine::NotifyHookChange");
+ iNotifyHookChange.iNotifyPending=ETrue;
+ iNotifyHookChange.iNotifyHandle=aTsyReqHandle;
+ iNotifyHookChange.iNotifyData=(TAny*)aHookStatus;
+ LOGLINE1("<<CSimLine::NotifyHookChange");
+ return KErrNone;
+ }
+
+TInt CSimLine::NotifyHookChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+* Cancel a client's interest in being notified when the line hook changes state.
+* Core ETel API Request.
+*
+* @param aTsyReqHandle Tsy Request handle for the client cancel request
+* @return KErrNone
+*/
+ {
+ LOGLINE1(">>CSimLine::NotifyHookChangeCancel");
+ if(iNotifyHookChange.iNotifyPending)
+ {
+ iNotifyHookChange.iNotifyPending=EFalse;
+ ReqCompleted(iNotifyHookChange.iNotifyHandle,KErrCancel);
+ }
+ LOGLINE1("<<CSimLine::NotifyHookChangeCancel");
+ return KErrNone;
+ }
+
+
+TInt CSimLine::NotifyMobileLineStatusChange(const TTsyReqHandle aTsyReqHandle, RMobileCall::TMobileCallStatus* aStatus)
+/**
+* Record a client's interst in being notified when the line changes state. (Multimode)
+* MM ETel API Request.
+*
+* @param aTsyReqHandle Tsy Request handle for the client request
+* @param aStatus pointer to the line status
+* @return KErrNone
+*/
+ {
+ LOGLINE1(">>CSimLine::NotifyMobileLineStatusChange");
+ iNotifyMobileStatusChange.iNotifyPending=ETrue;
+ iNotifyMobileStatusChange.iNotifyHandle=aTsyReqHandle;
+ iNotifyMobileStatusChange.iNotifyData=aStatus;
+ LOGLINE1("<<CSimLine::NotifyMobileLineStatusChange");
+ return KErrNone;
+ }
+
+TInt CSimLine::NotifyMobileLineStatusChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+* Cancel a client's interest in being notified when the line changes state.(Multimode Request)
+* MM ETel API Request.
+*
+* @param aTsyReqHandle Tsy Request handle for the client cancel request
+* @return KErrNone
+*/
+ {
+ LOGLINE1(">>CSimLine::NotifyMobileLineStatusChangeCancel");
+ if(iNotifyMobileStatusChange.iNotifyPending)
+ {
+ iNotifyMobileStatusChange.iNotifyPending=EFalse;
+ ReqCompleted(iNotifyMobileStatusChange.iNotifyHandle,KErrCancel);
+ }
+ LOGLINE1("<<CSimLine::NotifyMobileLineStatusChangeCancel");
+ return KErrNone;
+ }
+
+TInt CSimLine::NotifyStatusChange(const TTsyReqHandle aTsyReqHandle, RCall::TStatus* aStatus)
+/**
+* Record a client's interst in being notified when the line changes state. (Core)
+* Core ETel API Request.
+*
+* @param aTsyReqHandle Tsy Request handle for the client request
+* @param aStatus pointer to the line status
+* @return KErrNone
+*/
+ {
+ LOGLINE1(">>CSimLine::NotifyStatusChange");
+ iNotifyStatusChange.iNotifyPending=ETrue;
+ iNotifyStatusChange.iNotifyHandle=aTsyReqHandle;
+ iNotifyStatusChange.iNotifyData=aStatus;
+ LOGLINE1("<<CSimLine::NotifyStatusChange");
+ return KErrNone;
+ }
+
+TInt CSimLine::NotifyStatusChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+* Cancel a client's interest in being notified when the line changes state.(Multimode Request)
+* Core ETel API Request.
+*
+* @param aTsyReqHandle Tsy Request handle for the client cancel request
+* @return KErrNone
+*/
+ {
+ LOGLINE1(">>CSimLine::NotifyStatusChangeCancel");
+ if(iNotifyStatusChange.iNotifyPending)
+ {
+ iNotifyStatusChange.iNotifyPending=EFalse;
+ ReqCompleted(iNotifyStatusChange.iNotifyHandle,KErrCancel);
+ }
+ LOGLINE1("<<CSimLine::NotifyStatusChangeCancel");
+ return KErrNone;
+ }
+
+TInt CSimLine::NotifyCallAdded(const TTsyReqHandle aTsyReqHandle,TName* aName)
+/**
+* Record a client's interest in being notified when a new call is added.
+* Core ETel API Request.
+*
+* @param aTsyReqHandle Tsy Request handle for the client request
+* @param aName pointer to the name of the call
+* @return KErrNone
+*/
+ {
+ LOGLINE1(">>CSimLine::NotifyCallAdded");
+ iNotifyCallAdded.iNotifyPending=ETrue;
+ iNotifyCallAdded.iNotifyHandle=aTsyReqHandle;
+ iNotifyCallAdded.iNotifyData=(TAny*)aName;
+ LOGLINE1("<<CSimLine::NotifyCallAdded");
+ return KErrNone;
+ }
+
+TInt CSimLine::NotifyCallAddedCancel(const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+* Cancel a client's interest in being notified when a new call is added.
+* Core ETel API Request.
+*
+* @param aTsyReqHandle Tsy Request handle for the client cancel request
+* @return KErrNone
+*/
+ {
+ LOGLINE1(">>CSimLine::NotifyCallAddedCancel");
+ if(iNotifyCallAdded.iNotifyPending)
+ {
+ iNotifyCallAdded.iNotifyPending=EFalse;
+ ReqCompleted(iNotifyCallAdded.iNotifyHandle,KErrCancel);
+ }
+ LOGLINE1("<<CSimLine::NotifyCallAddedCancel");
+ return KErrNone;
+ }
+
+
+void CSimLine::HandleNewCallAddedNotification(const TDesC& aNewName)
+/**
+* Process a potential "New Call Added Notification" completion.
+*/
+ {
+ LOGLINE1(">>CSimLine::HandleNewCallAddedNotification");
+ iNameOfLastCallAdded.Copy(aNewName);
+ if(iNotifyCallAdded.iNotifyPending)
+ {
+ iNotifyCallAdded.iNotifyPending=EFalse;
+ ((TName*)iNotifyCallAdded.iNotifyData)->Copy(aNewName);
+ ReqCompleted(iNotifyCallAdded.iNotifyHandle,KErrNone);
+ }
+ LOGLINE1("<<CSimLine::HandleNewCallAddedNotification");
+ }
+
+TInt CSimLine::GetCaps(const TTsyReqHandle aTsyReqHandle, RLine::TCaps* aCaps)
+/**
+ * Retrieve the current line capabilities.
+ * Core ETel API Request.
+ *
+ * @param aTsyReqHandle TSY request handle associated with this request.
+ * @param aCaps Point to capability structure that will be populated with the caps.
+ * @return TInt Standard return value.
+ */
+ {
+ aCaps->iFlags=iCaps;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+TInt CSimLine::NotifyCapsChange(const TTsyReqHandle aTsyReqHandle, RLine::TCaps* aCaps)
+/**
+* Register a client's interest in being notified when the line caps change.
+* Core ETel API Request.
+*
+* @param aTsyReqHandle The TSY handle associated with this request.
+* @param aCaps The capability structure that will be populated with the new capability
+* information.
+* @return TInt Standard error code.
+*/
+ {
+ __ASSERT_ALWAYS(!iNotifyCapsChange.iNotifyPending,SimPanic(ENotificationReqAlreadyOutstanding));
+ iNotifyCapsChange.iNotifyPending=ETrue;
+ iNotifyCapsChange.iNotifyHandle=aTsyReqHandle;
+ iNotifyCapsChange.iNotifyData=aCaps;
+ return KErrNone;
+ }
+
+TInt CSimLine::NotifyCapsChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+* Cancel a client's interest in being notified when the call capabilities change.
+* Core ETel API Request.
+*/
+ {
+ if(iNotifyCapsChange.iNotifyPending)
+ {
+ iNotifyCapsChange.iNotifyPending=EFalse;
+ ReqCompleted(iNotifyCapsChange.iNotifyHandle,KErrCancel);
+ }
+ return KErrNone;
+ }
+
+TInt CSimLine::GetInfo(const TTsyReqHandle aTsyReqHandle, RMobileLine::TLineInfo* aLineInfo)
+/**
+* Retrieve the Line Information
+* Core ETel API Request.
+*
+* @param aTsyReqHandle
+* @param aLineInfo pointer to the line information to be returned to client
+* @return KErrNone
+*/
+ {
+ LOGLINE1(">>CSimLine::GetInfo");
+ aLineInfo->iHookStatus=iHookState;
+ aLineInfo->iStatus=(RCall::TStatus)iState;
+ aLineInfo->iNameOfLastCallAdded.Copy(iNameOfLastCallAdded);
+ if(iAnswerNextIncomingCall)
+ aLineInfo->iNameOfCallForAnswering.Copy(iAnswerNextIncomingCall->iName);
+ else
+ aLineInfo->iNameOfCallForAnswering.Zero();
+
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ LOGLINE1("<<CSimLine::GetInfo");
+ return KErrNone;
+ }
+
+
+RCall::TStatus CSimLine::GetCoreLineStatus()
+/**
+* Converts Multimode call status (RMobileCall::TMobileCallStatus) to
+* Core call Status (RCall::TStatus)
+*
+* @return RCall::TStatus The core call status
+*/
+ {
+// All status enums with values of Disconnecting and below are identical in
+// ETelMM and Core, so the mapping function is simple.
+ RCall::TStatus coreStatus;
+ if (iState <= RMobileCall::EStatusDisconnecting)
+ coreStatus = (RCall::TStatus)iState;
+ else
+ switch (iState)
+ {
+ case RMobileCall::EStatusReconnectPending:
+ case RMobileCall::EStatusHold:
+ coreStatus = RCall::EStatusConnected;
+ break;
+ case RMobileCall::EStatusWaitingAlternatingCallSwitch:
+ coreStatus = RCall::EStatusIdle;
+ break;
+ default:
+ coreStatus = RCall::EStatusUnknown;
+ break;
+ }
+ return coreStatus;
+ }
+
+TInt CSimLine::GetStatus(const TTsyReqHandle aTsyReqHandle,RCall::TStatus* aLineStatus)
+/**
+* Return the current line state. (Core API request)
+* Core ETel API Request.
+*
+* @param aTsyReqHandle
+* @param aLineStatus pointer to the line status
+* @return KErrNone
+*/
+ {
+ LOGLINE1(">>CSimLine::GetStatus");
+ *aLineStatus=GetCoreLineStatus();
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ LOGLINE1("<<CSimLine::GetStatus");
+ return KErrNone;
+ }
+
+TInt CSimLine::GetMobileLineStatus(const TTsyReqHandle aTsyReqHandle,RMobileCall::TMobileCallStatus* aLineStatus)
+/**
+* Return the current line state. (MultiMode API request)
+* MM ETel API Request.
+*
+* @param aTsyReqHandle
+* @param aLineStatus pointer to the line status
+* @return KErrNone
+*/
+ {
+ LOGLINE1(">>CSimLine::GetMobileLineStatus");
+ *aLineStatus=iState;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ LOGLINE1("<<CSimLine::GetMobileLineStatus");
+ return KErrNone;
+ }
+
+TInt CSimLine::GetHookStatus(const TTsyReqHandle aTsyReqHandle,RCall::THookStatus* aHookStatus)
+/**
+* Return the current Hook state.
+* Core ETel API Request.
+*
+* @param aTsyReqHandle
+* @param aHookStatus pointer to the hook status
+* @return KErrNone
+*/
+ {
+ LOGLINE1(">>CSimLine::GetHookStatus");
+ *aHookStatus=iHookState;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ LOGLINE1("<<CSimLine::GetHookStatus");
+ return KErrNone;
+ }
+
+const CTestConfigSection* CSimLine::CfgFile()
+/**
+* Returns a pointer to the config file section
+*
+* @return CTestConfig a pointer to the configuration file data section
+*/
+ {
+ LOGLINE1(">>CSimLine::CfgFile");
+ return iPhone->CfgFile();
+ }
+
+TInt CSimLine::ChangeStateL(RMobileCall::TMobileCallStatus aNewState,TBool aSwap,CSimCall* aOriginatingCall)
+/**
+* Validate and change the Line State
+*
+* @param aNewState the new state to change to
+* @param aSwap indicates whether change comes from swap operation on the call
+* @param aOriginatingCall original call that change comes from
+* @return Error indication if change of state is successful or not
+*/
+ {
+ __ASSERT_ALWAYS(aNewState!=RMobileCall::EStatusUnknown,SimPanic(ECallStatusUnknownIllegal));
+ __ASSERT_ALWAYS(iState!=RMobileCall::EStatusUnknown,SimPanic(ECallStatusUnknownIllegal));
+ CSimCall* swappedCall=NULL;
+ TInt i=0;
+ TInt count=iCalls->Count();
+ for(i=0;i<count;i++)
+ {
+ LOGLINE3(">>CSimLine::ChangeState0 0x%08x %d",iCalls->At(i),iCalls->At(i)->iState);
+ }
+
+ TInt ret=KErrGeneral;
+ const TStateChangeValidity* stateChangePnt=KLineStateChangeValidity;
+ while(stateChangePnt->iOldState!=KStateTableTerminator)
+ {
+ if((stateChangePnt->iOldState==iState) &&
+ ((stateChangePnt->iNewState==aNewState) || aNewState==RMobileCall::EStatusIdle))
+ {
+ ret=stateChangePnt->iError;
+ break;
+ }
+ stateChangePnt++;
+ }
+
+ //coverity[cannot_single]
+ if(ret!=KErrNone && !(aSwap && iState==RMobileCall::EStatusConnected && aNewState==RMobileCall::EStatusConnected))
+ return ret;
+
+ LOGLINE2(">>CSimLine::ChangeState 0x%08x",aOriginatingCall);
+ if(aNewState==RMobileCall::EStatusIdle)
+ {
+ if(iState==RMobileCall::EStatusIdle)
+ return KErrAlreadyExists;
+ else if(iState==RMobileCall::EStatusDisconnecting || iState==RMobileCall::EStatusDialling)
+ {
+ TInt i=0;
+ TInt count=iCalls->Count();
+ for(i=0;i<count;i++)
+ {
+ LOGLINE3(">>CSimLine::ChangeState1 0x%08x %d",iCalls->At(i),iCalls->At(i)->iState);
+
+ if(aOriginatingCall!=iCalls->At(i) && iCalls->At(i)->iState != RMobileCall::EStatusIdle)
+ {
+ aNewState=iCalls->At(i)->iState;
+ break;
+ }
+ }
+ }
+ }
+ else if(aNewState==RMobileCall::EStatusHold)
+ {
+ if((iState == RMobileCall::EStatusRinging) &&
+ (aNewState == RMobileCall::EStatusHold))
+ {
+ if(aOriginatingCall->iState != RMobileCall::EStatusConnected)
+ return KErrGeneral;
+ aNewState=RMobileCall::EStatusRinging;
+ }
+ TInt i=0;
+ TInt count=iCalls->Count();
+ for(i=0;i<count;i++)
+ {
+ LOGLINE3(">>CSimLine::ChangeState1 0x%08x %d",iCalls->At(i),iCalls->At(i)->iState);
+ if(iCalls->At(i) != aOriginatingCall && iCalls->At(i)->iState == RMobileCall::EStatusHold)
+ {
+ if(aSwap)
+ {
+ swappedCall=iCalls->At(i);
+ swappedCall->iState=RMobileCall::EStatusConnected;
+ aNewState=RMobileCall::EStatusConnected;
+ }
+ else
+ return KErrAlreadyExists;
+ }
+ }
+ }
+ else if(aNewState==RMobileCall::EStatusConnected)
+ {
+ TInt i=0;
+ TInt count=iCalls->Count();
+ for(i=0;i<count;i++)
+ {
+ LOGLINE3(">>CSimLine::ChangeState1 0x%08x %d",iCalls->At(i),iCalls->At(i)->iState);
+ if(iCalls->At(i) != aOriginatingCall)
+ {
+ if(iCalls->At(i)->iState == RMobileCall::EStatusConnected)
+ {
+ //coverity[dead_error_condition]
+ if(aSwap)
+ {
+ swappedCall=iCalls->At(i);
+ swappedCall->iState=RMobileCall::EStatusHold;
+ aNewState=RMobileCall::EStatusConnected;
+ break;
+ }
+ else
+ //coverity[dead_error_line]
+ return KErrAlreadyExists;
+ }
+ }
+ }
+ }
+
+ // Actually change the state.
+ LOGLINE3(">>CSimLine::ChangeState [oldState=%d] [newState=%d]", iState, aNewState);
+
+ if(iState != aNewState)
+ {
+ iState=aNewState;
+
+ // Check for a pending line state notification (core)
+ if(iNotifyStatusChange.iNotifyPending)
+ {
+ iNotifyStatusChange.iNotifyPending=EFalse;
+ *(RCall::TStatus*)iNotifyStatusChange.iNotifyData=GetCoreLineStatus();
+ ReqCompleted(iNotifyStatusChange.iNotifyHandle,KErrNone);
+ }
+
+ // Check for a pending line state notification (multimode)
+ if(iNotifyMobileStatusChange.iNotifyPending)
+ {
+ iNotifyMobileStatusChange.iNotifyPending=EFalse;
+ *(RMobileCall::TMobileCallStatus*)iNotifyMobileStatusChange.iNotifyData=iState;
+ ReqCompleted(iNotifyMobileStatusChange.iNotifyHandle,KErrNone);
+ }
+
+ // Check for a pending hook state notification.
+ if(iHookState!=ConvertStateToHook(iState))
+ {
+ iHookState=ConvertStateToHook(iState);
+ if(iNotifyHookChange.iNotifyPending)
+ {
+ iNotifyHookChange.iNotifyPending=EFalse;
+ *(RCall::THookStatus*)iNotifyHookChange.iNotifyData=iHookState;
+ ReqCompleted(iNotifyHookChange.iNotifyHandle,KErrNone);
+ }
+ }
+ }
+ // Check for a possible change in capabilities.
+ TUint caps=Caps();
+ if(iCaps!=caps)
+ {
+ iCaps=caps;
+ if(iNotifyCapsChange.iNotifyPending)
+ {
+ iNotifyCapsChange.iNotifyPending=EFalse;
+ ((RLine::TCaps*)iNotifyCapsChange.iNotifyData)->iFlags=iCaps;
+ ReqCompleted(iNotifyCapsChange.iNotifyHandle,KErrNone);
+ }
+ }
+
+ if(aSwap && swappedCall)
+ swappedCall->UpdateNotifiers();
+ // Request that the phone change its state, to ensure its in step.
+ if((ret = iPhone->ValidateChangeState(this,aNewState)) != KErrNone)
+ return ret;
+
+ for(i=0;i<iCalls->Count();i++)
+ {
+ LOGLINE3(">>CSimLine::ChangeState5 0x%08x %d",iCalls->At(i),iCalls->At(i)->iState);
+ }
+
+ LOGLINE1("<<CSimLine::ChangeState");
+ return KErrNone;
+ }
+
+void CSimLine::SimPSEvent(const CSimPubSub::TPubSubProperty aProperty, TInt /*aStatus*/)
+/**
+Handles the P&S notifications for the Line class
+
+@param aProperty The property key representing the notification.
+*/
+ {
+ LOGLINE1(">>CSimLine::SimPSEvent");
+ if(aProperty==iICProperty) // check for this here still, start the timer for amount specified in config file.
+ ProcessIncomingCallEvent();
+ if(aProperty==iRHProperty)
+ ProcessRemoteHangupEvent();
+ LOGLINE1("<<CSimLine::SimPSEvent");
+ }
+
+TInt CSimLine::SetAutoAnswerCallObject(CSimCall* aCallObject)
+/**
+* Attempt to set the call object that will be used to answer the next incoming
+* call. If there is already an AnswerIncomingCall registered, then
+* return with the relevant error.
+*
+* @param aCallObject pointer to the call object
+* @return KErrNone if successful
+*/
+ {
+ LOGLINE1(">>CSimLine::SetAnswerCallObject");
+ if(iAnswerIncomingCallReqPending) // Is there a request already outstanding?
+ return KErrEtelAnswerAlreadyOutstanding;
+
+ iAnswerIncomingCallReqPending=ETrue;
+ if (iAnswerNextIncomingCall!=aCallObject)
+ {
+ if (iSpareCall != iAnswerNextIncomingCall)
+ {
+ iAnswerNextIncomingCall->Close();
+ }
+ iAnswerNextIncomingCall=aCallObject; // Set the "answer next call" object
+ iAnswerNextIncomingCall->Open();
+ }
+ LOGLINE1("<<CSimLine::SetAnswerCallObject");
+ return KErrNone;
+ }
+
+void CSimLine::ResetAutoAnswerCallObject(CSimCall* aCallObject)
+/**
+* This function is used to reset, or effectively cancel, the call object that
+* was to be used to automatically answer the next incoming call.
+*
+* @param aCallObject pointer to the call object
+*/
+ {
+ LOGLINE1(">>CSimLine::ResetAnswerCallObject");
+ __ASSERT_ALWAYS(iAnswerNextIncomingCall==aCallObject,SimPanic(EIllegalAnswerNextIncomingCallInconsistancy));
+ iAnswerNextIncomingCall->Close();
+ iAnswerNextIncomingCall=iSpareCall;
+ iAnswerIncomingCallReqPending=EFalse;
+ }
+
+void CSimLine::ProcessIncomingCallEvent()
+/**
+* Process an incoming call event.
+*/
+ {
+ LOGLINE1(">>CSimLine::ProcessIncomingCallEvent ");
+
+ if (iSpareCall == iAnswerNextIncomingCall)
+ {
+ TName callName;
+ TRAPD(err,iAnswerNextIncomingCall=CreateNewCallL(callName,ECallTypeNormalCall));
+ if (err!=KErrNone)
+ {
+ SimPanic(EOjectNotConstructed);
+ }
+ }
+
+ // Delay sending the notification of an incoming call if
+ // one has been set.
+ iTimer->Start(iNotifyIncomingCallPause, this);
+
+ __ASSERT_ALWAYS(iAnswerNextIncomingCall->ActionEvent(CSimCall::ECallEventIncomingCall,KErrNone) == KErrNone, SimPanic(EGeneral));
+ LOGLINE1("<<CSimLine::ProcessIncomingCallEvent");
+ }
+
+TInt CSimLine::SetRemoteHangupCallObject(CSimCall* aCallObject)
+/**
+* Attempt to set the call object that will be hung up remotely
+* If there is already a RemoteHangup registered, then
+* return with the relevant error.
+*
+* @param aCallObject pointer to the call object
+* @return KErrNone if successful
+*/
+ {
+ LOGLINE1(">>CSimLine::SetRemoteHangupCallObject");
+ if(iRemoteHangupCallReqPending) // Is there a request already outstanding?
+ return KErrEtelInitialisationFailure;
+
+ iRemoteHangupCallReqPending=ETrue;
+ if (iRemoteHangupCall!=aCallObject)
+ {
+ iRemoteHangupCall=aCallObject; // Set the "remote hang up" object
+ }
+ LOGLINE1("<<CSimLine::SetRemoteHangupCallObject");
+ return KErrNone;
+ }
+
+void CSimLine::ResetRemoteHangupCallObject(CSimCall* aCallObject)
+/**
+* This function is used to reset, or effectively cancel, the call object that
+* was to be remotely hung up.
+*
+* @param aCallObject pointer to the call object
+*/
+ {
+ LOGLINE1(">>CSimLine::ResetRemoteHangupCallObject");
+ __ASSERT_ALWAYS(iRemoteHangupCall==aCallObject,SimPanic(EIllegalAnswerRemoteHangupCallInconsistency));
+ iRemoteHangupCallReqPending=EFalse;
+ }
+
+void CSimLine::ProcessRemoteHangupEvent()
+/**
+* Process a remote hangup event.
+*/
+ {
+ LOGLINE1(">>CSimLine::ProcessRemoteHangupEvent");
+
+ if (iRemoteHangupCall == NULL)
+ {
+ TInt err = FindActiveCall(iRemoteHangupCall);
+ if(err == KErrNone)
+ {
+ err = iRemoteHangupCall->ActionEvent(CSimCall::ECallEventRemoteHangup,KErrNone);
+ if(err != KErrNone)
+ {
+ LOGLINE2("ERROR: CSimLine::ProcessRemoteHangupEvent returned: %d", err);
+ }
+ }
+ else
+ {
+ LOGLINE1("No outstanding call to hang up remotely");
+ }
+ }
+ LOGLINE1("<<CSimLine::ProcessRemoteHangupEvent");
+ }
+
+void CSimLine::CallDestructor(CSimCall* aCall)
+/**
+ * This function is called from a call's destructor.
+ * It must delete the call from its list. If the call cannot be found, an unacceptable
+ * inconsistancy must have developed, and the TSY will panic.
+ */
+ {
+ for(TInt i=0;i<iCalls->Count();i++)
+ {
+ if(iCalls->At(i)==aCall)
+ {
+ iCalls->Delete(i);
+ return;
+ }
+ }
+ SimPanic(EIllegalCallNotRegisteredWithLine);
+ }
+
+TBool CSimLine::IsAnswerCallObjectSpare()
+/**
+ * Is the "answer" call object actually the spare object.
+ */
+ {
+ return (iSpareCall==iAnswerNextIncomingCall);
+ }
+
+/**
+Called when iTimer has delayed the sending of the notification of the incoming call.
+*/
+void CSimLine::TimerCallBack(TInt /*aId*/)
+ {
+ ProcessNotifyIncomingCallEvent();
+ }
+
+/**
+Send notification of an incoming call.
+*/
+void CSimLine::ProcessNotifyIncomingCallEvent()
+ {
+ LOGLINE1(">>CSimLine::ProcessNotifyIncomingCallEvent");
+ if(iNotifyIncomingCall.iNotifyPending)
+ {
+ iNotifyIncomingCall.iNotifyPending=EFalse;
+ ((TName*)iNotifyIncomingCall.iNotifyData)->Copy(iAnswerNextIncomingCall->iName);
+ ReqCompleted(iNotifyIncomingCall.iNotifyHandle,KErrNone);
+ }
+ LOGLINE1("<<CSimLine::ProcessNotifyIncomingCallEvent");
+ }
+