telephonyserverplugins/simtsy/src/CSimCallForwarding.cpp
changeset 0 3553901f7fa8
child 15 fc69e1e37771
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 // Implements the functionality required to provide clients with
       
    15 // callforwarding status and registration information.
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file
       
    21 */
       
    22 
       
    23 #include <testconfigfileparser.h>
       
    24 #include "CSimCallForwarding.h"
       
    25 #include "CSimPhone.h"
       
    26 #include "Simlog.h"
       
    27 
       
    28 const TInt KSettingListGranularity=5;	// < The granularity used for parameter list arrays.
       
    29 const TInt KInvalidTimeout = -1;        // Value used when timeout period does not matter
       
    30 const TInt KMobServiceIndxStart = 1;
       
    31 const TInt KMobServiceIndxEnd   = 6;
       
    32 
       
    33 CSimCallForwarding* CSimCallForwarding::NewL(CSimPhone* aPhone)
       
    34 /**
       
    35  * Standard two-phase constructor.
       
    36  * @param aPhone				The parent phone object.
       
    37  * @return CSimNetworkStatus	The new network status class.
       
    38  */
       
    39 	{
       
    40 	CSimCallForwarding* self=new(ELeave) CSimCallForwarding(aPhone);
       
    41 	CleanupStack::PushL(self);
       
    42 	self->ConstructL();
       
    43 	CleanupStack::Pop();
       
    44 	return self;
       
    45 	}
       
    46 
       
    47 CSimCallForwarding::CSimCallForwarding(CSimPhone* aPhone)
       
    48 		: iPhone(aPhone)
       
    49 /**
       
    50  * Trivial first phase construction.
       
    51  * @param aPhone				The parent phone object.
       
    52  */
       
    53 	{
       
    54 	}
       
    55 
       
    56 void CSimCallForwarding::ConstructL()
       
    57 	/** 
       
    58 	Second phase of 2-Phase Constructor
       
    59  	Retrieves all the Call forwarding and Identity services tags from the config file
       
    60 	*/
       
    61 	{
       
    62 	LOGCALL1("Starting to parse Call Forwarding config parameters...");
       
    63 
       
    64 	iIdentityServiceStatus=new(ELeave) CArrayFixFlat<TIdentityServiceStatus>(KSettingListGranularity);
       
    65 	
       
    66 	iGetCFStatus = new(ELeave) CArrayPtrFlat<CListReadAllAttempt>(1);
       
    67 	FindAndCreateCFListL();
       
    68 	
       
    69 	// Read in the Identity services information
       
    70 	TInt count=CfgFile()->ItemCount(KIdentityServiceStatus);
       
    71 	const CTestConfigItem* item=NULL;
       
    72 	TInt ret=KErrNone;
       
    73 	for(TInt i=0;i<count;i++)
       
    74 		{
       
    75 		item=CfgFile()->Item(KIdentityServiceStatus,i);
       
    76 		if(!item)
       
    77 			break;
       
    78 
       
    79 		TInt status, service;
       
    80 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,service);
       
    81 		if(ret!=KErrNone)
       
    82 			{
       
    83 			LOGPARSERR("service",ret,0,&KIdentityServiceStatus);
       
    84 			continue;
       
    85 			}
       
    86 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,status);
       
    87 		if(ret!=KErrNone)
       
    88 			{
       
    89 			LOGPARSERR("status",ret,1,&KIdentityServiceStatus);
       
    90 			continue;
       
    91 			}
       
    92 			
       
    93 		TIdentityServiceStatus identityServiceStatus;
       
    94 		identityServiceStatus.iService = static_cast<RMobilePhone::TMobilePhoneIdService>(service);
       
    95 		identityServiceStatus.iStatus = static_cast<RMobilePhone::TMobilePhoneIdServiceStatus>(status);
       
    96 		iIdentityServiceStatus->AppendL(identityServiceStatus);
       
    97 		}
       
    98 		
       
    99 	LOGCALL1("...Finished parsing Call Forwarding config parameters...");
       
   100 	}
       
   101 
       
   102 CSimCallForwarding::~CSimCallForwarding()
       
   103 	/** 
       
   104 	Destroy all the objects constructed.
       
   105 	*/
       
   106 	{
       
   107 	if (iIdentityServiceStatus != NULL)
       
   108 		{
       
   109 		iIdentityServiceStatus->Delete(0,iIdentityServiceStatus->Count());
       
   110 		delete iIdentityServiceStatus;
       
   111 		}
       
   112 	delete iCFList;
       
   113 	if (iGetCFStatus)
       
   114 		iGetCFStatus->ResetAndDestroy();
       
   115 	delete iGetCFStatus;
       
   116 	}
       
   117 
       
   118 
       
   119 TInt CSimCallForwarding::ExtFunc(const TTsyReqHandle aReqHandle,const TInt aIpc, const TDataPackage& aPckg)
       
   120 	{
       
   121 	/**
       
   122 	Handles all the Call forwarding APIs
       
   123 	@param aReqHandle to the request
       
   124 	@param Ipc unique identifier of the method to call
       
   125 	@param aPckg contains arguments of the method to call
       
   126 	*/
       
   127 	TAny* dataPtr = aPckg.Ptr1();
       
   128 	TAny* dataPtr2 = aPckg.Ptr2();
       
   129 
       
   130 	// The following requests can be completed even if the completion of another request is pending.
       
   131 	switch(aIpc)
       
   132 		{
       
   133 	case EMobilePhoneSetCallForwardingStatus:
       
   134 		return SetCallForwardingStatus(aReqHandle,
       
   135 			reinterpret_cast<RMobilePhone::TMobilePhoneCFCondition*>(dataPtr),
       
   136 			reinterpret_cast<RMobilePhone::TMobilePhoneCFChangeV1*>(dataPtr2));
       
   137 	case EMobilePhoneNotifyCallForwardingStatusChange:
       
   138 		return NotifyCallForwardingStatusChange(aReqHandle, reinterpret_cast<RMobilePhone::TMobilePhoneCFCondition*>(dataPtr));
       
   139 	case EMobilePhoneGetIdentityServiceStatus:
       
   140 		return GetIdentityServiceStatus(aReqHandle, 
       
   141 			reinterpret_cast<RMobilePhone::TMobilePhoneIdService*>(dataPtr),
       
   142 			reinterpret_cast<RMobilePhone::TMobilePhoneIdServiceStatus*>(dataPtr2));
       
   143 	case EMobilePhoneGetCallForwardingStatusPhase1:
       
   144 		return GetCallForwardingStatusPhase1(aReqHandle, 
       
   145 			REINTERPRET_CAST(CRetrieveMobilePhoneCFList::TGetCallForwardingRequest*, dataPtr), 
       
   146 			REINTERPRET_CAST(TInt*, dataPtr2));
       
   147 	case EMobilePhoneGetCallForwardingStatusPhase2:
       
   148 		return GetCallForwardingStatusPhase2(aReqHandle, 
       
   149 			REINTERPRET_CAST(RMobilePhone::TClientId*, dataPtr), aPckg.Des2n());			
       
   150 	default:
       
   151 		break;
       
   152 		}
       
   153 	return KErrNotSupported;
       
   154 	}
       
   155 	
       
   156 TInt CSimCallForwarding::CancelService(const TInt aIpc, const TTsyReqHandle aReqHandle)
       
   157 	/**
       
   158 	Cancels Call forwarding requests
       
   159 	@param ipc request to cancel
       
   160 	@param aReqHandle Handle to the request
       
   161 	*/
       
   162 	{
       
   163 	switch(aIpc)
       
   164 		{
       
   165 	case EMobilePhoneSetCallForwardingStatus:
       
   166 		return SetCallForwardingStatusCancel(aReqHandle);
       
   167 	case EMobilePhoneNotifyCallForwardingStatusChange:
       
   168 		return NotifyCallForwardingStatusChangeCancel(aReqHandle);
       
   169 	case EMobilePhoneGetIdentityServiceStatus:
       
   170 		return GetIdentityServiceStatusCancel(aReqHandle);
       
   171 	default:
       
   172 		break;
       
   173 		}
       
   174 	return KErrNone;
       
   175 	}
       
   176 	
       
   177 void CSimCallForwarding::FindAndCreateCFListL()
       
   178 	{
       
   179 	/**
       
   180 	Creates the Call forwarding list from the config file
       
   181 	*/
       
   182 	LOGCALL1("CSimPhone::FindAndCreateCFListL");
       
   183 	RMobilePhone::TMobilePhoneCFInfoEntryV1 entry;
       
   184 
       
   185 	if(iCFList)
       
   186 		delete iCFList;
       
   187 	iCFList=NULL;
       
   188 
       
   189 	iCFList = CMobilePhoneCFList::NewL();
       
   190 	TInt count=CfgFile()->ItemCount(KCFList);
       
   191 	const CTestConfigItem* item=NULL;
       
   192 	TInt ret=KErrNone;
       
   193 
       
   194 	LOGCALL1("Starting to Load and Parse CFList Config parameters");
       
   195 	
       
   196 	TInt i;
       
   197 	for(i=0;i<count;i++)
       
   198 		{
       
   199 		item=CfgFile()->Item(KCFList,i);
       
   200 		if(!item)
       
   201 			break;
       
   202 		
       
   203 		TPtrC8 number;
       
   204 		TInt condition, serviceGroup, status, timeout; // valid for CFRNy only
       
   205 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,condition);
       
   206 		if(ret!=KErrNone)
       
   207 			{
       
   208 			LOGPARSERR("condition",ret,0,&KCFList);
       
   209 			continue;
       
   210 			}
       
   211 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,serviceGroup);
       
   212 		if(ret!=KErrNone)
       
   213 			{
       
   214 			LOGPARSERR("serviceGroup",ret,1,&KCFList);
       
   215 			continue;
       
   216 			}
       
   217 
       
   218 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,status);
       
   219 		if(ret!=KErrNone)
       
   220 			{
       
   221 			LOGPARSERR("status",ret,2,&KCFList);
       
   222 			continue;
       
   223 			}
       
   224 
       
   225 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,timeout);
       
   226 		if(ret!=KErrNone)
       
   227 			{
       
   228 			LOGPARSERR("timeout",ret,3,&KCFList);
       
   229 			continue;
       
   230 			}
       
   231 		
       
   232 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,4,number);
       
   233 		if(ret!=KErrNone)
       
   234 			{
       
   235 			LOGPARSERR("number",ret,4,&KCFList);
       
   236 			continue;
       
   237 			}
       
   238 		
       
   239 		entry.iServiceGroup=(RMobilePhone::TMobileService)serviceGroup;
       
   240 		entry.iNumber.iTelNumber.Copy(number);
       
   241 		entry.iTimeout=timeout;
       
   242 		entry.iCondition=(RMobilePhone::TMobilePhoneCFCondition)condition;
       
   243 		entry.iStatus=(RMobilePhone::TMobilePhoneCFStatus)status;
       
   244 		iCFList->AddEntryL(entry);
       
   245 		}//end for
       
   246 	
       
   247 	//CFlist must define entries for each condition even if unknown
       
   248 	//fill up table if it misses conditions:
       
   249 	
       
   250 	RArray<TBool> serviceArray;
       
   251 	//voice, auxVoice, data, packet, fax, sms, all;
       
   252 
       
   253 	CleanupClosePushL(serviceArray);
       
   254 
       
   255 	RMobilePhone::TMobilePhoneCFInfoEntryV1 extraEntry;
       
   256 
       
   257 	for (TInt j=1;j<5;j++)//loop conditions
       
   258 		{
       
   259 		TInt serviceFound=EFalse;
       
   260 		TInt index;
       
   261 		extraEntry.iCondition=static_cast<RMobilePhone::TMobilePhoneCFCondition>(j);
       
   262 		serviceArray.Reset();
       
   263 		for(TInt h=0;h<8;h++)
       
   264 			{
       
   265 			serviceArray.Append(EFalse);
       
   266 			}
       
   267 		
       
   268 		for (TInt k=0;k<count;k++)//loop entries
       
   269 			{
       
   270 			entry=iCFList->GetEntryL(k);
       
   271 			if(entry.iCondition==static_cast<RMobilePhone::TMobilePhoneCFCondition>(j))
       
   272 				{
       
   273 				index = (TInt)entry.iServiceGroup;
       
   274 				serviceArray[index]=ETrue;
       
   275 				}
       
   276 			}
       
   277 		
       
   278 		if (!serviceArray[7])//(all services)
       
   279 			{
       
   280 			for (TInt l=1;l<7;l++)
       
   281 				{
       
   282 				if (serviceArray[l])
       
   283 					serviceFound=ETrue;										
       
   284 				}
       
   285 			//no service defined for this condition
       
   286 			if(!serviceFound)
       
   287 				{
       
   288 				extraEntry.iServiceGroup=RMobilePhone::EAllServices;
       
   289 				extraEntry.iStatus=RMobilePhone::ECallForwardingStatusNotRegistered;
       
   290 				iCFList->AddEntryL(extraEntry);
       
   291 				}
       
   292 			//some services defined in table
       
   293 			else
       
   294 				{
       
   295 				for (TInt m=1;m<7;m++)
       
   296 					{
       
   297 					if (!serviceArray[m])
       
   298 						{
       
   299 						extraEntry.iServiceGroup=static_cast<RMobilePhone::TMobileService>(m);
       
   300 						extraEntry.iStatus=RMobilePhone::ECallForwardingStatusNotRegistered;
       
   301 						iCFList->AddEntryL(extraEntry);
       
   302 						}
       
   303 					}//end for
       
   304 				}//end else
       
   305 			}//end if
       
   306 		}//end for
       
   307 		
       
   308 	CleanupStack::PopAndDestroy(&serviceArray);	//Destroying serviceArray to free the memory
       
   309 	}
       
   310 
       
   311 TInt CSimCallForwarding::GetIdentityServiceStatus(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhoneIdService* aService, RMobilePhone::TMobilePhoneIdServiceStatus* aStatus)
       
   312 	/**
       
   313 	Gets the status of the identity services
       
   314 	@param aReqHandle handle to the request
       
   315 	@param aService service that the client is interested in
       
   316 	@param aStatus of the identity service
       
   317 	*/
       
   318 	{
       
   319 	RMobilePhone::TMobilePhoneIdServiceStatus status;
       
   320 	status = RMobilePhone::EIdServiceUnknown;
       
   321 	TInt count = iIdentityServiceStatus->Count();
       
   322 	for(TInt i=0; i<count; i++)
       
   323 		{
       
   324 		if(iIdentityServiceStatus->At(i).iService == *aService)
       
   325 			{
       
   326 			status = iIdentityServiceStatus->At(i).iStatus;
       
   327 			break;
       
   328 			}
       
   329 		}
       
   330 	*aStatus = status;
       
   331 	iPhone->ReqCompleted(aReqHandle, KErrNone);
       
   332 	return KErrNone;
       
   333 	}
       
   334 	
       
   335 TInt CSimCallForwarding::GetIdentityServiceStatusCancel(const TTsyReqHandle aReqHandle)
       
   336 	/**
       
   337 	Cancels the request to get the status of the identity services
       
   338 	@param aReqHandle hadle to the request
       
   339 	*/
       
   340 	{
       
   341 	iPhone->ReqCompleted(aReqHandle,KErrCancel);
       
   342 	return KErrNone;
       
   343 	}
       
   344 	
       
   345 TInt CSimCallForwarding::NotifyCallForwardingStatusChange(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhoneCFCondition* aCF)
       
   346 	/**
       
   347 	Requests to be notified of call forwarding status change
       
   348 	@param aReqHandle handle to the request
       
   349 	@param aCF condition for which the client wants to be notified
       
   350 	 */
       
   351 	{
       
   352 	__ASSERT_ALWAYS(!iCFNotification.iCFChangeInfoNotificationPending,SimPanic(ENotificationReqAlreadyOutstanding));
       
   353 
       
   354 	iCFNotification.iCFChangeInfoNotificationPending=ETrue;
       
   355 	iCFNotification.iCFChangeInfoReqHandle=aReqHandle;
       
   356 	iCFNotification.iCurrentCFCondition=aCF;
       
   357 	LOGCALL1("Finished CSimCallForwarding::NotifyCallForwardingStatusChange");
       
   358 	return KErrNone;
       
   359 	}
       
   360 	
       
   361 TInt CSimCallForwarding::NotifyCallForwardingStatusChangeCancel(const TTsyReqHandle aReqHandle)
       
   362 	/**
       
   363 	Cancels the request to be notified of call forwarding status change
       
   364 	@param aReqHandle handle to the request
       
   365 	*/
       
   366 	{
       
   367 	if(iCFNotification.iCFChangeInfoNotificationPending)
       
   368 		{
       
   369 		iCFNotification.iCFChangeInfoNotificationPending=EFalse;
       
   370 		iPhone->ReqCompleted(aReqHandle,KErrCancel);
       
   371 		}
       
   372 	return KErrNone;
       
   373 	}
       
   374 	
       
   375 TInt CSimCallForwarding::SetCallForwardingStatus(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhoneCFCondition* aCF,  RMobilePhone::TMobilePhoneCFChangeV1* aInfo)
       
   376 	/**
       
   377 	Sets the status of call forwarding
       
   378 	@param aReqHandle handle to the request
       
   379 	@param aCF condition for which the client wants to set the status
       
   380 	@param aInfo value of Call forwarding to set
       
   381 	*/
       
   382 	{
       
   383 	TRAPD(err, UpdateCFListL(aCF,aInfo));
       
   384 	if ( err != KErrNone )
       
   385 		{ 
       
   386 		iPhone->ReqCompleted(aReqHandle,err);
       
   387 		return KErrNone;
       
   388 		}
       
   389 		
       
   390 	if(iCFNotification.iCFChangeInfoNotificationPending)
       
   391 		{
       
   392 		*(iCFNotification.iCurrentCFCondition)=*aCF;
       
   393 		iCFNotification.iCFChangeInfoNotificationPending=EFalse;
       
   394 		iPhone->ReqCompleted(iCFNotification.iCFChangeInfoReqHandle,KErrNone);
       
   395 		}
       
   396 	
       
   397 	iPhone->ReqCompleted(aReqHandle,err);
       
   398 	LOGCALL1("Finished CSimCallForwarding::SetCallForwardingStatus");
       
   399 	return KErrNone;
       
   400 	}
       
   401 	
       
   402 TInt CSimCallForwarding::SetCallForwardingStatusCancel(const TTsyReqHandle aReqHandle)
       
   403 	/**
       
   404 	Cancels the request to set the status of call forwarding
       
   405 	@param aReqHandle handle to the request
       
   406 	*/
       
   407 	{
       
   408 	iPhone->ReqCompleted(aReqHandle,KErrCancel);
       
   409 	return KErrNone;
       
   410 	}
       
   411 	
       
   412 
       
   413 TInt CSimCallForwarding::GetCallForwardingStatusPhase1(const TTsyReqHandle aTsyReqHandle, 
       
   414 												 CRetrieveMobilePhoneCFList::TGetCallForwardingRequest* aReqData, 
       
   415 												 TInt* aBufSize)
       
   416 	{
       
   417 	/**
       
   418 	1st phase retrieval of the status of call forwarding
       
   419 	@param aTsyReqHandle handle to the request
       
   420 	@param aReqData contains details of the request
       
   421 	@param aBufSize size of the buffer the client needs to allocate for phase 2
       
   422 	*/
       
   423 	LOGCALL1("CSimPhone::GetCallForwardingStatusPhase1");
       
   424 	TInt ret=KErrNone;
       
   425 
       
   426     // for forwarding we cannot querry for all conditions;
       
   427     // conditions - specific
       
   428     // services  - individual and all
       
   429 	if ((aReqData->iCondition==RMobilePhone::ECallForwardingUnspecified)
       
   430 	   || (aReqData->iCondition==RMobilePhone::ECallForwardingAllCases)
       
   431 	   || (aReqData->iCondition==RMobilePhone::ECallForwardingAllConditionalCases))
       
   432 	   {
       
   433 			iPhone->ReqCompleted(aTsyReqHandle,KErrArgument);
       
   434 		}
       
   435 	else
       
   436 		{
       
   437 		TInt leaveCode=KErrNone;
       
   438 		TRAP(leaveCode, ret=ProcessGetCallForwardingStatusPhase1L(aTsyReqHandle, aReqData, aBufSize););
       
   439 		if (leaveCode != KErrNone)
       
   440 			iPhone->ReqCompleted(aTsyReqHandle,leaveCode);
       
   441 		}
       
   442 	LOGCALL1("CSimPhone::GetCallForwardingStatusPhase1");
       
   443 	return ret;
       
   444 	}
       
   445 	
       
   446 TInt CSimCallForwarding::ProcessGetCallForwardingStatusPhase1L(const TTsyReqHandle aTsyReqHandle, 
       
   447 														 CRetrieveMobilePhoneCFList::TGetCallForwardingRequest* aReqData, 
       
   448 														 TInt* aBufSize)
       
   449 	{
       
   450 	/** Retrieve call forwarding status of each line from phone, 
       
   451 	store each CF status response as a list entry,
       
   452 	stream the list and then return size of this buffer to client
       
   453 	@param aReqHandle Handle to the request
       
   454 	@param aReqData information about the request
       
   455 	@param aBufSize Size of the buffer the client has to allocate for the 2nd pahase
       
   456 	*/
       
   457 
       
   458 	LOGCALL1("CSimPhone::ProcessGetCallForwardingStatusPhase1L");
       
   459 
       
   460 	CMobilePhoneCFList* list=CMobilePhoneCFList::NewL();
       
   461 	CleanupStack::PushL(list);
       
   462 	
       
   463 	TInt cnt=0;//Only interested by entries with a particular condition
       
   464 	TInt maxNum=iCFList->Enumerate();
       
   465 	TBool isAllGroups = (aReqData->iServiceGroup == RMobilePhone::EAllServices);
       
   466 	for(TInt i=0;i<maxNum;i++)
       
   467 		{
       
   468 		RMobilePhone::TMobilePhoneCFInfoEntryV1 entry = iCFList->GetEntryL(i);
       
   469 		
       
   470 		// Check that the data structure is supported by the simulated TSY version
       
   471 		TInt err = iPhone->CheckSimTsyVersion(entry);
       
   472 		if(err != KErrNone)
       
   473 			{
       
   474 			iPhone->ReqCompleted(aTsyReqHandle, err);
       
   475 			return KErrNone;
       
   476 			}
       
   477 
       
   478 		if((entry.iCondition == aReqData->iCondition) 
       
   479 		   &&(entry.iStatus != RMobilePhone::ECallForwardingStatusNotRegistered))
       
   480 			{
       
   481 			if ( !isAllGroups && (entry.iServiceGroup != aReqData->iServiceGroup))
       
   482 				{
       
   483 				continue;
       
   484 				}
       
   485 			list->AddEntryL(entry);
       
   486 			cnt++;
       
   487 			}	
       
   488 		}
       
   489 	// Store the streamed list and the client ID
       
   490 	CListReadAllAttempt* read=CListReadAllAttempt::NewL(aReqData->iClient,aTsyReqHandle);
       
   491 	CleanupStack::PushL(read);
       
   492 	
       
   493 	read->iListBuf = list->StoreLC();
       
   494 	CleanupStack::Pop(); // pop the CBufBase allocated by StoreLC
       
   495 	
       
   496 	iGetCFStatus->AppendL(read);
       
   497 	CleanupStack::Pop(read); // pop the CListReadAllAttempt
       
   498 	
       
   499 	// return the CBufBase’s size to client
       
   500 	*aBufSize=(read->iListBuf)->Size();
       
   501 	
       
   502 	CleanupStack::PopAndDestroy(list); // pop&destroy list
       
   503 	
       
   504 	// Complete first phase of list retrieval
       
   505 	iPhone->ReqCompleted(aTsyReqHandle,KErrNone);
       
   506 	LOGCALL1("CSimPhone::ProcessGetCallForwardingStatusPhase1L");
       
   507 	return KErrNone;	
       
   508 	}
       
   509 
       
   510 TInt CSimCallForwarding::GetCallForwardingStatusPhase2(const TTsyReqHandle aTsyReqHandle, 
       
   511 												 RMobilePhone::TClientId* aClient, TDes8* aBuf)
       
   512 	/**
       
   513 	2nd phase retrieval of the status of call forwarding
       
   514 	@param aTsyRqHandle handle to the request
       
   515 	@param aClient pointer to the client
       
   516 	@param aBuf buffer that contains the call forwarding list
       
   517 	*/
       
   518 	{
       
   519 	LOGCALL1("CSimPhone::GetCallForwardingStatusPhase2");
       
   520 	CListReadAllAttempt* read=NULL;
       
   521 	// Find the get detected network attempt from this client
       
   522 	for (TInt i=0; i<iGetCFStatus->Count(); ++i)
       
   523 		{
       
   524 		read = iGetCFStatus->At(i);
       
   525 		if ((read->iClient.iSessionHandle==aClient->iSessionHandle) &&
       
   526 		    (read->iClient.iSubSessionHandle==aClient->iSubSessionHandle))
       
   527 			{
       
   528 			TPtr8 bufPtr((read->iListBuf)->Ptr(0));
       
   529 			// Copy the streamed list to the client
       
   530 			aBuf->Copy(bufPtr);
       
   531 			delete read;
       
   532 			iGetCFStatus->Delete(i);
       
   533 			iPhone->ReqCompleted(aTsyReqHandle,KErrNone);
       
   534 			return KErrNone;
       
   535 			}
       
   536 		}
       
   537 	// Should handle error case of not finding the matching client from read all phase 1
       
   538 	LOGCALL1("CSimPhone::GetCallForwardingStatusPhase2");
       
   539 	return KErrNotFound;
       
   540 	}
       
   541 
       
   542 
       
   543 TInt CSimCallForwarding::GetCallForwardingStatusCancel(const TTsyReqHandle aTsyReqHandle)
       
   544 	{
       
   545 	/**
       
   546 	Cancel the request to retrieve the status of call forwarding
       
   547 	@param aTsyReqHandle handle to the request
       
   548 	*/
       
   549 	LOGCALL1("CSimPhone::GetCallForwardingStatusCancel");
       
   550 	iPhone->ReqCompleted(aTsyReqHandle,KErrNone);
       
   551 	// Remove the read all attempt from iGetCFStatus
       
   552 	CListReadAllAttempt* read=NULL;
       
   553 	for (TInt i=0; i<iGetCFStatus->Count(); ++i)
       
   554 		{
       
   555 		read = iGetCFStatus->At(i);
       
   556 		if (read->iReqHandle == aTsyReqHandle)
       
   557 			{
       
   558 			delete read;
       
   559 			iGetCFStatus->Delete(i);
       
   560 			break;
       
   561 			}
       
   562 		}
       
   563 	iPhone->ReqCompleted(aTsyReqHandle,KErrCancel);
       
   564 	LOGCALL1("CSimPhone::GetCallForwardingStatusCancel");
       
   565 	return KErrNone;
       
   566 	}
       
   567 
       
   568 void CSimCallForwarding::UpdateCFListL(RMobilePhone::TMobilePhoneCFCondition* aCF, 
       
   569 									   RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo )
       
   570 	{		
       
   571 	/**
       
   572 	Modifies the status of call forwarding
       
   573 	@param aCF condition
       
   574 	@param aCFInfo details of the request
       
   575 	*/
       
   576 	User::LeaveIfNull(aCF);
       
   577 	User::LeaveIfNull(aCFInfo);
       
   578 
       
   579 	if (*aCF == RMobilePhone::ECallForwardingUnspecified)
       
   580 	    {
       
   581 	    // not supported - tell user it is a wrong argument 
       
   582 		User::Leave(KErrArgument);
       
   583 	    }
       
   584 	     
       
   585 	if ((*aCF == RMobilePhone::ECallForwardingAllCases)
       
   586 		||(*aCF == RMobilePhone::ECallForwardingAllConditionalCases)) 
       
   587 	    {
       
   588 	    // not supported - tell user it is a wrong argument 
       
   589 		User::Leave(KErrNotSupported);
       
   590 	    }  
       
   591 	       
       
   592 	switch (aCFInfo->iAction)
       
   593 		{
       
   594 		case RMobilePhone::EServiceActionRegister:
       
   595 			RegisterL(aCF, aCFInfo);
       
   596 			break;
       
   597 			
       
   598 		case RMobilePhone::EServiceActionActivate:
       
   599 			ActivateL(aCF, aCFInfo);
       
   600 			break;
       
   601 			
       
   602 		case RMobilePhone::EServiceActionInvoke:
       
   603 		    // currently not supported
       
   604 		    // tell user it is a wrong argument 
       
   605 			User::Leave(KErrArgument);
       
   606 			break;
       
   607 			
       
   608 		case RMobilePhone::EServiceActionDeactivate:
       
   609 			DeactivateL(aCF, aCFInfo);
       
   610 			break;
       
   611 			
       
   612 		case RMobilePhone::EServiceActionErase:
       
   613 			EraseL(aCF, aCFInfo);
       
   614 			break;
       
   615 			
       
   616 		case RMobilePhone::EServiceActionUnspecified:
       
   617 		default:
       
   618 		    // not supported - tell user it is a wrong argument 
       
   619 			User::Leave(KErrArgument);
       
   620 			break;
       
   621 		}
       
   622 	}
       
   623 	
       
   624 
       
   625 inline void SplitOneCFEntryIntoSeparateGroupsL(CMobilePhoneCFList* aCFList,
       
   626 											   RMobilePhone::TMobilePhoneCFInfoEntryV1& aOrigEntry,
       
   627 											   RMobilePhone::TMobileService aExceptServiceGroup)
       
   628 	{
       
   629 	/*
       
   630 	Splits one entry valid for all basic service groups into individual entries 
       
   631 	and places them into a CMobilePhoneCFList. This excludes one service group.	 
       
   632 	@param aCBList The list to which to store the entries
       
   633 	@param aOrigEntry The original entry; details of which should be passed to individual group entries
       
   634 	@param aExceptServiceGroup The group which has to be avoided
       
   635 	*/
       
   636 	// we have to split the entry into entries 
       
   637 	// per group with the same condition; excluding the specified service group 
       
   638 	RMobilePhone::TMobilePhoneCFInfoEntryV1 anotherEntry(aOrigEntry);
       
   639 
       
   640 	RMobilePhone::TMobileService service;
       
   641 	
       
   642 	for (TInt i = KMobServiceIndxStart;i <= KMobServiceIndxEnd;i++)
       
   643 		{
       
   644 		service=static_cast<RMobilePhone::TMobileService>(i);
       
   645 		
       
   646 		if( service != aExceptServiceGroup )
       
   647 			{
       
   648 			anotherEntry.iServiceGroup=service;
       
   649 			aCFList->AddEntryL(anotherEntry);
       
   650 			}
       
   651 		}//end for (another)
       
   652 	}
       
   653 	
       
   654 	
       
   655 void CSimCallForwarding::UpdateCFQuiescentCondition(TBool aActivate, 
       
   656 													RMobilePhone::TMobilePhoneCFCondition aCF)
       
   657 	{
       
   658 	// only the Call Forward Unconditional can alter any other CF condition
       
   659 	if(aCF == RMobilePhone::ECallForwardingUnconditional)
       
   660 		{		
       
   661 		TBool cFBChangeRequired = EFalse;
       
   662 		
       
   663 		RMobilePhone::TMobilePhoneCFInfoEntryV1 theEntry;
       
   664 		
       
   665 		const TInt count = iCFList->Enumerate();
       
   666 
       
   667 		// look for any instances of the ECallForwardingBusy
       
   668 		for (TInt indx=0; indx < count; indx++)
       
   669 			{ 
       
   670 			theEntry = iCFList->GetEntryL(indx);
       
   671 			
       
   672 			if(theEntry.iCondition == RMobilePhone::ECallForwardingBusy &&
       
   673 			  (theEntry.iStatus == RMobilePhone::ECallForwardingStatusActive || 
       
   674 			   theEntry.iStatus == RMobilePhone::ECallForwardingStatusQuiescent)) 
       
   675 				{
       
   676 				cFBChangeRequired = ETrue;
       
   677 				}												
       
   678 			}
       
   679 		
       
   680 		if(cFBChangeRequired)
       
   681 			{
       
   682 			// retain prev version of the list in local variable and in Cleanup stack
       
   683 			CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL();
       
   684 			CleanupStack::PushL(thePrevCFList);
       
   685 	
       
   686 			// copy existing data into the temp storage
       
   687 			for (TInt indx=0; indx < count; indx++)
       
   688 				{ 
       
   689 				thePrevCFList->AddEntryL(iCFList->GetEntryL(indx));
       
   690 				}
       
   691 
       
   692 			delete iCFList;
       
   693 			iCFList = NULL;
       
   694 	
       
   695 			// create a new version and hold it in the class member
       
   696 			iCFList = CMobilePhoneCFList::NewL();
       
   697 	
       
   698 			// get a hold of it in a local variable       
       
   699 			CMobilePhoneCFList* theNewCFList = iCFList;
       
   700 			
       
   701 			for(TInt indx=0; indx < count; indx++)
       
   702 				{
       
   703 				theEntry = thePrevCFList->GetEntryL(indx);
       
   704 			
       
   705 				if(theEntry.iCondition == RMobilePhone::ECallForwardingBusy)
       
   706 					{
       
   707 					if(aActivate)
       
   708 						{
       
   709 						if(theEntry.iStatus == RMobilePhone::ECallForwardingStatusActive)
       
   710 							{
       
   711 							theEntry.iStatus = RMobilePhone::ECallForwardingStatusQuiescent;
       
   712 							}
       
   713 						}
       
   714 					else
       
   715 						{
       
   716 						if(theEntry.iStatus == RMobilePhone::ECallForwardingStatusQuiescent)
       
   717 							{
       
   718 							theEntry.iStatus = RMobilePhone::ECallForwardingStatusActive;
       
   719 							}
       
   720 						}					
       
   721 					}			
       
   722 				theNewCFList->AddEntryL(theEntry);
       
   723 				}					
       
   724 			
       
   725 			// now delete the old memory
       
   726 			CleanupStack::PopAndDestroy(thePrevCFList);
       
   727 			}						
       
   728 		}
       
   729 	}	
       
   730 
       
   731 void CSimCallForwarding::ActivateL(RMobilePhone::TMobilePhoneCFCondition* aCF, 
       
   732 								   RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo )
       
   733 	{
       
   734 	// NOTE: An assumption is made that the calling method has checked the parameters
       
   735 	// are not NULL.
       
   736 	RMobilePhone::TMobilePhoneCFInfoEntryV1 theNewEntry;
       
   737 
       
   738 	theNewEntry.iCondition = *aCF;
       
   739 	theNewEntry.iServiceGroup = aCFInfo->iServiceGroup;
       
   740 	theNewEntry.iStatus= RMobilePhone::ECallForwardingStatusNotActive;
       
   741 	theNewEntry.iNumber = aCFInfo->iNumber;
       
   742 	
       
   743 	if (*aCF ==  RMobilePhone::ECallForwardingNoReply)
       
   744 		{	
       
   745 		theNewEntry.iTimeout = aCFInfo->iTimeout;
       
   746 		}
       
   747 	else
       
   748 		{
       
   749 		theNewEntry.iTimeout = KInvalidTimeout;
       
   750 		} 
       
   751 
       
   752 
       
   753 	// retain prev version of the list in local variable and in Cleanup stack
       
   754 	CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL();
       
   755 	CleanupStack::PushL(thePrevCFList);
       
   756 	
       
   757 	const TInt count = iCFList->Enumerate();
       
   758 	
       
   759 	TBool CFUActive = EFalse;
       
   760 	
       
   761 	// copy existing data into the temp storage
       
   762 	for (TInt indx = 0; indx < count; indx++)
       
   763 		{ 	
       
   764 		thePrevCFList->AddEntryL(iCFList->GetEntryL(indx));
       
   765 		
       
   766 		RMobilePhone::TMobilePhoneCFInfoEntryV1 copyEntry = iCFList->GetEntryL(indx);
       
   767 
       
   768 		if(copyEntry.iCondition == RMobilePhone::ECallForwardingUnconditional &&
       
   769 		   copyEntry.iStatus == RMobilePhone::ECallForwardingStatusActive)
       
   770 			{
       
   771 			CFUActive = ETrue;
       
   772 			}
       
   773 		}
       
   774 	
       
   775 	delete iCFList;
       
   776 	iCFList = NULL;
       
   777 	
       
   778 	// create a new version and hold it in the class member
       
   779 	iCFList = CMobilePhoneCFList::NewL();
       
   780 	
       
   781 	// get a hold of it in a local variable 
       
   782 	CMobilePhoneCFList* theNewCFList = iCFList;
       
   783 	
       
   784 	TBool callForwardActivated = EFalse;
       
   785 		
       
   786 	RMobilePhone::TMobilePhoneCFInfoEntryV1 entry;
       
   787 	
       
   788 	for (TInt i = 0; i < count; i++)
       
   789 		{
       
   790 		entry = thePrevCFList->GetEntryL(i);
       
   791 					
       
   792 		if(theNewEntry.iCondition == entry.iCondition)
       
   793 			{			
       
   794 			if(theNewEntry.iServiceGroup == entry.iServiceGroup)
       
   795 				{
       
   796 				// only activate service if previously in a not active state
       
   797 				if(entry.iStatus == RMobilePhone::ECallForwardingStatusNotActive)
       
   798 					{
       
   799 					if(entry.iCondition == RMobilePhone::ECallForwardingBusy && CFUActive != EFalse)
       
   800 						{
       
   801 						// do nothing, condition's service will not be activated as callforwarding
       
   802 						// unconditional is active	
       
   803 						}
       
   804 					else
       
   805 						{
       
   806 						entry.iStatus = RMobilePhone::ECallForwardingStatusActive;
       
   807 						callForwardActivated = ETrue;									
       
   808 						}
       
   809 					}					
       
   810 				}
       
   811 			else if(entry.iServiceGroup == RMobilePhone::EAllServices)
       
   812 				{
       
   813 				if(entry.iStatus == RMobilePhone::ECallForwardingStatusNotActive)
       
   814 					{
       
   815 					SplitOneCFEntryIntoSeparateGroupsL(theNewCFList,
       
   816 													   entry,
       
   817 													   theNewEntry.iServiceGroup);
       
   818 					
       
   819 					callForwardActivated = ETrue;
       
   820 					entry = theNewEntry;
       
   821 					}				
       
   822 				}					
       
   823 			}		
       
   824 
       
   825 		theNewCFList->AddEntryL(entry);				
       
   826 		}
       
   827 	
       
   828 	if(callForwardActivated)
       
   829 		{
       
   830 		// only need to check quiescent status if an activation has occurred
       
   831 		UpdateCFQuiescentCondition(ETrue, theNewEntry.iCondition);	
       
   832 		}
       
   833 
       
   834 	CleanupStack::PopAndDestroy(thePrevCFList);
       
   835 	}
       
   836 
       
   837 void CSimCallForwarding::RegisterL(RMobilePhone::TMobilePhoneCFCondition* aCF, RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo)
       
   838 	{
       
   839 	TInt count = iCFList->Enumerate();
       
   840 	RMobilePhone::TMobilePhoneCFInfoEntryV1 theNewEntry;
       
   841 
       
   842 	theNewEntry.iCondition = *aCF;
       
   843 	theNewEntry.iServiceGroup = aCFInfo->iServiceGroup;
       
   844 	theNewEntry.iStatus= RMobilePhone::ECallForwardingStatusNotActive;
       
   845 
       
   846 	theNewEntry.iNumber = aCFInfo->iNumber;
       
   847 	if (*aCF ==  RMobilePhone::ECallForwardingNoReply)
       
   848 		{	
       
   849 		theNewEntry.iTimeout = aCFInfo->iTimeout;
       
   850 		}
       
   851 	else
       
   852 		{
       
   853 		 theNewEntry.iTimeout = KInvalidTimeout;
       
   854 		} 
       
   855 
       
   856 	// retain prev version of the list in local variable and in Cleanup stack
       
   857 	CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL();
       
   858 	CleanupStack::PushL(thePrevCFList);
       
   859 	// copy existing data into the temp storage
       
   860 	for (TInt indx=0; indx<count; indx++)
       
   861 		{ 
       
   862 		thePrevCFList->AddEntryL(iCFList->GetEntryL(indx));
       
   863 		}
       
   864 	delete iCFList;
       
   865 	iCFList = NULL;
       
   866 	// create a new version and hold it in the class member
       
   867 	iCFList = CMobilePhoneCFList::NewL();
       
   868 	// get a hold of it in a local variable       
       
   869 	CMobilePhoneCFList* theNewCFList = iCFList;
       
   870 		
       
   871 	if (theNewEntry.iServiceGroup==RMobilePhone::EAllServices)
       
   872 		{
       
   873 		//nothing for all conds
       
   874 		
       
   875 		//action is to Regiser (and activate)AllServices with a particular condition;
       
   876 		//Only copy entries with a different condition
       
   877 		//entries with same condition should not be copied as they will
       
   878 		//be represented by 1 with allservices
       
   879 		for (TInt i = 0; i<count; i++)
       
   880 			{
       
   881 			RMobilePhone::TMobilePhoneCFInfoEntryV1 entry = thePrevCFList->GetEntryL(i);
       
   882 
       
   883 			if (entry.iCondition != theNewEntry.iCondition)
       
   884 				// check if the existing entry is encompassed by the new one
       
   885 				theNewCFList->AddEntryL(entry);
       
   886 			}
       
   887 		theNewCFList->AddEntryL(theNewEntry);			
       
   888 		}
       
   889 	else
       
   890 		{
       
   891 		//ActivateOne;
       
   892 		for (TInt i = 0; i<count; i++)
       
   893 			{
       
   894 			RMobilePhone::TMobilePhoneCFInfoEntryV1 entry = thePrevCFList->GetEntryL(i);
       
   895 
       
   896 			if (theNewEntry.iCondition==entry.iCondition
       
   897 				&&  entry.iServiceGroup==theNewEntry.iServiceGroup)
       
   898 				{
       
   899 				theNewCFList->AddEntryL(theNewEntry);
       
   900 				continue;
       
   901 				}
       
   902 			if (entry.iCondition != theNewEntry.iCondition
       
   903 				|| (entry.iCondition == theNewEntry.iCondition
       
   904 				&& entry.iServiceGroup != theNewEntry.iServiceGroup
       
   905 				&& entry.iServiceGroup != RMobilePhone::EAllServices))
       
   906 				{
       
   907 				theNewCFList->AddEntryL(entry);	
       
   908 				continue;
       
   909 				}
       
   910 				
       
   911 			if(theNewEntry.iCondition==entry.iCondition
       
   912 				&&  entry.iServiceGroup==RMobilePhone::EAllServices)
       
   913 				{
       
   914 					
       
   915 				SplitOneCFEntryIntoSeparateGroupsL( 
       
   916 											theNewCFList,
       
   917 											entry,
       
   918 											theNewEntry.iServiceGroup
       
   919 											);
       
   920 					
       
   921 				theNewCFList->AddEntryL(theNewEntry);
       
   922 				}//end if
       
   923 			}//end for
       
   924 		}//end else
       
   925 	// now delete the old memory
       
   926 	CleanupStack::PopAndDestroy(thePrevCFList);
       
   927 	}
       
   928 
       
   929 void CSimCallForwarding::DeactivateL(RMobilePhone::TMobilePhoneCFCondition* aCF, 
       
   930 									 RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo )
       
   931 	{
       
   932 	// NOTE: An assumption is made that the calling method has checked the parameters
       
   933 	// are not NULL.
       
   934 		
       
   935 	RMobilePhone::TMobilePhoneCFInfoEntryV1 theNewEntry;
       
   936 
       
   937 	theNewEntry.iCondition = *aCF;
       
   938 	theNewEntry.iServiceGroup = aCFInfo->iServiceGroup;
       
   939 	theNewEntry.iStatus= RMobilePhone::ECallForwardingStatusNotActive;
       
   940 		
       
   941 	// retain prev version of the list in local variable and in Cleanup stack
       
   942 	CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL();
       
   943 	CleanupStack::PushL(thePrevCFList);
       
   944 		
       
   945 	const TInt count = iCFList->Enumerate();
       
   946 
       
   947 	// copy existing data into the temp storage
       
   948 	for (TInt indx = 0; indx < count; indx++)
       
   949 		{ 
       
   950 		thePrevCFList->AddEntryL(iCFList->GetEntryL(indx));
       
   951 		}
       
   952 	
       
   953 	delete iCFList;
       
   954 	iCFList = NULL;
       
   955 	
       
   956 	// create a new version and hold it in the class member
       
   957 	iCFList = CMobilePhoneCFList::NewL();
       
   958 	
       
   959 	// get a hold of it in a local variable       
       
   960 	CMobilePhoneCFList* theNewCFList = iCFList;
       
   961 		
       
   962 	TBool callForwardDeactivated = EFalse;
       
   963 			
       
   964 	RMobilePhone::TMobilePhoneCFInfoEntryV1 entry;
       
   965 
       
   966 	//Deactivate will deactivate active entries 
       
   967 	for (TInt indx = 0; indx < count; indx++)
       
   968 		{
       
   969 		entry = thePrevCFList->GetEntryL(indx);
       
   970 				
       
   971 		if(entry.iCondition == theNewEntry.iCondition)
       
   972 			{
       
   973 			if(entry.iServiceGroup == theNewEntry.iServiceGroup)
       
   974 				{
       
   975 				if(entry.iStatus == RMobilePhone::ECallForwardingStatusActive)
       
   976 					{
       
   977 				   	entry.iStatus = RMobilePhone::ECallForwardingStatusNotActive;
       
   978 					callForwardDeactivated = ETrue;
       
   979 					}								
       
   980 				}
       
   981 			else if(entry.iServiceGroup == RMobilePhone::EAllServices)
       
   982 				{
       
   983 				if(entry.iStatus == RMobilePhone::ECallForwardingStatusActive)
       
   984 					{
       
   985 					SplitOneCFEntryIntoSeparateGroupsL(theNewCFList,
       
   986 													   entry,
       
   987 													   theNewEntry.iServiceGroup);
       
   988 										
       
   989 					entry = theNewEntry;
       
   990 					callForwardDeactivated = ETrue;					
       
   991 					}			
       
   992 				}			
       
   993 			}	
       
   994 		
       
   995 		theNewCFList->AddEntryL(entry);
       
   996 		}//end for
       
   997 		
       
   998 	// this method will check if any de-activation has caused another Condition to become 
       
   999 	// cleared of the quiescent state
       
  1000 	if(callForwardDeactivated)
       
  1001 		{		
       
  1002 		// pass a FALSE to the function to notify of a service de-activation
       
  1003 		UpdateCFQuiescentCondition(EFalse, theNewEntry.iCondition);
       
  1004 		}
       
  1005 
       
  1006 	// now delete the old memory	
       
  1007 	CleanupStack::PopAndDestroy(thePrevCFList);
       
  1008 	}
       
  1009 
       
  1010 void CSimCallForwarding::EraseL(RMobilePhone::TMobilePhoneCFCondition* aCF, 
       
  1011 								RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo )
       
  1012 	{
       
  1013 	// NOTE: An assumption is made that the calling method has checked the parameters
       
  1014 	// are not NULL.
       
  1015 	
       
  1016 	RMobilePhone::TMobilePhoneCFInfoEntryV1 theNewEntry;
       
  1017 
       
  1018 	theNewEntry.iCondition = *aCF;
       
  1019 	theNewEntry.iServiceGroup = aCFInfo->iServiceGroup;
       
  1020 	theNewEntry.iNumber.iTelNumber.Copy(KEmptyString);
       
  1021 	theNewEntry.iTimeout = KErrNotFound;
       
  1022 	theNewEntry.iStatus = RMobilePhone::ECallForwardingStatusNotRegistered;
       
  1023 	
       
  1024 	// retain prev version of the list in local variable and in Cleanup stack
       
  1025 	CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL();
       
  1026 	CleanupStack::PushL(thePrevCFList);
       
  1027 	
       
  1028 	const TInt count = iCFList->Enumerate();
       
  1029 
       
  1030 	// copy existing data into the temp storage
       
  1031 	for (TInt indx = 0; indx < count; indx++)
       
  1032 		{ 
       
  1033 		thePrevCFList->AddEntryL(iCFList->GetEntryL(indx));
       
  1034 		}
       
  1035 	
       
  1036 	delete iCFList;
       
  1037 	iCFList = NULL;
       
  1038 	
       
  1039 	// create a new version and hold it in the class member
       
  1040 	iCFList = CMobilePhoneCFList::NewL();
       
  1041 	
       
  1042 	// get a hold of it in a local variable       
       
  1043 	CMobilePhoneCFList* theNewCFList = iCFList;
       
  1044 	
       
  1045 	RMobilePhone::TMobilePhoneCFInfoEntryV1 entry;	
       
  1046 	
       
  1047 	for(TInt i = 0; i < count; i++)
       
  1048 		{
       
  1049 		entry = thePrevCFList->GetEntryL(i);
       
  1050 		
       
  1051 		if(entry.iCondition == theNewEntry.iCondition)
       
  1052 			{
       
  1053 			if(entry.iServiceGroup == theNewEntry.iServiceGroup)
       
  1054 				{
       
  1055 				if(entry.iStatus == RMobilePhone::ECallForwardingStatusNotActive)
       
  1056 					{
       
  1057 				   	entry = theNewEntry;
       
  1058 					}								
       
  1059 				}
       
  1060 			else if(entry.iServiceGroup == RMobilePhone::EAllServices)
       
  1061 				{
       
  1062 				if(entry.iStatus == RMobilePhone::ECallForwardingStatusActive)
       
  1063 					{
       
  1064 					SplitOneCFEntryIntoSeparateGroupsL(theNewCFList,
       
  1065 													   entry,
       
  1066 													   theNewEntry.iServiceGroup);
       
  1067 										
       
  1068 					entry = theNewEntry;
       
  1069 					}			
       
  1070 				}
       
  1071 			}
       
  1072 		theNewCFList->AddEntryL(entry);		
       
  1073 		}
       
  1074 
       
  1075 	// now delete the old memory
       
  1076 	CleanupStack::PopAndDestroy(thePrevCFList);	
       
  1077 	}
       
  1078 	
       
  1079 const CTestConfigSection* CSimCallForwarding::CfgFile()
       
  1080 /**
       
  1081  * Returns a pointer to the current configuration file section.
       
  1082  *
       
  1083  * @return CTestConfigSection	A pointer to the current configuration file data section.
       
  1084  */
       
  1085 	{
       
  1086 	return iPhone->CfgFile();
       
  1087 	}
       
  1088 
       
  1089