telephonyserverplugins/simtsy/src/CSimVoiceCall.cpp
changeset 0 3553901f7fa8
child 19 630d2f34d719
equal deleted inserted replaced
-1:000000000000 0:3553901f7fa8
       
     1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // This file contains the implementation of the Simulator TSY Voice Call functionality.  
       
    15 // The Call classes process the Call-based requests made by ETel clients 
       
    16 // and passed down to the TSY by the ETel Server.
       
    17 // 
       
    18 //
       
    19 
       
    20 /**
       
    21  @file
       
    22 */
       
    23 
       
    24 #include <testconfigfileparser.h>
       
    25 
       
    26 #include "CSimVoiceCall.h"
       
    27 #include "CSimPhone.h"
       
    28 #include "CSimDtmf.h"
       
    29 #include "Simlog.h"
       
    30 #include "CSimTsyMode.h"
       
    31 
       
    32 CSimVoiceCall* CSimVoiceCall::NewL(CSimLine* aLine,const TDesC& aName, CSimPhone* aPhone)
       
    33 /**
       
    34 * Standard two phase constructor.
       
    35 *
       
    36 * @param aLine pointer to the Line object.
       
    37 * @param aName name of the call to be constructed
       
    38 * @return CSimVoiceCall  pointer to the voice call object created
       
    39 * @leave Leaves if no memory or object is not created for any reason
       
    40 */
       
    41 	{
       
    42 	CSimVoiceCall* voiceCall=new(ELeave) CSimVoiceCall(aLine,aName,aPhone);
       
    43 	TCleanupItem newCallVoiceClose(CloseCall,voiceCall);
       
    44 	CleanupStack::PushL(newCallVoiceClose);
       
    45 	voiceCall->ConstructL();
       
    46 	CleanupStack::Pop();
       
    47 	return voiceCall;
       
    48 	}
       
    49 
       
    50 CSimVoiceCall::CSimVoiceCall(CSimLine* aLine,const TDesC& aName, CSimPhone* aPhone)
       
    51 	: CSimCall(aLine,aName,aPhone)
       
    52 /**
       
    53 * Trivial constructor. Calls CSimCall to initialise its members
       
    54 */
       
    55 	{
       
    56 	}
       
    57 
       
    58 void CSimVoiceCall::ConstructL()
       
    59 /**
       
    60 * Second phase of 2-Phase Constructor
       
    61 * Retrieves all the pausing duration tags from the config file
       
    62 *
       
    63 * @param aName name of the voice call to be constructed
       
    64 */
       
    65 	{
       
    66 	LOGVOICE1("Starting to parse Voice Call config parameters...");
       
    67 	iCaps=Caps();
       
    68 	iDiallingPause=iLine->CfgFile()->ItemValue(KDiallingPauseDuration,KDefaultDiallingPauseDuration);
       
    69 	iConnectingPause=iLine->CfgFile()->ItemValue(KConnectingPauseDuration,KDefaultConnectingPauseDuration);
       
    70 	iDisconnectingPause=iLine->CfgFile()->ItemValue(KDisconnectingPauseDuration,KDefaultDisconnectingPauseDuration);
       
    71 	iAnswerIncomingPause=iLine->CfgFile()->ItemValue(KAnswerIncomingPauseDuration,KDefaultAnswerIncomingPauseDuration);
       
    72 	iRemoteHangupPause=iLine->CfgFile()->ItemValue(KRemoteHangupPauseDuration,KDefaultRemoteHangupPauseDuration);
       
    73 
       
    74 	iTimer=CSimTimer::NewL(iLine->iPhone);
       
    75 	CSimCall::ConstructL();
       
    76 	
       
    77 	//If present read in remote party info tag
       
    78 	TPtrC8 callingname, remotenumber;
       
    79 	TInt delay=0;
       
    80 	const CTestConfigItem* item=NULL;
       
    81 	item=iLine->CfgFile()->Item(KNotifyRemotePartyInfo);
       
    82 	TInt ret;
       
    83 	if (item)
       
    84 		{
       
    85 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,delay);
       
    86 		if(ret!=KErrNone)
       
    87 			{
       
    88 			LOGPARSERR("delay",ret,0,&KNotifyRemotePartyInfo);
       
    89 			}
       
    90 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,callingname);
       
    91 		if(ret!=KErrNone)
       
    92 			{
       
    93 			LOGPARSERR("callingname",ret,1,&KNotifyRemotePartyInfo);
       
    94 			}
       
    95 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,remotenumber);
       
    96 		if(ret!=KErrNone)
       
    97 			{
       
    98 			LOGPARSERR("remotenumber",ret,2,&KNotifyRemotePartyInfo);
       
    99 			}
       
   100 		
       
   101 		iNotifyRemotePartyInfoTimer->iDelay = delay;
       
   102 		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iDirection = RMobileCall::EDirectionUnknown;
       
   103 		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iCallingName.Copy(callingname);
       
   104 		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteNumber.iTelNumber.Copy(remotenumber);	
       
   105 		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteNumber.iTypeOfNumber = RMobilePhone::EInternationalNumber;
       
   106 		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteNumber.iNumberPlan = RMobilePhone::EIsdnNumberPlan;
       
   107 		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteIdStatus = RMobileCall::ERemoteIdentityAvailable;					
       
   108 		}
       
   109 	else
       
   110 		{
       
   111 		iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteIdStatus = RMobileCall::ERemoteIdentityUnknown;
       
   112 		}
       
   113 	
       
   114 	LOGVOICE1("...Finished parsing Voice Call config parameters...");
       
   115 	}
       
   116 
       
   117 CSimVoiceCall::~CSimVoiceCall()
       
   118 /**
       
   119 * Destroy all the objects constructed.
       
   120 * CSimTimer and CSimSysAgent objects are destroyed here
       
   121 */
       
   122 	{
       
   123 	delete iTimer;
       
   124 	if(iAnswerIncomingCall.iNotifyPending)
       
   125 		iLine->ResetAutoAnswerCallObject(this);
       
   126 	}
       
   127 
       
   128 TInt CSimVoiceCall::ExtFunc(const TTsyReqHandle aTsyReqHandle,const TInt aIpc,const TDataPackage& aPackage)
       
   129 /**
       
   130 * ExtFunc is called by the server when it has a "extended", i.e. non-core ETel request 
       
   131 * for the TSY to process
       
   132 * A request handle, request type and request data are passed to the TSY
       
   133 *
       
   134 * @param aTsyReqHandle
       
   135 * @param aIpc IPc number representing the request
       
   136 * @param aPackage data for the request
       
   137 * @return KErrNone
       
   138 */
       
   139 	{
       
   140 	TAny* dataPtr=aPackage.Ptr1();
       
   141 
       
   142 	// The request data has to extracted from TDataPackage and the TAny* pointers have to
       
   143 	// be "cast" to the expected request data type
       
   144 
       
   145 	switch (aIpc)
       
   146 		{
       
   147 	//
       
   148 	// No Flow Control NOR Multiple Completion
       
   149 	//
       
   150 	case EMobileCallGetMobileCallCaps:
       
   151 		return GetMobileCallCaps(aTsyReqHandle,aPackage.Des1n());
       
   152 
       
   153 	case EMobileCallGetMobileCallStatus:
       
   154 		return GetMobileCallStatus(aTsyReqHandle,
       
   155 			REINTERPRET_CAST(RMobileCall::TMobileCallStatus*,dataPtr));
       
   156 
       
   157 	case EMobileCallGetMobileCallInfo:
       
   158 		return GetMobileCallInfo(aTsyReqHandle,aPackage.Des1n());
       
   159 
       
   160 	case EMobileCallDialEmergencyCall:
       
   161 		return DialEmergencyCall(aTsyReqHandle,aPackage.Des1u());
       
   162 
       
   163 	case EMobileCallHold:
       
   164 		return Hold(aTsyReqHandle);
       
   165 
       
   166 	case EMobileCallResume:
       
   167 		return Resume(aTsyReqHandle);
       
   168 
       
   169 	case EMobileCallSwap:
       
   170 		return Swap(aTsyReqHandle);
       
   171 	
       
   172 	case EMobileCallDialISV:
       
   173 		return DialISV(aTsyReqHandle, aPackage.Des1n(), aPackage.Des2u());
       
   174 
       
   175 	case EMobileCallAnswerISV:
       
   176 		TInt retVal;
       
   177 		TRAPD(errVal, retVal=AnswerIncomingCallISVL(aTsyReqHandle, aPackage.Des1n()));
       
   178 		if (errVal != KErrNone)
       
   179 			{
       
   180 			return errVal;
       
   181 			}
       
   182 		else
       
   183 			{
       
   184 			return retVal;	
       
   185 			}
       
   186 		
       
   187 	//
       
   188 	// Multiple Completion Services with Immediate Server Repost
       
   189 	// (Usually Notifications)
       
   190 	//
       
   191 	case EMobileCallNotifyMobileCallStatusChange:
       
   192 		return NotifyMobileCallStatusChange(aTsyReqHandle,
       
   193 			REINTERPRET_CAST(RMobileCall::TMobileCallStatus*, dataPtr));
       
   194 
       
   195 	case EMobileCallNotifyMobileCallCapsChange:
       
   196 		return NotifyMobileCallCapsChange(aTsyReqHandle, aPackage.Des1n());
       
   197 		
       
   198 	case EMobileCallNotifyRemotePartyInfoChange:
       
   199 		return NotifyRemotePartyInfoChange(aTsyReqHandle, aPackage.Des1n());		
       
   200 
       
   201 	default:
       
   202 		break;
       
   203 		}
       
   204 	return KErrNotSupported;
       
   205 	}
       
   206 
       
   207 TInt CSimVoiceCall::CancelService(const TInt aIpc,const TTsyReqHandle aTsyReqHandle)
       
   208 /**
       
   209  * Cancel an outstanding request.
       
   210  * @param aIpc The IPC number of the request that must be cancelled.  Note: this is not the
       
   211  *             IPC number of the cancel request itself.
       
   212  * @param aTsyReqHandle The TSY Request Handle of the request to be cancelled.
       
   213  */
       
   214 	{
       
   215 	switch(aIpc)
       
   216 		{
       
   217 	case EMobileCallNotifyMobileCallStatusChange:
       
   218 		return NotifyMobileCallStatusChangeCancel(aTsyReqHandle);
       
   219 
       
   220 	case EMobileCallNotifyMobileCallCapsChange:
       
   221 		return NotifyMobileCallCapsChangeCancel(aTsyReqHandle);
       
   222 
       
   223 	case EMobileCallDialEmergencyCall:
       
   224 		return DialEmergencyCallCancel(aTsyReqHandle);
       
   225 
       
   226 	case EMobileCallHold:
       
   227 		return HoldCancel(aTsyReqHandle);
       
   228 
       
   229 	case EMobileCallResume:
       
   230 		return ResumeCancel(aTsyReqHandle);
       
   231 
       
   232 	case EMobileCallSwap:
       
   233 		return SwapCancel(aTsyReqHandle);
       
   234 		
       
   235 	case EMobileCallNotifyRemotePartyInfoChange:
       
   236 		return NotifyRemotePartyInfoChangeCancel();
       
   237 		
       
   238 	case EMobileCallDialISV:
       
   239 		return DialISVCancel(aTsyReqHandle);
       
   240 		
       
   241 	case EMobileCallAnswerISV:
       
   242 		return AnswerIncomingCallISVCancel(aTsyReqHandle);       
       
   243 	default:
       
   244 		break;
       
   245 		}
       
   246 
       
   247 	return CCallBase::CancelService(aIpc,aTsyReqHandle);
       
   248 	}
       
   249 
       
   250 TInt CSimVoiceCall::DialEmergencyCall(const TTsyReqHandle aTsyReqHandle,TDesC* aTelNumber)
       
   251 /**
       
   252 * Process a client's emergency call request.
       
   253 *
       
   254 * @param aTsyReqHandle
       
   255 * @param aTelNumber The telephone number to dial
       
   256 * @return KErrNone
       
   257 */
       
   258 	{
       
   259 	return Dial(aTsyReqHandle,NULL,aTelNumber);
       
   260 	}
       
   261 
       
   262 TInt CSimVoiceCall::DialEmergencyCallCancel(const TTsyReqHandle aTsyReqHandle)
       
   263 /**
       
   264 * Cancels an emergency call request.
       
   265 *
       
   266 * @param aTsyReqHandle
       
   267 * @return KErrNone if successfully cancelled
       
   268 */
       
   269 	{
       
   270 	return DialCancel(aTsyReqHandle);
       
   271 	}
       
   272 
       
   273 TInt CSimVoiceCall::Dial(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams,TDesC* /*aTelNumber*/)
       
   274 /**
       
   275 * Process a client's dial request.
       
   276 *
       
   277 * @param aTsyReqHandle
       
   278 * @param aCallParams  the call parameters
       
   279 * @param aTelNumber The telephone number to dial
       
   280 * @return KErrNone
       
   281 */
       
   282 	{
       
   283 	LOGVOICE1(">>CSimVoiceCall::Dial");
       
   284 	// Note: The telephone number and call parameters should be validated against config file
       
   285 	//       values here.
       
   286 	
       
   287 	//see where the dial request has orignated from
       
   288 	if(aCallParams)
       
   289 		{
       
   290 		RCall::TCallParamsPckg* callparamsPckg=reinterpret_cast<RCall::TCallParamsPckg*>(const_cast<TDesC8*>(aCallParams));
       
   291 		RCall::TCallParams& callparams=(*callparamsPckg)();
       
   292 		
       
   293 		if(callparams.ExtensionId() == RMobileCall::KETel3rdPartyCallParamsV1)
       
   294 			{
       
   295 			LOGVOICE1("<<CSimVoiceCall::Dial request from Etel 3rd Party client.");
       
   296 			}
       
   297 		}
       
   298 
       
   299 	iDialRequestHandle=aTsyReqHandle;
       
   300 	TInt ret;
       
   301 	ret = ActionEvent(ECallEventDial,KErrNone);
       
   302 	LOGVOICE1("<<CSimVoiceCall::Dial");
       
   303 	return ret;
       
   304 	}
       
   305 	
       
   306 TInt CSimVoiceCall::DialCancel(const TTsyReqHandle /*aTsyReqHandle*/)
       
   307 /**
       
   308 * Cancels a dial Request
       
   309 *
       
   310 * @param aTsyReqHandle
       
   311 * @return KErrNone if successfully cancelled
       
   312 */
       
   313 	{
       
   314 	LOGVOICE1(">>CSimVoiceCall::DialCancel");
       
   315 	switch(iState)
       
   316 		{
       
   317 	case RMobileCall::EStatusIdle:
       
   318 		SimPanic(EIllegalCancelRequest);		// A DialCancel should never reach the TSY in this state.
       
   319 		break;
       
   320 
       
   321 	case RMobileCall::EStatusDialling:
       
   322 	case RMobileCall::EStatusConnecting:
       
   323 		iTimer->DoCancel();
       
   324 		// Can ignore for cancel
       
   325 		TInt err;
       
   326 		err = KErrNone;
       
   327 		TRAP(err, (void)ChangeStateL(RMobileCall::EStatusIdle,EFalse,EFalse));
       
   328 		if (err != KErrNone)
       
   329 			{
       
   330 			ReqCompleted(iDialRequestHandle, err);
       
   331 			}
       
   332 		else
       
   333 			{
       
   334 			ReqCompleted(iDialRequestHandle, KErrCancel);
       
   335 			}
       
   336 		break;
       
   337 
       
   338 	case RMobileCall::EStatusConnected:
       
   339 		SimPanic(EIllegalCancelRequest);		// A DialCancel should never reach the TSY in this state.
       
   340 		break;
       
   341 
       
   342 	default:
       
   343 		break;
       
   344 		}
       
   345 	LOGVOICE1("<<CSimVoiceCall::DialCancel");
       
   346 	return KErrNone;
       
   347 	}
       
   348 
       
   349 TInt CSimVoiceCall::DialISV(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams,TDesC* /*aTelNumber*/)
       
   350 /**
       
   351 * Process an EtelISV client's dial request.
       
   352 *
       
   353 * @param aTsyReqHandle
       
   354 * @param aCallParams  the call parameters
       
   355 * @param aTelNumber The telephone number to dial
       
   356 * @return KErrNone
       
   357 */
       
   358 	{
       
   359 	LOGVOICE1(">>CSimVoiceCall::DialISV");
       
   360 	// Note: The telephone number and call parameters should be validated against config file
       
   361 	//       values here.
       
   362 	
       
   363 	//see where the dial request has orignated from
       
   364 	if(aCallParams)
       
   365 		{
       
   366 		RCall::TCallParamsPckg* callparamsPckg=reinterpret_cast<RCall::TCallParamsPckg*>(const_cast<TDesC8*>(aCallParams));
       
   367 		RCall::TCallParams& callparams=(*callparamsPckg)();
       
   368 		
       
   369 		if(callparams.ExtensionId() == RMobileCall::KETel3rdPartyCallParamsV1)
       
   370 			{
       
   371 			LOGVOICE1("<<CSimVoiceCall::Dial request from Etel 3rd Party client.");
       
   372 			}
       
   373 		}
       
   374 
       
   375 	iDialRequestHandle=aTsyReqHandle;
       
   376 	TInt ret;
       
   377 	ret = ActionEvent(ECallEventDial,KErrNone);
       
   378 	LOGVOICE1("<<CSimVoiceCall::DialISV");
       
   379 	return ret;
       
   380 	}
       
   381 
       
   382 TInt CSimVoiceCall::DialISVCancel(const TTsyReqHandle /*aTsyReqHandle*/)
       
   383 /**
       
   384 * Cancels an EtelISV originated dial Request
       
   385 *
       
   386 * @param aTsyReqHandle
       
   387 * @return KErrNone if successfully cancelled
       
   388 */
       
   389 	{
       
   390 	LOGVOICE1(">>CSimVoiceCall::DialISVCancel");
       
   391 	switch(iState)
       
   392 		{
       
   393 	case RMobileCall::EStatusIdle:
       
   394 		SimPanic(EIllegalCancelRequest);		// A DialCancel should never reach the TSY in this state.
       
   395 		break;
       
   396 
       
   397 	case RMobileCall::EStatusDialling:
       
   398 	case RMobileCall::EStatusConnecting:
       
   399 		iTimer->DoCancel();
       
   400 		// Can ignore for cancel
       
   401 		TInt err;
       
   402 		err = KErrNone;
       
   403 		TRAP(err, (void)ChangeStateL(RMobileCall::EStatusIdle,EFalse,EFalse));
       
   404 		if (err != KErrNone)
       
   405 			{
       
   406 			ReqCompleted(iDialRequestHandle, err);
       
   407 			}
       
   408 		else
       
   409 			{
       
   410 			ReqCompleted(iDialRequestHandle, KErrCancel);
       
   411 			}
       
   412 		break;
       
   413 
       
   414 	case RMobileCall::EStatusConnected:
       
   415 		SimPanic(EIllegalCancelRequest);		// A DialCancel should never reach the TSY in this state.
       
   416 		break;
       
   417 
       
   418 	default:
       
   419 		break;
       
   420 		}
       
   421 	LOGVOICE1("<<CSimVoiceCall::DialISVCancel");
       
   422 	return KErrNone;
       
   423 	}
       
   424 
       
   425 TInt CSimVoiceCall::AnswerIncomingCall(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams)
       
   426 /**
       
   427 * Register a client's interest in answering the next incoming call.
       
   428 * First register interest in incoming calls with the line, then, if a call
       
   429 * is already ringing, start the answer procedure.
       
   430 *
       
   431 * @param aTsyReqHandle
       
   432 * @param aCallParams  the call parameters
       
   433 * @return KErrNone
       
   434 */
       
   435 	{
       
   436 	LOGVOICE3(">>CSimVoiceCall::AnswerIncomingCall  0x%08x, state %d entry ",this,iState);
       
   437 	
       
   438 	//see where the answer request has orignated from
       
   439 	if(aCallParams)
       
   440 		{
       
   441 		RCall::TCallParamsPckg* callparamsPckg=reinterpret_cast<RCall::TCallParamsPckg*>(const_cast<TDesC8*>(aCallParams));
       
   442 		RCall::TCallParams& callparams=(*callparamsPckg)();
       
   443 		
       
   444 		if(callparams.ExtensionId() == RMobileCall::KETel3rdPartyCallParamsV1)
       
   445 			{
       
   446 			LOGVOICE1("<<CSimVoiceCall::AnswerIncomingCall request from Etel 3rd Party client.");
       
   447 			}
       
   448 		}
       
   449 	
       
   450 	TInt ret=iLine->SetAutoAnswerCallObject(this);
       
   451 	if(ret!=KErrNone)
       
   452 		{
       
   453 		ReqCompleted(aTsyReqHandle,ret);
       
   454 		return KErrNone;
       
   455 		}
       
   456 
       
   457 	iAnswerIncomingCall.iNotifyPending=ETrue;
       
   458 	iAnswerIncomingCall.iNotifyHandle=aTsyReqHandle;
       
   459 
       
   460 	if(iState==RMobileCall::EStatusRinging)
       
   461 			ret = ActionEvent(ECallEventAnswerIncoming,KErrNone);	
       
   462 	else if(iLine->iState==RMobileCall::EStatusRinging)
       
   463 		{		
       
   464 		TRAPD(errVal, ret=ChangeStateL(RMobileCall::EStatusRinging,EFalse,EFalse));
       
   465 		if (errVal != KErrNone)
       
   466 			{
       
   467 			ret = errVal;
       
   468 			}
       
   469 
       
   470 		if(ret==KErrNone)
       
   471 			ret = ActionEvent(ECallEventAnswerIncoming,KErrNone);		
       
   472 		}
       
   473 	LOGVOICE3("<<CSimVoiceCall::AnswerIncomingCall  0x%08x, state %d exit",this,iState);
       
   474 	return ret;
       
   475 	}
       
   476 
       
   477 TInt CSimVoiceCall::AnswerIncomingCallCancel(const TTsyReqHandle /*aTsyReqHandle*/)
       
   478 /**
       
   479 * Cancels a AnswerIncomingCall Request
       
   480 *
       
   481 * @param aTsyReqHandle
       
   482 * @return KErrNone if successfully cancelled
       
   483 */
       
   484 	{
       
   485 	LOGVOICE1(">>CSimVoiceCall::AnswerIncomingCallCancel");
       
   486 	if(iAnswerIncomingCall.iNotifyPending)
       
   487 		{
       
   488 		iAnswerIncomingCall.iNotifyPending=EFalse;
       
   489 		iLine->ResetAutoAnswerCallObject(this);
       
   490 		ReqCompleted(iAnswerIncomingCall.iNotifyHandle,KErrCancel);
       
   491 		}
       
   492 	LOGVOICE1("<<CSimVoiceCall::AnswerIncomingCallCancel");
       
   493 	return KErrNone;
       
   494 	}
       
   495 
       
   496 TInt CSimVoiceCall::AnswerIncomingCallISVL(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams)
       
   497 /**
       
   498 * Register an EtelISV client's interest in answering the next incoming call.
       
   499 * First register interest in incoming calls with the line, then, if a call
       
   500 * is already ringing, start the answer procedure.
       
   501 *
       
   502 * @param aTsyReqHandle
       
   503 * @param aCallParams  the call parameters
       
   504 * @return KErrNone
       
   505 */
       
   506 	{
       
   507 	LOGVOICE3(">>CSimVoiceCall::AnswerIncomingCallISV  0x%08x, state %d entry ",this,iState);
       
   508 	
       
   509 	//see where the answer request has orignated from
       
   510 	if(aCallParams)
       
   511 		{
       
   512 		RCall::TCallParamsPckg* callparamsPckg=reinterpret_cast<RCall::TCallParamsPckg*>(const_cast<TDesC8*>(aCallParams));
       
   513 		RCall::TCallParams& callparams=(*callparamsPckg)();
       
   514 		
       
   515 		if(callparams.ExtensionId() == RMobileCall::KETel3rdPartyCallParamsV1)
       
   516 			{
       
   517 			LOGVOICE1("<<CSimVoiceCall::AnswerIncomingCallISV request from Etel 3rd Party client.");
       
   518 			}
       
   519 		}
       
   520 	
       
   521 	TInt ret=iLine->SetAutoAnswerCallObject(this);
       
   522 	if(ret!=KErrNone)
       
   523 		{
       
   524 		ReqCompleted(aTsyReqHandle,ret);
       
   525 		return KErrNone;
       
   526 		}
       
   527 
       
   528 	iAnswerIncomingCall.iNotifyPending=ETrue;
       
   529 	iAnswerIncomingCall.iNotifyHandle=aTsyReqHandle;
       
   530 
       
   531 	if(iState==RMobileCall::EStatusRinging)
       
   532 			ret = ActionEvent(ECallEventAnswerIncoming,KErrNone);	
       
   533 	else if(iLine->iState==RMobileCall::EStatusRinging)
       
   534 			{
       
   535 			TRAPD(leaveValue, ret=ChangeStateL(RMobileCall::EStatusRinging,EFalse,EFalse));
       
   536 			if (leaveValue != KErrNone)
       
   537 				{
       
   538 				return leaveValue;
       
   539 				}
       
   540 
       
   541 			if (ret == KErrNone)
       
   542                 {
       
   543 				ret = ActionEvent(ECallEventAnswerIncoming,KErrNone);		
       
   544 	 		    }		
       
   545 		}
       
   546 	LOGVOICE3("<<CSimVoiceCall::AnswerIncomingCallISV  0x%08x, state %d exit",this,iState);
       
   547 	return ret;
       
   548 	}
       
   549 
       
   550 TInt CSimVoiceCall::AnswerIncomingCallISVCancel(const TTsyReqHandle /*aTsyReqHandle*/)
       
   551 /**
       
   552 * Cancels an EtelISV originated AnswerIncomingCall Request
       
   553 *
       
   554 * @param aTsyReqHandle
       
   555 * @return KErrNone if successfully cancelled
       
   556 */
       
   557 	{
       
   558 	LOGVOICE1(">>CSimVoiceCall::AnswerIncomingCallISVCancel");
       
   559 	if(iAnswerIncomingCall.iNotifyPending)
       
   560 		{
       
   561 		iAnswerIncomingCall.iNotifyPending=EFalse;
       
   562 		iLine->ResetAutoAnswerCallObject(this);
       
   563 		ReqCompleted(iAnswerIncomingCall.iNotifyHandle,KErrCancel);
       
   564 		}
       
   565 	LOGVOICE1("<<CSimVoiceCall::AnswerIncomingCallISVCancel");
       
   566 	return KErrNone;
       
   567 	}
       
   568 
       
   569 TInt CSimVoiceCall::Connect(const TTsyReqHandle aTsyReqHandle,const TDesC8* /*aCallParams*/)
       
   570 	{
       
   571 	ReqCompleted(aTsyReqHandle,KErrNotSupported);
       
   572 	return KErrNone;
       
   573 	}
       
   574 
       
   575 TInt CSimVoiceCall::ConnectCancel(const TTsyReqHandle aTsyReqHandle)
       
   576 	{
       
   577 	ReqCompleted(aTsyReqHandle,KErrNotSupported);
       
   578 	return KErrNone;
       
   579 	}
       
   580 
       
   581 TInt CSimVoiceCall::HangUp(const TTsyReqHandle aTsyReqHandle)
       
   582 /**
       
   583 * Process a client's HangUp request.
       
   584 *
       
   585 * @param aTsyReqHandle
       
   586 * @return KErrNone
       
   587 */
       
   588 	{
       
   589 	LOGVOICE1(">>CSimVoiceCall::HangUp");
       
   590 	iHangUpRequestHandle=aTsyReqHandle;
       
   591 	TInt ret=ActionEvent(ECallEventHangUp,KErrNone);
       
   592 	if(ret!=KErrNone)
       
   593 		ReqCompleted(aTsyReqHandle,ret);
       
   594 	LOGVOICE1("<<CSimVoiceCall::HangUp");
       
   595 	return KErrNone;
       
   596 	}
       
   597 
       
   598 TInt CSimVoiceCall::HangUpCancel(const TTsyReqHandle /*aTsyReqHandle*/)
       
   599 /**
       
   600 * Cancels a HangUp Request
       
   601 *
       
   602 * @param aTsyReqHandle
       
   603 * @return KErrNone if successfully cancelled
       
   604 */
       
   605 	{
       
   606 	LOGVOICE1(">>CSimVoiceCall::HangUpCancel");
       
   607 	switch(iState)
       
   608 		{
       
   609 	case RMobileCall::EStatusIdle:
       
   610 		SimPanic(EIllegalCancelRequest);		// A DialCancel should never reach the TSY in this state.
       
   611 		break;
       
   612 
       
   613 	case RMobileCall::EStatusDisconnecting:
       
   614 		iTimer->DoCancel();
       
   615 		// Can ignore for cancel
       
   616 		TInt err;
       
   617 		err = KErrNone;
       
   618 		TRAP(err, (void)ChangeStateL(RMobileCall::EStatusConnected,EFalse,EFalse));
       
   619 		if (err != KErrNone)
       
   620 			{
       
   621 			ReqCompleted(iHangUpRequestHandle, err);
       
   622 			}
       
   623 		else
       
   624 			{
       
   625 			ReqCompleted(iHangUpRequestHandle, KErrCancel);
       
   626 			}
       
   627 		break;
       
   628 
       
   629 	default:
       
   630 		break;
       
   631 		}
       
   632 	LOGVOICE1("<<CSimVoiceCall::HangUpCancel");
       
   633 	return KErrNone;
       
   634 	}
       
   635 
       
   636 TInt CSimVoiceCall::RelinquishOwnership()
       
   637 	{
       
   638 	return KErrNotSupported;
       
   639 	}
       
   640 
       
   641 TInt CSimVoiceCall::GetBearerServiceInfo(const TTsyReqHandle aTsyReqHandle,RCall::TBearerService* /*aBearerService*/)
       
   642 /**
       
   643 * Retrieves the bearer service info
       
   644 * Not supported for voice calls
       
   645 */
       
   646 	{
       
   647 	ReqCompleted(aTsyReqHandle,KErrNotSupported);
       
   648 	return KErrNone;
       
   649 	}
       
   650 
       
   651 TInt CSimVoiceCall::GetCallParams(const TTsyReqHandle aTsyReqHandle, TDes8* /*aParams*/)
       
   652 /**
       
   653 * Retrives the call parameters
       
   654 * Not supported for voice calls
       
   655 */
       
   656 	{
       
   657 	ReqCompleted(aTsyReqHandle,KErrNotSupported);
       
   658 	return KErrNone;
       
   659 	}
       
   660 
       
   661 TInt CSimVoiceCall::LoanDataPort(const TTsyReqHandle,RCall::TCommPort*)
       
   662 /**
       
   663 * Loans the comm port.
       
   664 * This is a data call specific request so not supported here.
       
   665 */
       
   666 	{
       
   667 	return KErrNotSupported;
       
   668 	}
       
   669 /**
       
   670 * Cancels the LoanDataPort request.
       
   671 * This is a data call specific request so not supported here.
       
   672 */
       
   673 
       
   674 TInt CSimVoiceCall::LoanDataPortCancel(const TTsyReqHandle)
       
   675 	{
       
   676 	return KErrNotSupported;
       
   677 	}
       
   678 
       
   679 TInt CSimVoiceCall::RecoverDataPort(const TTsyReqHandle)
       
   680 /**
       
   681 * Recovers the comm port.
       
   682 * This is a data call specific request so not supported here.
       
   683 */
       
   684 	{
       
   685 	return KErrNotSupported;
       
   686 	}
       
   687 
       
   688 TInt CSimVoiceCall::Hold(const TTsyReqHandle aReqHandle)
       
   689 /**
       
   690  * Put the call on hold.
       
   691  * @param aReqHandle	The request handle associated with this call.
       
   692  * @return TInt			Standard error value.
       
   693  */
       
   694 	{
       
   695 	if(iState!=RMobileCall::EStatusConnected)
       
   696 		{
       
   697 		ReqCompleted(aReqHandle,KErrEtelCallNotActive);
       
   698 		return KErrNone;
       
   699 		}
       
   700 	iHoldResumeRequestHandle=aReqHandle;
       
   701 	TInt ret=ActionEvent(ECallEventHold,KErrNone);
       
   702 	return ret;
       
   703 	}
       
   704 
       
   705 TInt CSimVoiceCall::HoldCancel(const TTsyReqHandle)
       
   706 /**
       
   707  * Cancel a Hold request.  Since hold is completed synchronously, this function is empty.
       
   708  */
       
   709 	{
       
   710 	return KErrNone;
       
   711 	}
       
   712 	
       
   713 /**
       
   714  * Cancel a NotifyConnectConfirmation request. It is possible to cancel
       
   715  * a pending notification if the client did not issue a Dial request.
       
   716  * @param aReqHandle	The request handle associated with this call.
       
   717  */
       
   718 TInt CSimVoiceCall::NotifyConnectConfirmationCancel(const TTsyReqHandle aReqHandle)
       
   719 	{
       
   720 	if (iNotifyConnectConfirmReqHandle==aReqHandle)
       
   721 		{
       
   722 		iNotifyConnectConfirmReqHandle = NULL;
       
   723 		}
       
   724 	ReqCompleted(aReqHandle,KErrCancel);
       
   725 	return KErrNone;
       
   726 	}
       
   727 
       
   728 /**
       
   729  * Resume a pending MO Connection.
       
   730  * @param aReqHandle	The request handle associated with this call.
       
   731  * @param aConnectContinue	Boolean to indicate whether to continue/terminate 
       
   732  *							the call connection.
       
   733  * @return TInt			Standard error value.
       
   734  */
       
   735 TInt CSimVoiceCall::ResumeConnect(const TTsyReqHandle aReqHandle, const TBool * aConnectContinue)
       
   736 	{
       
   737 	TInt ret=KErrNone;
       
   738 	
       
   739 	if(iWaitForConnectConfirm)
       
   740 		{
       
   741 		// synchronous operation for either case
       
   742 		if (*aConnectContinue)
       
   743 			{
       
   744 			// okay to continue, initiate dialing, this will
       
   745 			// change the state
       
   746 			ret=ActionEvent(ECallEventConnectContinue,KErrNone);
       
   747 			}
       
   748 		else
       
   749 			{
       
   750 			// terminate the call...
       
   751 	
       
   752 			// there must be a dial request previously issue,
       
   753 			// but we never send the dial request down to call-stack,
       
   754 			// and we did not invoke the dial timer, so it will
       
   755 			// never expire, so we complete the dial request here
       
   756 			ReqCompleted(iDialRequestHandle,KErrNone);
       
   757 			}
       
   758 			
       
   759 		// complete the resume request
       
   760 		ReqCompleted(aReqHandle,ret);
       
   761 		}
       
   762 	else
       
   763 		{
       
   764 		// client did not issue dial request previously, this request
       
   765 		// is received in the wrong state, reject this request
       
   766 		ReqCompleted(aReqHandle,KErrAccessDenied);
       
   767 		}
       
   768 	return ret;
       
   769 	}
       
   770 	
       
   771 /**
       
   772  * Cancel a ResumeConnect request.  Since resume is completed synchronously, this function is empty.
       
   773  */
       
   774 TInt CSimVoiceCall::ResumeConnectCancel(const TTsyReqHandle)
       
   775 	{
       
   776 	return KErrNone;
       
   777 	}
       
   778 
       
   779 
       
   780 TInt CSimVoiceCall::Resume(const TTsyReqHandle aReqHandle)
       
   781 /**
       
   782  * Put the call on resume.
       
   783  * @param aReqHandle	The request handle associated with this call.
       
   784  * @return TInt			Standard error value.
       
   785  */
       
   786 	{
       
   787 	if(iState!=RMobileCall::EStatusHold)
       
   788 		{
       
   789 		ReqCompleted(aReqHandle,KErrAccessDenied);
       
   790 		return KErrNone;
       
   791 		}
       
   792 	iHoldResumeRequestHandle=aReqHandle;
       
   793 	TInt ret=ActionEvent(ECallEventResume,KErrNone);
       
   794 	return ret;
       
   795 	}
       
   796 
       
   797 
       
   798 TInt CSimVoiceCall::ResumeCancel(const TTsyReqHandle)
       
   799 /**
       
   800  * Cancel a Resume request.  Since resume is completed synchronously, this function is empty.
       
   801  */
       
   802 	{
       
   803 	return KErrNone;
       
   804 	}
       
   805 
       
   806 TInt CSimVoiceCall::Swap(const TTsyReqHandle aReqHandle)
       
   807 /**
       
   808  * If the call is active, put it on hold.  If its on hold, resume it.
       
   809  * @param aReqHandle	The request handle associated with this call.
       
   810  * @return TInt			Standard error value.
       
   811  */
       
   812 	{
       
   813 	TCallEvent event;
       
   814 	if(iState==RMobileCall::EStatusConnected)
       
   815 		{
       
   816 		event=ECallEventHold;		
       
   817 		}
       
   818 	else if(iState==RMobileCall::EStatusHold)
       
   819 		{	
       
   820 		event=ECallEventResume;
       
   821 		}
       
   822 	else
       
   823 		{
       
   824 		ReqCompleted(aReqHandle,KErrEtelCallNotActive);
       
   825 		return KErrNone;
       
   826 		}
       
   827 
       
   828 	iHoldResumeRequestHandle=aReqHandle;
       
   829 	TInt ret=ActionEvent(event,ECallEventSwap);	
       
   830 	return ret;
       
   831 	}
       
   832 
       
   833 TInt CSimVoiceCall::SwapCancel(const TTsyReqHandle)
       
   834 /**
       
   835  * Cancel a Swap request.  Since swap is completed synchronously, this function is empty.
       
   836  */
       
   837 	{
       
   838 	return KErrNone;
       
   839 	}
       
   840 
       
   841 TInt CSimVoiceCall::ActionEvent(TCallEvent aEvent,TInt aOtherArgument)
       
   842 /**
       
   843 * Entry point when an event has occured that may advance the state machine.
       
   844 * The aEvent parameter describes the event.
       
   845 *
       
   846 * This function contains the main state machine for the voice call.  The outer layer
       
   847 * switches on the event type.  Where appropriate, there are inner layer switches
       
   848 * or conditional statements to handle the different responses that may be required to
       
   849 * the same event occurring in different states.
       
   850 *
       
   851 * @param aEvent The Call event to handle
       
   852 * @return value represents the error state caused by the attempted state machine jump.
       
   853 */
       
   854 	{
       
   855 	TInt ret=KErrNone;
       
   856 	__ASSERT_ALWAYS(iState!=RMobileCall::EStatusUnknown,SimPanic(ECallStatusUnknownIllegal));
       
   857 	__ASSERT_ALWAYS(aEvent!=ECallEventNtRasConnected,SimPanic(ECallEventIllegal));
       
   858 	LOGVOICE3(">>CSimVoiceCall::ActionEvent 0x%08x %d",this,iState);
       
   859 
       
   860 	switch(aEvent)
       
   861 		{
       
   862 	case ECallEventDial:
       
   863 		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventDial]");
       
   864 		if(iState==RMobileCall::EStatusIdle)
       
   865 			{			
       
   866 			TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusDialling,EFalse,EFalse));
       
   867 			if(ret==KErrNone)
       
   868 				iTimer->Start(iDiallingPause,this);
       
   869 			}
       
   870 		else
       
   871 			return KErrEtelCallAlreadyActive;
       
   872 		break;
       
   873 
       
   874 	case ECallEventHangUp:
       
   875 		{
       
   876 		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventHangUp]");
       
   877 		switch(iState)
       
   878 			{
       
   879 		case RMobileCall::EStatusDialling:
       
   880 		case RMobileCall::EStatusRinging:
       
   881 		case RMobileCall::EStatusAnswering:
       
   882 		case RMobileCall::EStatusConnecting:
       
   883 		case RMobileCall::EStatusConnected:
       
   884 		case RMobileCall::EStatusHold:
       
   885 			TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusDisconnecting,EFalse,EFalse));
       
   886 			if(ret==KErrNone)
       
   887 				iTimer->Start(iDisconnectingPause,this);
       
   888 			if(iSimDtmf)
       
   889 				{
       
   890 				iSimDtmf->CallClosureCallback();
       
   891 				iSimDtmf=NULL;
       
   892 				}
       
   893 			break;
       
   894 		default:
       
   895 			return KErrEtelCallNotActive;
       
   896 			}
       
   897 		}
       
   898 		break;
       
   899 
       
   900 	case ECallEventIncomingCall:
       
   901 		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventIncomingCall]");
       
   902 		if(iState==RMobileCall::EStatusIdle)
       
   903 			{
       
   904 			if(iAnswerIncomingCall.iNotifyPending)
       
   905 				{
       
   906 				TRAP(ret,	 ret=ProcessAnswerIncomingCallL());
       
   907 				}
       
   908 			else
       
   909 				{
       
   910 				TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusRinging,EFalse,EFalse));
       
   911 				if(ret!=KErrNone)
       
   912 					return ret;
       
   913 				}
       
   914 			}
       
   915 		else
       
   916 			return KErrEtelCallAlreadyActive;
       
   917 		break;
       
   918 
       
   919 	case ECallEventAnswerIncoming:
       
   920 		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventAnswerIncoming]");
       
   921 		if(iState==RMobileCall::EStatusRinging)
       
   922 			{
       
   923 			TRAP(ret, ret=ProcessAnswerIncomingCallL());
       
   924 			if(ret!=KErrNone)
       
   925 				{
       
   926 				return ret;
       
   927 				}
       
   928 			}
       
   929 		else
       
   930 			SimPanic(EIllegalStateInconsistancy);		// This is checked before calling ActionEvent
       
   931 		break;
       
   932 
       
   933 	case ECallEventRemoteHangup:
       
   934 		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventRemoteHangup]");
       
   935 		if(iState==RMobileCall::EStatusConnected)
       
   936 			{
       
   937 			TRAP(ret, ret=ProcessRemoteHangupL());
       
   938 			if(ret!=KErrNone)
       
   939 				{
       
   940 				return ret;
       
   941 				}
       
   942 			}
       
   943 		else
       
   944 			SimPanic(EIllegalStateInconsistancy);		// This is checked before calling ActionEvent
       
   945 		break;
       
   946 
       
   947 	case ECallEventTimeOut:
       
   948 			{
       
   949 			LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventTimeOut]");
       
   950 			switch(iState)
       
   951 				{
       
   952 			case RMobileCall::EStatusDialling:
       
   953 				LOGVOICE1(">>CSimVoiceCall::State = [EStatusDialling]");
       
   954 				TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusConnecting,EFalse,EFalse));
       
   955 				if(ret==KErrNone)
       
   956 					iTimer->Start(iConnectingPause,this);
       
   957 				return ret;
       
   958 			
       
   959 			case RMobileCall::EStatusConnecting:
       
   960 				LOGVOICE1(">>CSimVoiceCall::State = [EStatusConnecting]");
       
   961 				TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusConnected,EFalse,EFalse));
       
   962 				UpdateRemotePartyInfoDirection(RMobileCall::EStatusConnecting);
       
   963 				ReqCompleted(iDialRequestHandle,ret);
       
   964 				return ret;
       
   965 				
       
   966 			case RMobileCall::EStatusDisconnecting:
       
   967 				LOGVOICE1(">>CSimVoiceCall::State = [EStatusDisconnecting]");
       
   968 				TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusIdle,EFalse,EFalse));
       
   969 				ReqCompleted(iHangUpRequestHandle,ret);
       
   970 				return ret;
       
   971 				
       
   972 			case RMobileCall::EStatusAnswering:
       
   973 				LOGVOICE1(">>CSimVoiceCall::State = [EStatusAnswering]");
       
   974 				TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusConnected,EFalse,EFalse));
       
   975 				UpdateRemotePartyInfoDirection(RMobileCall::EStatusAnswering);
       
   976 				ReqCompleted(iAnswerIncomingCall.iNotifyHandle,ret);
       
   977 				return ret;
       
   978 
       
   979 			default:
       
   980 				break;
       
   981 				}
       
   982 			}
       
   983 		break;
       
   984 	case ECallEventHold:
       
   985 		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventHold]");
       
   986 		__ASSERT_ALWAYS(iState==RMobileCall::EStatusConnected,SimPanic(EIllegalStateInconsistancy));
       
   987 		TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusHold,aOtherArgument == ECallEventSwap,EFalse));
       
   988 		if (ret == KErrNone)
       
   989 			ReqCompleted(iHoldResumeRequestHandle,ret);
       
   990 		break;
       
   991 
       
   992 	case ECallEventResume:
       
   993 		LOGVOICE1(">>CSimVoiceCall::ActionEvent = [ECallEventResume]");
       
   994 		__ASSERT_ALWAYS(iState==RMobileCall::EStatusHold,SimPanic(EIllegalStateInconsistancy));
       
   995 		TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusConnected,aOtherArgument == ECallEventSwap,EFalse));
       
   996 		if (ret == KErrNone)
       
   997 			ReqCompleted(iHoldResumeRequestHandle,ret);
       
   998 		break;
       
   999 
       
  1000 	case ECallEventConnectContinue:
       
  1001 		SimPanic(EIllegalVoiceCallEvent);	// All other events not legal for voice call.
       
  1002 		break;
       
  1003 	default:
       
  1004 		SimPanic(EIllegalVoiceCallEvent);	// All other events not legal for voice call.
       
  1005 		break;
       
  1006 		}
       
  1007 
       
  1008 	return ret;
       
  1009 	}
       
  1010 
       
  1011 
       
  1012 void CSimVoiceCall::TimerCallBack(TInt /*aId*/)
       
  1013 /**
       
  1014 * Timer callback function.  When the timer goes off, it will call back into this
       
  1015 * function for further processing.
       
  1016 */
       
  1017 	{
       
  1018 	LOGVOICE1(">>CSimVoiceCall::TimerCallBack");
       
  1019 	TInt ret=ActionEvent(ECallEventTimeOut,KErrNone);
       
  1020 	__ASSERT_ALWAYS(ret==KErrNone,SimPanic(ETimeOutEventActionFailed));
       
  1021 	LOGVOICE1("<<CSimVoiceCall::TimerCallBack");
       
  1022 	}
       
  1023 
       
  1024 TInt CSimVoiceCall::ProcessAnswerIncomingCallL()
       
  1025 /**
       
  1026 * Answers an Incoming Call.
       
  1027 * First the call state must be changed to "answering", then the flag indicating
       
  1028 * that an answer incoming call request is no longer pending.  Finally, a new
       
  1029 * call object must be assigned to receive the details of the next incoming call.
       
  1030 */
       
  1031 	{
       
  1032 	LOGVOICE3(">>CSimVoiceCall::ProcessAnswerIncomingCall %d",iState,this);
       
  1033 	TInt ret=ChangeStateL(RMobileCall::EStatusAnswering,EFalse,EFalse);
       
  1034 	if(ret!=KErrNone)
       
  1035 		return ret;
       
  1036 	iTimer->Start(iAnswerIncomingPause,this);
       
  1037 	iAnswerIncomingCall.iNotifyPending=EFalse;
       
  1038 	iLine->ResetAutoAnswerCallObject(this);
       
  1039 	LOGVOICE1("<<CSimVoiceCall::ProcessAnswerIncomingCall");
       
  1040 	return ret;
       
  1041 	}
       
  1042 
       
  1043 TInt CSimVoiceCall::ProcessRemoteHangupL()
       
  1044 /**
       
  1045 * Hangs up a call remotely.
       
  1046 * First the call state must be changed to "disconnecting", then the flag indicating
       
  1047 * that a remote hangup request is no longer pending.  Finally, a new
       
  1048 * call object must be assigned to receive the next remote hangup request.
       
  1049 */
       
  1050 	{
       
  1051 	LOGVOICE3(">>CSimVoiceCall::ProcessRemoteHangupL %d",iState,this);
       
  1052 	TInt ret=ChangeStateL(RMobileCall::EStatusDisconnecting,EFalse,EFalse);
       
  1053 	if(ret!=KErrNone)
       
  1054 		return ret;
       
  1055 	iTimer->Start(iRemoteHangupPause,this);
       
  1056 	iLine->ResetRemoteHangupCallObject(this);
       
  1057 	LOGVOICE1("<<CSimVoiceCall::ProcessRemoteHangupL");
       
  1058 	return ret;
       
  1059 	}
       
  1060 
       
  1061 void CSimVoiceCall::SetDtmfSession(CSimDtmf* aSimDtmf)
       
  1062 /**
       
  1063  * Set the DTMF session pointer.
       
  1064  */
       
  1065 	{
       
  1066 	__ASSERT_ALWAYS(iState==RMobileCall::EStatusConnected,SimPanic(EIllegalDtmfReq));
       
  1067 	iSimDtmf=aSimDtmf;
       
  1068 	}
       
  1069 
       
  1070 CSimDtmf* CSimVoiceCall::GetDtmfSession()
       
  1071 /**
       
  1072  * Retrieve the DTMF session pointer.
       
  1073  */
       
  1074 	{
       
  1075 	return iSimDtmf;
       
  1076 	}
       
  1077 
       
  1078 
       
  1079 TUint CSimVoiceCall::Caps()
       
  1080 /**
       
  1081  * Return the current capabilities of this call.
       
  1082  * @return TUint	Current call capabilities.
       
  1083  */
       
  1084 	{
       
  1085 	TUint caps=RCall::KCapsVoice;
       
  1086 	if(iState!=RMobileCall::EStatusIdle)
       
  1087 		{
       
  1088 		if(iState==RMobileCall::EStatusConnected)
       
  1089 			{
       
  1090 			caps |= RCall::KCapsHangUp;
       
  1091 			// If there is only a single call and its state is connected then the hold capability 
       
  1092 			// should be set.
       
  1093 			// If there is more than one call then only the swap capability should be set as hold 
       
  1094 			// and resume apply only to single calls.
       
  1095 		
       
  1096 			TInt i=0;
       
  1097 			TBool singleCall = ETrue;
       
  1098 			TInt count=	iLine->iCalls->Count();
       
  1099 		
       
  1100 			while(singleCall && i<count)
       
  1101 				{
       
  1102  				if(iLine->iCalls->At(i) != this && (iLine->iCalls->At(i)->iState == RMobileCall::EStatusConnected || iLine->iCalls->At(i)->iState == RMobileCall::EStatusHold))
       
  1103 					singleCall = EFalse;
       
  1104 				i++;
       
  1105 				}	
       
  1106 			
       
  1107 			if (singleCall)
       
  1108 				caps |= RMobileCall::KCapsHold;
       
  1109 			// Swap capability is applicable to single and multiple call
       
  1110 			// scenarios
       
  1111 			caps |= RMobileCall::KCapsSwap;
       
  1112 			}
       
  1113 		else if(iState==RMobileCall::EStatusHold)
       
  1114 			{
       
  1115 			caps |= RCall::KCapsHangUp;
       
  1116 
       
  1117 			TBool otherConnected = EFalse;
       
  1118 			TInt count=	iLine->iCalls->Count();
       
  1119 			TInt i=0;
       
  1120 			while (!otherConnected && i<count)
       
  1121 				{
       
  1122  				if(iLine->iCalls->At(i) != this && (iLine->iCalls->At(i)->iState == RMobileCall::EStatusConnected || iLine->iCalls->At(i)->iState == RMobileCall::EStatusHold))
       
  1123 					otherConnected = ETrue;
       
  1124 				i++;
       
  1125 				}	
       
  1126 			if(otherConnected)
       
  1127 				{
       
  1128 				caps |= RMobileCall::KCapsSwap;
       
  1129 				}
       
  1130 			else
       
  1131 				{
       
  1132 				caps |= RMobileCall::KCapsResume;
       
  1133 				caps |= RMobileCall::KCapsSwap;
       
  1134 				}					
       
  1135 			}
       
  1136 		else if (iState==RMobileCall::EStatusRinging)
       
  1137 			{
       
  1138 			if((iLine->IsAnswerCallObjectSpare()))
       
  1139 				caps |= RCall::KCapsAnswer;	
       
  1140 			}
       
  1141 		}
       
  1142 	else
       
  1143 		{
       
  1144 		if(iLine->iState==RMobileCall::EStatusIdle || iLine->iState==RMobileCall::EStatusHold)
       
  1145 			{
       
  1146 			caps |= RCall::KCapsDial;
       
  1147 			if((iLine->IsAnswerCallObjectSpare()))
       
  1148 				caps |= RCall::KCapsAnswer;
       
  1149 			}
       
  1150 		else if (iLine->iState==RMobileCall::EStatusRinging)
       
  1151 			{
       
  1152 			if((iLine->IsAnswerCallObjectSpare()))
       
  1153 				caps |= RCall::KCapsAnswer;			
       
  1154 			}
       
  1155 		}
       
  1156 	return caps;
       
  1157 	}
       
  1158 
       
  1159 void CSimVoiceCall::UpdateRemotePartyInfoDirection(RMobileCall::TMobileCallStatus aPreviousStatus)
       
  1160 /**
       
  1161 Update the direction of the call for the remote party info member
       
  1162 */
       
  1163 	{
       
  1164 	if(iNotifyRemotePartyInfoTimer && iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteIdStatus != RMobileCall::ERemoteIdentityUnknown)	
       
  1165 		{
       
  1166 		if(aPreviousStatus == RMobileCall::EStatusAnswering)
       
  1167 			iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iDirection = RMobileCall::EMobileTerminated;
       
  1168 		else
       
  1169 			iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iDirection = RMobileCall::EMobileOriginated;
       
  1170 		}			
       
  1171 	}