--- a/telephonyserverplugins/simtsy/src/CSimCallForwarding.cpp Mon May 03 13:37:20 2010 +0300
+++ b/telephonyserverplugins/simtsy/src/CSimCallForwarding.cpp Thu May 06 15:10:38 2010 +0100
@@ -1,1089 +1,1089 @@
-// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
-// All rights reserved.
-// This component and the accompanying materials are made available
-// under the terms of "Eclipse Public License v1.0"
-// which accompanies this distribution, and is available
-// at the URL "http://www.eclipse.org/legal/epl-v10.html".
-//
-// Initial Contributors:
-// Nokia Corporation - initial contribution.
-//
-// Contributors:
-//
-// Description:
-// Implements the functionality required to provide clients with
-// callforwarding status and registration information.
-//
-//
-
-/**
- @file
-*/
-
-#include <testconfigfileparser.h>
-#include "CSimCallForwarding.h"
-#include "CSimPhone.h"
-#include "Simlog.h"
-
-const TInt KSettingListGranularity=5; // < The granularity used for parameter list arrays.
-const TInt KInvalidTimeout = -1; // Value used when timeout period does not matter
-const TInt KMobServiceIndxStart = 1;
-const TInt KMobServiceIndxEnd = 6;
-
-CSimCallForwarding* CSimCallForwarding::NewL(CSimPhone* aPhone)
-/**
- * Standard two-phase constructor.
- * @param aPhone The parent phone object.
- * @return CSimNetworkStatus The new network status class.
- */
- {
- CSimCallForwarding* self=new(ELeave) CSimCallForwarding(aPhone);
- CleanupStack::PushL(self);
- self->ConstructL();
- CleanupStack::Pop();
- return self;
- }
-
-CSimCallForwarding::CSimCallForwarding(CSimPhone* aPhone)
- : iPhone(aPhone)
-/**
- * Trivial first phase construction.
- * @param aPhone The parent phone object.
- */
- {
- }
-
-void CSimCallForwarding::ConstructL()
- /**
- Second phase of 2-Phase Constructor
- Retrieves all the Call forwarding and Identity services tags from the config file
- */
- {
- LOGCALL1("Starting to parse Call Forwarding config parameters...");
-
- iIdentityServiceStatus=new(ELeave) CArrayFixFlat<TIdentityServiceStatus>(KSettingListGranularity);
-
- iGetCFStatus = new(ELeave) CArrayPtrFlat<CListReadAllAttempt>(1);
- FindAndCreateCFListL();
-
- // Read in the Identity services information
- TInt count=CfgFile()->ItemCount(KIdentityServiceStatus);
- const CTestConfigItem* item=NULL;
- TInt ret=KErrNone;
- for(TInt i=0;i<count;i++)
- {
- item=CfgFile()->Item(KIdentityServiceStatus,i);
- if(!item)
- break;
-
- TInt status, service;
- ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,service);
- if(ret!=KErrNone)
- {
- LOGPARSERR("service",ret,0,&KIdentityServiceStatus);
- continue;
- }
- ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,status);
- if(ret!=KErrNone)
- {
- LOGPARSERR("status",ret,1,&KIdentityServiceStatus);
- continue;
- }
-
- TIdentityServiceStatus identityServiceStatus;
- identityServiceStatus.iService = static_cast<RMobilePhone::TMobilePhoneIdService>(service);
- identityServiceStatus.iStatus = static_cast<RMobilePhone::TMobilePhoneIdServiceStatus>(status);
- iIdentityServiceStatus->AppendL(identityServiceStatus);
- }
-
- LOGCALL1("...Finished parsing Call Forwarding config parameters...");
- }
-
-CSimCallForwarding::~CSimCallForwarding()
- /**
- Destroy all the objects constructed.
- */
- {
- if (iIdentityServiceStatus != NULL)
- {
- iIdentityServiceStatus->Delete(0,iIdentityServiceStatus->Count());
- delete iIdentityServiceStatus;
- }
- delete iCFList;
- if (iGetCFStatus)
- iGetCFStatus->ResetAndDestroy();
- delete iGetCFStatus;
- }
-
-
-TInt CSimCallForwarding::ExtFunc(const TTsyReqHandle aReqHandle,const TInt aIpc, const TDataPackage& aPckg)
- {
- /**
- Handles all the Call forwarding APIs
- @param aReqHandle to the request
- @param Ipc unique identifier of the method to call
- @param aPckg contains arguments of the method to call
- */
- TAny* dataPtr = aPckg.Ptr1();
- TAny* dataPtr2 = aPckg.Ptr2();
-
- // The following requests can be completed even if the completion of another request is pending.
- switch(aIpc)
- {
- case EMobilePhoneSetCallForwardingStatus:
- return SetCallForwardingStatus(aReqHandle,
- reinterpret_cast<RMobilePhone::TMobilePhoneCFCondition*>(dataPtr),
- reinterpret_cast<RMobilePhone::TMobilePhoneCFChangeV1*>(dataPtr2));
- case EMobilePhoneNotifyCallForwardingStatusChange:
- return NotifyCallForwardingStatusChange(aReqHandle, reinterpret_cast<RMobilePhone::TMobilePhoneCFCondition*>(dataPtr));
- case EMobilePhoneGetIdentityServiceStatus:
- return GetIdentityServiceStatus(aReqHandle,
- reinterpret_cast<RMobilePhone::TMobilePhoneIdService*>(dataPtr),
- reinterpret_cast<RMobilePhone::TMobilePhoneIdServiceStatus*>(dataPtr2));
- case EMobilePhoneGetCallForwardingStatusPhase1:
- return GetCallForwardingStatusPhase1(aReqHandle,
- REINTERPRET_CAST(CRetrieveMobilePhoneCFList::TGetCallForwardingRequest*, dataPtr),
- REINTERPRET_CAST(TInt*, dataPtr2));
- case EMobilePhoneGetCallForwardingStatusPhase2:
- return GetCallForwardingStatusPhase2(aReqHandle,
- REINTERPRET_CAST(RMobilePhone::TClientId*, dataPtr), aPckg.Des2n());
- default:
- break;
- }
- return KErrNotSupported;
- }
-
-TInt CSimCallForwarding::CancelService(const TInt aIpc, const TTsyReqHandle aReqHandle)
- /**
- Cancels Call forwarding requests
- @param ipc request to cancel
- @param aReqHandle Handle to the request
- */
- {
- switch(aIpc)
- {
- case EMobilePhoneSetCallForwardingStatus:
- return SetCallForwardingStatusCancel(aReqHandle);
- case EMobilePhoneNotifyCallForwardingStatusChange:
- return NotifyCallForwardingStatusChangeCancel(aReqHandle);
- case EMobilePhoneGetIdentityServiceStatus:
- return GetIdentityServiceStatusCancel(aReqHandle);
- default:
- break;
- }
- return KErrNone;
- }
-
-void CSimCallForwarding::FindAndCreateCFListL()
- {
- /**
- Creates the Call forwarding list from the config file
- */
- LOGCALL1("CSimPhone::FindAndCreateCFListL");
- RMobilePhone::TMobilePhoneCFInfoEntryV1 entry;
-
- if(iCFList)
- delete iCFList;
- iCFList=NULL;
-
- iCFList = CMobilePhoneCFList::NewL();
- TInt count=CfgFile()->ItemCount(KCFList);
- const CTestConfigItem* item=NULL;
- TInt ret=KErrNone;
-
- LOGCALL1("Starting to Load and Parse CFList Config parameters");
-
- TInt i;
- for(i=0;i<count;i++)
- {
- item=CfgFile()->Item(KCFList,i);
- if(!item)
- break;
-
- TPtrC8 number;
- TInt condition, serviceGroup, status, timeout; // valid for CFRNy only
- ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,condition);
- if(ret!=KErrNone)
- {
- LOGPARSERR("condition",ret,0,&KCFList);
- continue;
- }
- ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,serviceGroup);
- if(ret!=KErrNone)
- {
- LOGPARSERR("serviceGroup",ret,1,&KCFList);
- continue;
- }
-
- ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,status);
- if(ret!=KErrNone)
- {
- LOGPARSERR("status",ret,2,&KCFList);
- continue;
- }
-
- ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,timeout);
- if(ret!=KErrNone)
- {
- LOGPARSERR("timeout",ret,3,&KCFList);
- continue;
- }
-
- ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,4,number);
- if(ret!=KErrNone)
- {
- LOGPARSERR("number",ret,4,&KCFList);
- continue;
- }
-
- entry.iServiceGroup=(RMobilePhone::TMobileService)serviceGroup;
- entry.iNumber.iTelNumber.Copy(number);
- entry.iTimeout=timeout;
- entry.iCondition=(RMobilePhone::TMobilePhoneCFCondition)condition;
- entry.iStatus=(RMobilePhone::TMobilePhoneCFStatus)status;
- iCFList->AddEntryL(entry);
- }//end for
-
- //CFlist must define entries for each condition even if unknown
- //fill up table if it misses conditions:
-
- RArray<TBool> serviceArray;
- //voice, auxVoice, data, packet, fax, sms, all;
-
- CleanupClosePushL(serviceArray);
-
- RMobilePhone::TMobilePhoneCFInfoEntryV1 extraEntry;
-
- for (TInt j=1;j<5;j++)//loop conditions
- {
- TInt serviceFound=EFalse;
- TInt index;
- extraEntry.iCondition=static_cast<RMobilePhone::TMobilePhoneCFCondition>(j);
- serviceArray.Reset();
- for(TInt h=0;h<8;h++)
- {
- serviceArray.Append(EFalse);
- }
-
- for (TInt k=0;k<count;k++)//loop entries
- {
- entry=iCFList->GetEntryL(k);
- if(entry.iCondition==static_cast<RMobilePhone::TMobilePhoneCFCondition>(j))
- {
- index = (TInt)entry.iServiceGroup;
- serviceArray[index]=ETrue;
- }
- }
-
- if (!serviceArray[7])//(all services)
- {
- for (TInt l=1;l<7;l++)
- {
- if (serviceArray[l])
- serviceFound=ETrue;
- }
- //no service defined for this condition
- if(!serviceFound)
- {
- extraEntry.iServiceGroup=RMobilePhone::EAllServices;
- extraEntry.iStatus=RMobilePhone::ECallForwardingStatusNotRegistered;
- iCFList->AddEntryL(extraEntry);
- }
- //some services defined in table
- else
- {
- for (TInt m=1;m<7;m++)
- {
- if (!serviceArray[m])
- {
- extraEntry.iServiceGroup=static_cast<RMobilePhone::TMobileService>(m);
- extraEntry.iStatus=RMobilePhone::ECallForwardingStatusNotRegistered;
- iCFList->AddEntryL(extraEntry);
- }
- }//end for
- }//end else
- }//end if
- }//end for
-
- CleanupStack::PopAndDestroy(&serviceArray); //Destroying serviceArray to free the memory
- }
-
-TInt CSimCallForwarding::GetIdentityServiceStatus(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhoneIdService* aService, RMobilePhone::TMobilePhoneIdServiceStatus* aStatus)
- /**
- Gets the status of the identity services
- @param aReqHandle handle to the request
- @param aService service that the client is interested in
- @param aStatus of the identity service
- */
- {
- RMobilePhone::TMobilePhoneIdServiceStatus status;
- status = RMobilePhone::EIdServiceUnknown;
- TInt count = iIdentityServiceStatus->Count();
- for(TInt i=0; i<count; i++)
- {
- if(iIdentityServiceStatus->At(i).iService == *aService)
- {
- status = iIdentityServiceStatus->At(i).iStatus;
- break;
- }
- }
- *aStatus = status;
- iPhone->ReqCompleted(aReqHandle, KErrNone);
- return KErrNone;
- }
-
-TInt CSimCallForwarding::GetIdentityServiceStatusCancel(const TTsyReqHandle aReqHandle)
- /**
- Cancels the request to get the status of the identity services
- @param aReqHandle hadle to the request
- */
- {
- iPhone->ReqCompleted(aReqHandle,KErrCancel);
- return KErrNone;
- }
-
-TInt CSimCallForwarding::NotifyCallForwardingStatusChange(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhoneCFCondition* aCF)
- /**
- Requests to be notified of call forwarding status change
- @param aReqHandle handle to the request
- @param aCF condition for which the client wants to be notified
- */
- {
- __ASSERT_ALWAYS(!iCFNotification.iCFChangeInfoNotificationPending,SimPanic(ENotificationReqAlreadyOutstanding));
-
- iCFNotification.iCFChangeInfoNotificationPending=ETrue;
- iCFNotification.iCFChangeInfoReqHandle=aReqHandle;
- iCFNotification.iCurrentCFCondition=aCF;
- LOGCALL1("Finished CSimCallForwarding::NotifyCallForwardingStatusChange");
- return KErrNone;
- }
-
-TInt CSimCallForwarding::NotifyCallForwardingStatusChangeCancel(const TTsyReqHandle aReqHandle)
- /**
- Cancels the request to be notified of call forwarding status change
- @param aReqHandle handle to the request
- */
- {
- if(iCFNotification.iCFChangeInfoNotificationPending)
- {
- iCFNotification.iCFChangeInfoNotificationPending=EFalse;
- iPhone->ReqCompleted(aReqHandle,KErrCancel);
- }
- return KErrNone;
- }
-
-TInt CSimCallForwarding::SetCallForwardingStatus(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhoneCFCondition* aCF, RMobilePhone::TMobilePhoneCFChangeV1* aInfo)
- /**
- Sets the status of call forwarding
- @param aReqHandle handle to the request
- @param aCF condition for which the client wants to set the status
- @param aInfo value of Call forwarding to set
- */
- {
- TRAPD(err, UpdateCFListL(aCF,aInfo));
- if ( err != KErrNone )
- {
- iPhone->ReqCompleted(aReqHandle,err);
- return KErrNone;
- }
-
- if(iCFNotification.iCFChangeInfoNotificationPending)
- {
- *(iCFNotification.iCurrentCFCondition)=*aCF;
- iCFNotification.iCFChangeInfoNotificationPending=EFalse;
- iPhone->ReqCompleted(iCFNotification.iCFChangeInfoReqHandle,KErrNone);
- }
-
- iPhone->ReqCompleted(aReqHandle,err);
- LOGCALL1("Finished CSimCallForwarding::SetCallForwardingStatus");
- return KErrNone;
- }
-
-TInt CSimCallForwarding::SetCallForwardingStatusCancel(const TTsyReqHandle aReqHandle)
- /**
- Cancels the request to set the status of call forwarding
- @param aReqHandle handle to the request
- */
- {
- iPhone->ReqCompleted(aReqHandle,KErrCancel);
- return KErrNone;
- }
-
-
-TInt CSimCallForwarding::GetCallForwardingStatusPhase1(const TTsyReqHandle aTsyReqHandle,
- CRetrieveMobilePhoneCFList::TGetCallForwardingRequest* aReqData,
- TInt* aBufSize)
- {
- /**
- 1st phase retrieval of the status of call forwarding
- @param aTsyReqHandle handle to the request
- @param aReqData contains details of the request
- @param aBufSize size of the buffer the client needs to allocate for phase 2
- */
- LOGCALL1("CSimPhone::GetCallForwardingStatusPhase1");
- TInt ret=KErrNone;
-
- // for forwarding we cannot querry for all conditions;
- // conditions - specific
- // services - individual and all
- if ((aReqData->iCondition==RMobilePhone::ECallForwardingUnspecified)
- || (aReqData->iCondition==RMobilePhone::ECallForwardingAllCases)
- || (aReqData->iCondition==RMobilePhone::ECallForwardingAllConditionalCases))
- {
- iPhone->ReqCompleted(aTsyReqHandle,KErrArgument);
- }
- else
- {
- TInt leaveCode=KErrNone;
- TRAP(leaveCode, ret=ProcessGetCallForwardingStatusPhase1L(aTsyReqHandle, aReqData, aBufSize););
- if (leaveCode != KErrNone)
- iPhone->ReqCompleted(aTsyReqHandle,leaveCode);
- }
- LOGCALL1("CSimPhone::GetCallForwardingStatusPhase1");
- return ret;
- }
-
-TInt CSimCallForwarding::ProcessGetCallForwardingStatusPhase1L(const TTsyReqHandle aTsyReqHandle,
- CRetrieveMobilePhoneCFList::TGetCallForwardingRequest* aReqData,
- TInt* aBufSize)
- {
- /** Retrieve call forwarding status of each line from phone,
- store each CF status response as a list entry,
- stream the list and then return size of this buffer to client
- @param aReqHandle Handle to the request
- @param aReqData information about the request
- @param aBufSize Size of the buffer the client has to allocate for the 2nd pahase
- */
-
- LOGCALL1("CSimPhone::ProcessGetCallForwardingStatusPhase1L");
-
- CMobilePhoneCFList* list=CMobilePhoneCFList::NewL();
- CleanupStack::PushL(list);
-
- TInt cnt=0;//Only interested by entries with a particular condition
- TInt maxNum=iCFList->Enumerate();
- TBool isAllGroups = (aReqData->iServiceGroup == RMobilePhone::EAllServices);
- for(TInt i=0;i<maxNum;i++)
- {
- RMobilePhone::TMobilePhoneCFInfoEntryV1 entry = iCFList->GetEntryL(i);
-
- // Check that the data structure is supported by the simulated TSY version
- TInt err = iPhone->CheckSimTsyVersion(entry);
- if(err != KErrNone)
- {
- iPhone->ReqCompleted(aTsyReqHandle, err);
- return KErrNone;
- }
-
- if((entry.iCondition == aReqData->iCondition)
- &&(entry.iStatus != RMobilePhone::ECallForwardingStatusNotRegistered))
- {
- if ( !isAllGroups && (entry.iServiceGroup != aReqData->iServiceGroup))
- {
- continue;
- }
- list->AddEntryL(entry);
- cnt++;
- }
- }
- // Store the streamed list and the client ID
- CListReadAllAttempt* read=CListReadAllAttempt::NewL(aReqData->iClient,aTsyReqHandle);
- CleanupStack::PushL(read);
-
- read->iListBuf = list->StoreLC();
- CleanupStack::Pop(); // pop the CBufBase allocated by StoreLC
-
- iGetCFStatus->AppendL(read);
- CleanupStack::Pop(read); // pop the CListReadAllAttempt
-
- // return the CBufBase’s size to client
- *aBufSize=(read->iListBuf)->Size();
-
- CleanupStack::PopAndDestroy(list); // pop&destroy list
-
- // Complete first phase of list retrieval
- iPhone->ReqCompleted(aTsyReqHandle,KErrNone);
- LOGCALL1("CSimPhone::ProcessGetCallForwardingStatusPhase1L");
- return KErrNone;
- }
-
-TInt CSimCallForwarding::GetCallForwardingStatusPhase2(const TTsyReqHandle aTsyReqHandle,
- RMobilePhone::TClientId* aClient, TDes8* aBuf)
- /**
- 2nd phase retrieval of the status of call forwarding
- @param aTsyRqHandle handle to the request
- @param aClient pointer to the client
- @param aBuf buffer that contains the call forwarding list
- */
- {
- LOGCALL1("CSimPhone::GetCallForwardingStatusPhase2");
- CListReadAllAttempt* read=NULL;
- // Find the get detected network attempt from this client
- for (TInt i=0; i<iGetCFStatus->Count(); ++i)
- {
- read = iGetCFStatus->At(i);
- if ((read->iClient.iSessionHandle==aClient->iSessionHandle) &&
- (read->iClient.iSubSessionHandle==aClient->iSubSessionHandle))
- {
- TPtr8 bufPtr((read->iListBuf)->Ptr(0));
- // Copy the streamed list to the client
- aBuf->Copy(bufPtr);
- delete read;
- iGetCFStatus->Delete(i);
- iPhone->ReqCompleted(aTsyReqHandle,KErrNone);
- return KErrNone;
- }
- }
- // Should handle error case of not finding the matching client from read all phase 1
- LOGCALL1("CSimPhone::GetCallForwardingStatusPhase2");
- return KErrNotFound;
- }
-
-
-TInt CSimCallForwarding::GetCallForwardingStatusCancel(const TTsyReqHandle aTsyReqHandle)
- {
- /**
- Cancel the request to retrieve the status of call forwarding
- @param aTsyReqHandle handle to the request
- */
- LOGCALL1("CSimPhone::GetCallForwardingStatusCancel");
- iPhone->ReqCompleted(aTsyReqHandle,KErrNone);
- // Remove the read all attempt from iGetCFStatus
- CListReadAllAttempt* read=NULL;
- for (TInt i=0; i<iGetCFStatus->Count(); ++i)
- {
- read = iGetCFStatus->At(i);
- if (read->iReqHandle == aTsyReqHandle)
- {
- delete read;
- iGetCFStatus->Delete(i);
- break;
- }
- }
- iPhone->ReqCompleted(aTsyReqHandle,KErrCancel);
- LOGCALL1("CSimPhone::GetCallForwardingStatusCancel");
- return KErrNone;
- }
-
-void CSimCallForwarding::UpdateCFListL(RMobilePhone::TMobilePhoneCFCondition* aCF,
- RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo )
- {
- /**
- Modifies the status of call forwarding
- @param aCF condition
- @param aCFInfo details of the request
- */
- User::LeaveIfNull(aCF);
- User::LeaveIfNull(aCFInfo);
-
- if (*aCF == RMobilePhone::ECallForwardingUnspecified)
- {
- // not supported - tell user it is a wrong argument
- User::Leave(KErrArgument);
- }
-
- if ((*aCF == RMobilePhone::ECallForwardingAllCases)
- ||(*aCF == RMobilePhone::ECallForwardingAllConditionalCases))
- {
- // not supported - tell user it is a wrong argument
- User::Leave(KErrNotSupported);
- }
-
- switch (aCFInfo->iAction)
- {
- case RMobilePhone::EServiceActionRegister:
- RegisterL(aCF, aCFInfo);
- break;
-
- case RMobilePhone::EServiceActionActivate:
- ActivateL(aCF, aCFInfo);
- break;
-
- case RMobilePhone::EServiceActionInvoke:
- // currently not supported
- // tell user it is a wrong argument
- User::Leave(KErrArgument);
- break;
-
- case RMobilePhone::EServiceActionDeactivate:
- DeactivateL(aCF, aCFInfo);
- break;
-
- case RMobilePhone::EServiceActionErase:
- EraseL(aCF, aCFInfo);
- break;
-
- case RMobilePhone::EServiceActionUnspecified:
- default:
- // not supported - tell user it is a wrong argument
- User::Leave(KErrArgument);
- break;
- }
- }
-
-
-inline void SplitOneCFEntryIntoSeparateGroupsL(CMobilePhoneCFList* aCFList,
- RMobilePhone::TMobilePhoneCFInfoEntryV1& aOrigEntry,
- RMobilePhone::TMobileService aExceptServiceGroup)
- {
- /*
- Splits one entry valid for all basic service groups into individual entries
- and places them into a CMobilePhoneCFList. This excludes one service group.
- @param aCBList The list to which to store the entries
- @param aOrigEntry The original entry; details of which should be passed to individual group entries
- @param aExceptServiceGroup The group which has to be avoided
- */
- // we have to split the entry into entries
- // per group with the same condition; excluding the specified service group
- RMobilePhone::TMobilePhoneCFInfoEntryV1 anotherEntry(aOrigEntry);
-
- RMobilePhone::TMobileService service;
-
- for (TInt i = KMobServiceIndxStart;i <= KMobServiceIndxEnd;i++)
- {
- service=static_cast<RMobilePhone::TMobileService>(i);
-
- if( service != aExceptServiceGroup )
- {
- anotherEntry.iServiceGroup=service;
- aCFList->AddEntryL(anotherEntry);
- }
- }//end for (another)
- }
-
-
-void CSimCallForwarding::UpdateCFQuiescentConditionL(TBool aActivate,
- RMobilePhone::TMobilePhoneCFCondition aCF)
- {
- // only the Call Forward Unconditional can alter any other CF condition
- if(aCF == RMobilePhone::ECallForwardingUnconditional)
- {
- TBool cFBChangeRequired = EFalse;
-
- RMobilePhone::TMobilePhoneCFInfoEntryV1 theEntry;
-
- const TInt count = iCFList->Enumerate();
-
- // look for any instances of the ECallForwardingBusy
- for (TInt indx=0; indx < count; indx++)
- {
- theEntry = iCFList->GetEntryL(indx);
-
- if(theEntry.iCondition == RMobilePhone::ECallForwardingBusy &&
- (theEntry.iStatus == RMobilePhone::ECallForwardingStatusActive ||
- theEntry.iStatus == RMobilePhone::ECallForwardingStatusQuiescent))
- {
- cFBChangeRequired = ETrue;
- }
- }
-
- if(cFBChangeRequired)
- {
- // retain prev version of the list in local variable and in Cleanup stack
- CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL();
- CleanupStack::PushL(thePrevCFList);
-
- // copy existing data into the temp storage
- for (TInt indx=0; indx < count; indx++)
- {
- thePrevCFList->AddEntryL(iCFList->GetEntryL(indx));
- }
-
- delete iCFList;
- iCFList = NULL;
-
- // create a new version and hold it in the class member
- iCFList = CMobilePhoneCFList::NewL();
-
- // get a hold of it in a local variable
- CMobilePhoneCFList* theNewCFList = iCFList;
-
- for(TInt indx=0; indx < count; indx++)
- {
- theEntry = thePrevCFList->GetEntryL(indx);
-
- if(theEntry.iCondition == RMobilePhone::ECallForwardingBusy)
- {
- if(aActivate)
- {
- if(theEntry.iStatus == RMobilePhone::ECallForwardingStatusActive)
- {
- theEntry.iStatus = RMobilePhone::ECallForwardingStatusQuiescent;
- }
- }
- else
- {
- if(theEntry.iStatus == RMobilePhone::ECallForwardingStatusQuiescent)
- {
- theEntry.iStatus = RMobilePhone::ECallForwardingStatusActive;
- }
- }
- }
- theNewCFList->AddEntryL(theEntry);
- }
-
- // now delete the old memory
- CleanupStack::PopAndDestroy(thePrevCFList);
- }
- }
- }
-
-void CSimCallForwarding::ActivateL(RMobilePhone::TMobilePhoneCFCondition* aCF,
- RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo )
- {
- // NOTE: An assumption is made that the calling method has checked the parameters
- // are not NULL.
- RMobilePhone::TMobilePhoneCFInfoEntryV1 theNewEntry;
-
- theNewEntry.iCondition = *aCF;
- theNewEntry.iServiceGroup = aCFInfo->iServiceGroup;
- theNewEntry.iStatus= RMobilePhone::ECallForwardingStatusNotActive;
- theNewEntry.iNumber = aCFInfo->iNumber;
-
- if (*aCF == RMobilePhone::ECallForwardingNoReply)
- {
- theNewEntry.iTimeout = aCFInfo->iTimeout;
- }
- else
- {
- theNewEntry.iTimeout = KInvalidTimeout;
- }
-
-
- // retain prev version of the list in local variable and in Cleanup stack
- CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL();
- CleanupStack::PushL(thePrevCFList);
-
- const TInt count = iCFList->Enumerate();
-
- TBool CFUActive = EFalse;
-
- // copy existing data into the temp storage
- for (TInt indx = 0; indx < count; indx++)
- {
- thePrevCFList->AddEntryL(iCFList->GetEntryL(indx));
-
- RMobilePhone::TMobilePhoneCFInfoEntryV1 copyEntry = iCFList->GetEntryL(indx);
-
- if(copyEntry.iCondition == RMobilePhone::ECallForwardingUnconditional &&
- copyEntry.iStatus == RMobilePhone::ECallForwardingStatusActive)
- {
- CFUActive = ETrue;
- }
- }
-
- delete iCFList;
- iCFList = NULL;
-
- // create a new version and hold it in the class member
- iCFList = CMobilePhoneCFList::NewL();
-
- // get a hold of it in a local variable
- CMobilePhoneCFList* theNewCFList = iCFList;
-
- TBool callForwardActivated = EFalse;
-
- RMobilePhone::TMobilePhoneCFInfoEntryV1 entry;
-
- for (TInt i = 0; i < count; i++)
- {
- entry = thePrevCFList->GetEntryL(i);
-
- if(theNewEntry.iCondition == entry.iCondition)
- {
- if(theNewEntry.iServiceGroup == entry.iServiceGroup)
- {
- // only activate service if previously in a not active state
- if(entry.iStatus == RMobilePhone::ECallForwardingStatusNotActive)
- {
- if(entry.iCondition == RMobilePhone::ECallForwardingBusy && CFUActive != EFalse)
- {
- // do nothing, condition's service will not be activated as callforwarding
- // unconditional is active
- }
- else
- {
- entry.iStatus = RMobilePhone::ECallForwardingStatusActive;
- callForwardActivated = ETrue;
- }
- }
- }
- else if(entry.iServiceGroup == RMobilePhone::EAllServices)
- {
- if(entry.iStatus == RMobilePhone::ECallForwardingStatusNotActive)
- {
- SplitOneCFEntryIntoSeparateGroupsL(theNewCFList,
- entry,
- theNewEntry.iServiceGroup);
-
- callForwardActivated = ETrue;
- entry = theNewEntry;
- }
- }
- }
-
- theNewCFList->AddEntryL(entry);
- }
-
- if(callForwardActivated)
- {
- // only need to check quiescent status if an activation has occurred
- UpdateCFQuiescentConditionL(ETrue, theNewEntry.iCondition);
- }
-
- CleanupStack::PopAndDestroy(thePrevCFList);
- }
-
-void CSimCallForwarding::RegisterL(RMobilePhone::TMobilePhoneCFCondition* aCF, RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo)
- {
- TInt count = iCFList->Enumerate();
- RMobilePhone::TMobilePhoneCFInfoEntryV1 theNewEntry;
-
- theNewEntry.iCondition = *aCF;
- theNewEntry.iServiceGroup = aCFInfo->iServiceGroup;
- theNewEntry.iStatus= RMobilePhone::ECallForwardingStatusNotActive;
-
- theNewEntry.iNumber = aCFInfo->iNumber;
- if (*aCF == RMobilePhone::ECallForwardingNoReply)
- {
- theNewEntry.iTimeout = aCFInfo->iTimeout;
- }
- else
- {
- theNewEntry.iTimeout = KInvalidTimeout;
- }
-
- // retain prev version of the list in local variable and in Cleanup stack
- CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL();
- CleanupStack::PushL(thePrevCFList);
- // copy existing data into the temp storage
- for (TInt indx=0; indx<count; indx++)
- {
- thePrevCFList->AddEntryL(iCFList->GetEntryL(indx));
- }
- delete iCFList;
- iCFList = NULL;
- // create a new version and hold it in the class member
- iCFList = CMobilePhoneCFList::NewL();
- // get a hold of it in a local variable
- CMobilePhoneCFList* theNewCFList = iCFList;
-
- if (theNewEntry.iServiceGroup==RMobilePhone::EAllServices)
- {
- //nothing for all conds
-
- //action is to Regiser (and activate)AllServices with a particular condition;
- //Only copy entries with a different condition
- //entries with same condition should not be copied as they will
- //be represented by 1 with allservices
- for (TInt i = 0; i<count; i++)
- {
- RMobilePhone::TMobilePhoneCFInfoEntryV1 entry = thePrevCFList->GetEntryL(i);
-
- if (entry.iCondition != theNewEntry.iCondition)
- // check if the existing entry is encompassed by the new one
- theNewCFList->AddEntryL(entry);
- }
- theNewCFList->AddEntryL(theNewEntry);
- }
- else
- {
- //ActivateOne;
- for (TInt i = 0; i<count; i++)
- {
- RMobilePhone::TMobilePhoneCFInfoEntryV1 entry = thePrevCFList->GetEntryL(i);
-
- if (theNewEntry.iCondition==entry.iCondition
- && entry.iServiceGroup==theNewEntry.iServiceGroup)
- {
- theNewCFList->AddEntryL(theNewEntry);
- continue;
- }
- if (entry.iCondition != theNewEntry.iCondition
- || (entry.iCondition == theNewEntry.iCondition
- && entry.iServiceGroup != theNewEntry.iServiceGroup
- && entry.iServiceGroup != RMobilePhone::EAllServices))
- {
- theNewCFList->AddEntryL(entry);
- continue;
- }
-
- if(theNewEntry.iCondition==entry.iCondition
- && entry.iServiceGroup==RMobilePhone::EAllServices)
- {
-
- SplitOneCFEntryIntoSeparateGroupsL(
- theNewCFList,
- entry,
- theNewEntry.iServiceGroup
- );
-
- theNewCFList->AddEntryL(theNewEntry);
- }//end if
- }//end for
- }//end else
- // now delete the old memory
- CleanupStack::PopAndDestroy(thePrevCFList);
- }
-
-void CSimCallForwarding::DeactivateL(RMobilePhone::TMobilePhoneCFCondition* aCF,
- RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo )
- {
- // NOTE: An assumption is made that the calling method has checked the parameters
- // are not NULL.
-
- RMobilePhone::TMobilePhoneCFInfoEntryV1 theNewEntry;
-
- theNewEntry.iCondition = *aCF;
- theNewEntry.iServiceGroup = aCFInfo->iServiceGroup;
- theNewEntry.iStatus= RMobilePhone::ECallForwardingStatusNotActive;
-
- // retain prev version of the list in local variable and in Cleanup stack
- CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL();
- CleanupStack::PushL(thePrevCFList);
-
- const TInt count = iCFList->Enumerate();
-
- // copy existing data into the temp storage
- for (TInt indx = 0; indx < count; indx++)
- {
- thePrevCFList->AddEntryL(iCFList->GetEntryL(indx));
- }
-
- delete iCFList;
- iCFList = NULL;
-
- // create a new version and hold it in the class member
- iCFList = CMobilePhoneCFList::NewL();
-
- // get a hold of it in a local variable
- CMobilePhoneCFList* theNewCFList = iCFList;
-
- TBool callForwardDeactivated = EFalse;
-
- RMobilePhone::TMobilePhoneCFInfoEntryV1 entry;
-
- //Deactivate will deactivate active entries
- for (TInt indx = 0; indx < count; indx++)
- {
- entry = thePrevCFList->GetEntryL(indx);
-
- if(entry.iCondition == theNewEntry.iCondition)
- {
- if(entry.iServiceGroup == theNewEntry.iServiceGroup)
- {
- if(entry.iStatus == RMobilePhone::ECallForwardingStatusActive)
- {
- entry.iStatus = RMobilePhone::ECallForwardingStatusNotActive;
- callForwardDeactivated = ETrue;
- }
- }
- else if(entry.iServiceGroup == RMobilePhone::EAllServices)
- {
- if(entry.iStatus == RMobilePhone::ECallForwardingStatusActive)
- {
- SplitOneCFEntryIntoSeparateGroupsL(theNewCFList,
- entry,
- theNewEntry.iServiceGroup);
-
- entry = theNewEntry;
- callForwardDeactivated = ETrue;
- }
- }
- }
-
- theNewCFList->AddEntryL(entry);
- }//end for
-
- // this method will check if any de-activation has caused another Condition to become
- // cleared of the quiescent state
- if(callForwardDeactivated)
- {
- // pass a FALSE to the function to notify of a service de-activation
- UpdateCFQuiescentConditionL(EFalse, theNewEntry.iCondition);
- }
-
- // now delete the old memory
- CleanupStack::PopAndDestroy(thePrevCFList);
- }
-
-void CSimCallForwarding::EraseL(RMobilePhone::TMobilePhoneCFCondition* aCF,
- RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo )
- {
- // NOTE: An assumption is made that the calling method has checked the parameters
- // are not NULL.
-
- RMobilePhone::TMobilePhoneCFInfoEntryV1 theNewEntry;
-
- theNewEntry.iCondition = *aCF;
- theNewEntry.iServiceGroup = aCFInfo->iServiceGroup;
- theNewEntry.iNumber.iTelNumber.Copy(KEmptyString);
- theNewEntry.iTimeout = KErrNotFound;
- theNewEntry.iStatus = RMobilePhone::ECallForwardingStatusNotRegistered;
-
- // retain prev version of the list in local variable and in Cleanup stack
- CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL();
- CleanupStack::PushL(thePrevCFList);
-
- const TInt count = iCFList->Enumerate();
-
- // copy existing data into the temp storage
- for (TInt indx = 0; indx < count; indx++)
- {
- thePrevCFList->AddEntryL(iCFList->GetEntryL(indx));
- }
-
- delete iCFList;
- iCFList = NULL;
-
- // create a new version and hold it in the class member
- iCFList = CMobilePhoneCFList::NewL();
-
- // get a hold of it in a local variable
- CMobilePhoneCFList* theNewCFList = iCFList;
-
- RMobilePhone::TMobilePhoneCFInfoEntryV1 entry;
-
- for(TInt i = 0; i < count; i++)
- {
- entry = thePrevCFList->GetEntryL(i);
-
- if(entry.iCondition == theNewEntry.iCondition)
- {
- if(entry.iServiceGroup == theNewEntry.iServiceGroup)
- {
- if(entry.iStatus == RMobilePhone::ECallForwardingStatusNotActive)
- {
- entry = theNewEntry;
- }
- }
- else if(entry.iServiceGroup == RMobilePhone::EAllServices)
- {
- if(entry.iStatus == RMobilePhone::ECallForwardingStatusActive)
- {
- SplitOneCFEntryIntoSeparateGroupsL(theNewCFList,
- entry,
- theNewEntry.iServiceGroup);
-
- entry = theNewEntry;
- }
- }
- }
- theNewCFList->AddEntryL(entry);
- }
-
- // now delete the old memory
- CleanupStack::PopAndDestroy(thePrevCFList);
- }
-
-const CTestConfigSection* CSimCallForwarding::CfgFile()
-/**
- * Returns a pointer to the current configuration file section.
- *
- * @return CTestConfigSection A pointer to the current configuration file data section.
- */
- {
- return iPhone->CfgFile();
- }
-
-
+// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implements the functionality required to provide clients with
+// callforwarding status and registration information.
+//
+//
+
+/**
+ @file
+*/
+
+#include <testconfigfileparser.h>
+#include "CSimCallForwarding.h"
+#include "CSimPhone.h"
+#include "Simlog.h"
+
+const TInt KSettingListGranularity=5; // < The granularity used for parameter list arrays.
+const TInt KInvalidTimeout = -1; // Value used when timeout period does not matter
+const TInt KMobServiceIndxStart = 1;
+const TInt KMobServiceIndxEnd = 6;
+
+CSimCallForwarding* CSimCallForwarding::NewL(CSimPhone* aPhone)
+/**
+ * Standard two-phase constructor.
+ * @param aPhone The parent phone object.
+ * @return CSimNetworkStatus The new network status class.
+ */
+ {
+ CSimCallForwarding* self=new(ELeave) CSimCallForwarding(aPhone);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+CSimCallForwarding::CSimCallForwarding(CSimPhone* aPhone)
+ : iPhone(aPhone)
+/**
+ * Trivial first phase construction.
+ * @param aPhone The parent phone object.
+ */
+ {
+ }
+
+void CSimCallForwarding::ConstructL()
+ /**
+ Second phase of 2-Phase Constructor
+ Retrieves all the Call forwarding and Identity services tags from the config file
+ */
+ {
+ LOGCALL1("Starting to parse Call Forwarding config parameters...");
+
+ iIdentityServiceStatus=new(ELeave) CArrayFixFlat<TIdentityServiceStatus>(KSettingListGranularity);
+
+ iGetCFStatus = new(ELeave) CArrayPtrFlat<CListReadAllAttempt>(1);
+ FindAndCreateCFListL();
+
+ // Read in the Identity services information
+ TInt count=CfgFile()->ItemCount(KIdentityServiceStatus);
+ const CTestConfigItem* item=NULL;
+ TInt ret=KErrNone;
+ for(TInt i=0;i<count;i++)
+ {
+ item=CfgFile()->Item(KIdentityServiceStatus,i);
+ if(!item)
+ break;
+
+ TInt status, service;
+ ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,service);
+ if(ret!=KErrNone)
+ {
+ LOGPARSERR("service",ret,0,&KIdentityServiceStatus);
+ continue;
+ }
+ ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,status);
+ if(ret!=KErrNone)
+ {
+ LOGPARSERR("status",ret,1,&KIdentityServiceStatus);
+ continue;
+ }
+
+ TIdentityServiceStatus identityServiceStatus;
+ identityServiceStatus.iService = static_cast<RMobilePhone::TMobilePhoneIdService>(service);
+ identityServiceStatus.iStatus = static_cast<RMobilePhone::TMobilePhoneIdServiceStatus>(status);
+ iIdentityServiceStatus->AppendL(identityServiceStatus);
+ }
+
+ LOGCALL1("...Finished parsing Call Forwarding config parameters...");
+ }
+
+CSimCallForwarding::~CSimCallForwarding()
+ /**
+ Destroy all the objects constructed.
+ */
+ {
+ if (iIdentityServiceStatus != NULL)
+ {
+ iIdentityServiceStatus->Delete(0,iIdentityServiceStatus->Count());
+ delete iIdentityServiceStatus;
+ }
+ delete iCFList;
+ if (iGetCFStatus)
+ iGetCFStatus->ResetAndDestroy();
+ delete iGetCFStatus;
+ }
+
+
+TInt CSimCallForwarding::ExtFunc(const TTsyReqHandle aReqHandle,const TInt aIpc, const TDataPackage& aPckg)
+ {
+ /**
+ Handles all the Call forwarding APIs
+ @param aReqHandle to the request
+ @param Ipc unique identifier of the method to call
+ @param aPckg contains arguments of the method to call
+ */
+ TAny* dataPtr = aPckg.Ptr1();
+ TAny* dataPtr2 = aPckg.Ptr2();
+
+ // The following requests can be completed even if the completion of another request is pending.
+ switch(aIpc)
+ {
+ case EMobilePhoneSetCallForwardingStatus:
+ return SetCallForwardingStatus(aReqHandle,
+ reinterpret_cast<RMobilePhone::TMobilePhoneCFCondition*>(dataPtr),
+ reinterpret_cast<RMobilePhone::TMobilePhoneCFChangeV1*>(dataPtr2));
+ case EMobilePhoneNotifyCallForwardingStatusChange:
+ return NotifyCallForwardingStatusChange(aReqHandle, reinterpret_cast<RMobilePhone::TMobilePhoneCFCondition*>(dataPtr));
+ case EMobilePhoneGetIdentityServiceStatus:
+ return GetIdentityServiceStatus(aReqHandle,
+ reinterpret_cast<RMobilePhone::TMobilePhoneIdService*>(dataPtr),
+ reinterpret_cast<RMobilePhone::TMobilePhoneIdServiceStatus*>(dataPtr2));
+ case EMobilePhoneGetCallForwardingStatusPhase1:
+ return GetCallForwardingStatusPhase1(aReqHandle,
+ REINTERPRET_CAST(CRetrieveMobilePhoneCFList::TGetCallForwardingRequest*, dataPtr),
+ REINTERPRET_CAST(TInt*, dataPtr2));
+ case EMobilePhoneGetCallForwardingStatusPhase2:
+ return GetCallForwardingStatusPhase2(aReqHandle,
+ REINTERPRET_CAST(RMobilePhone::TClientId*, dataPtr), aPckg.Des2n());
+ default:
+ break;
+ }
+ return KErrNotSupported;
+ }
+
+TInt CSimCallForwarding::CancelService(const TInt aIpc, const TTsyReqHandle aReqHandle)
+ /**
+ Cancels Call forwarding requests
+ @param ipc request to cancel
+ @param aReqHandle Handle to the request
+ */
+ {
+ switch(aIpc)
+ {
+ case EMobilePhoneSetCallForwardingStatus:
+ return SetCallForwardingStatusCancel(aReqHandle);
+ case EMobilePhoneNotifyCallForwardingStatusChange:
+ return NotifyCallForwardingStatusChangeCancel(aReqHandle);
+ case EMobilePhoneGetIdentityServiceStatus:
+ return GetIdentityServiceStatusCancel(aReqHandle);
+ default:
+ break;
+ }
+ return KErrNone;
+ }
+
+void CSimCallForwarding::FindAndCreateCFListL()
+ {
+ /**
+ Creates the Call forwarding list from the config file
+ */
+ LOGCALL1("CSimPhone::FindAndCreateCFListL");
+ RMobilePhone::TMobilePhoneCFInfoEntryV1 entry;
+
+ if(iCFList)
+ delete iCFList;
+ iCFList=NULL;
+
+ iCFList = CMobilePhoneCFList::NewL();
+ TInt count=CfgFile()->ItemCount(KCFList);
+ const CTestConfigItem* item=NULL;
+ TInt ret=KErrNone;
+
+ LOGCALL1("Starting to Load and Parse CFList Config parameters");
+
+ TInt i;
+ for(i=0;i<count;i++)
+ {
+ item=CfgFile()->Item(KCFList,i);
+ if(!item)
+ break;
+
+ TPtrC8 number;
+ TInt condition, serviceGroup, status, timeout; // valid for CFRNy only
+ ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,condition);
+ if(ret!=KErrNone)
+ {
+ LOGPARSERR("condition",ret,0,&KCFList);
+ continue;
+ }
+ ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,serviceGroup);
+ if(ret!=KErrNone)
+ {
+ LOGPARSERR("serviceGroup",ret,1,&KCFList);
+ continue;
+ }
+
+ ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,status);
+ if(ret!=KErrNone)
+ {
+ LOGPARSERR("status",ret,2,&KCFList);
+ continue;
+ }
+
+ ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,timeout);
+ if(ret!=KErrNone)
+ {
+ LOGPARSERR("timeout",ret,3,&KCFList);
+ continue;
+ }
+
+ ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,4,number);
+ if(ret!=KErrNone)
+ {
+ LOGPARSERR("number",ret,4,&KCFList);
+ continue;
+ }
+
+ entry.iServiceGroup=(RMobilePhone::TMobileService)serviceGroup;
+ entry.iNumber.iTelNumber.Copy(number);
+ entry.iTimeout=timeout;
+ entry.iCondition=(RMobilePhone::TMobilePhoneCFCondition)condition;
+ entry.iStatus=(RMobilePhone::TMobilePhoneCFStatus)status;
+ iCFList->AddEntryL(entry);
+ }//end for
+
+ //CFlist must define entries for each condition even if unknown
+ //fill up table if it misses conditions:
+
+ RArray<TBool> serviceArray;
+ //voice, auxVoice, data, packet, fax, sms, all;
+
+ CleanupClosePushL(serviceArray);
+
+ RMobilePhone::TMobilePhoneCFInfoEntryV1 extraEntry;
+
+ for (TInt j=1;j<5;j++)//loop conditions
+ {
+ TInt serviceFound=EFalse;
+ TInt index;
+ extraEntry.iCondition=static_cast<RMobilePhone::TMobilePhoneCFCondition>(j);
+ serviceArray.Reset();
+ for(TInt h=0;h<8;h++)
+ {
+ serviceArray.Append(EFalse);
+ }
+
+ for (TInt k=0;k<count;k++)//loop entries
+ {
+ entry=iCFList->GetEntryL(k);
+ if(entry.iCondition==static_cast<RMobilePhone::TMobilePhoneCFCondition>(j))
+ {
+ index = (TInt)entry.iServiceGroup;
+ serviceArray[index]=ETrue;
+ }
+ }
+
+ if (!serviceArray[7])//(all services)
+ {
+ for (TInt l=1;l<7;l++)
+ {
+ if (serviceArray[l])
+ serviceFound=ETrue;
+ }
+ //no service defined for this condition
+ if(!serviceFound)
+ {
+ extraEntry.iServiceGroup=RMobilePhone::EAllServices;
+ extraEntry.iStatus=RMobilePhone::ECallForwardingStatusNotRegistered;
+ iCFList->AddEntryL(extraEntry);
+ }
+ //some services defined in table
+ else
+ {
+ for (TInt m=1;m<7;m++)
+ {
+ if (!serviceArray[m])
+ {
+ extraEntry.iServiceGroup=static_cast<RMobilePhone::TMobileService>(m);
+ extraEntry.iStatus=RMobilePhone::ECallForwardingStatusNotRegistered;
+ iCFList->AddEntryL(extraEntry);
+ }
+ }//end for
+ }//end else
+ }//end if
+ }//end for
+
+ CleanupStack::PopAndDestroy(&serviceArray); //Destroying serviceArray to free the memory
+ }
+
+TInt CSimCallForwarding::GetIdentityServiceStatus(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhoneIdService* aService, RMobilePhone::TMobilePhoneIdServiceStatus* aStatus)
+ /**
+ Gets the status of the identity services
+ @param aReqHandle handle to the request
+ @param aService service that the client is interested in
+ @param aStatus of the identity service
+ */
+ {
+ RMobilePhone::TMobilePhoneIdServiceStatus status;
+ status = RMobilePhone::EIdServiceUnknown;
+ TInt count = iIdentityServiceStatus->Count();
+ for(TInt i=0; i<count; i++)
+ {
+ if(iIdentityServiceStatus->At(i).iService == *aService)
+ {
+ status = iIdentityServiceStatus->At(i).iStatus;
+ break;
+ }
+ }
+ *aStatus = status;
+ iPhone->ReqCompleted(aReqHandle, KErrNone);
+ return KErrNone;
+ }
+
+TInt CSimCallForwarding::GetIdentityServiceStatusCancel(const TTsyReqHandle aReqHandle)
+ /**
+ Cancels the request to get the status of the identity services
+ @param aReqHandle hadle to the request
+ */
+ {
+ iPhone->ReqCompleted(aReqHandle,KErrCancel);
+ return KErrNone;
+ }
+
+TInt CSimCallForwarding::NotifyCallForwardingStatusChange(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhoneCFCondition* aCF)
+ /**
+ Requests to be notified of call forwarding status change
+ @param aReqHandle handle to the request
+ @param aCF condition for which the client wants to be notified
+ */
+ {
+ __ASSERT_ALWAYS(!iCFNotification.iCFChangeInfoNotificationPending,SimPanic(ENotificationReqAlreadyOutstanding));
+
+ iCFNotification.iCFChangeInfoNotificationPending=ETrue;
+ iCFNotification.iCFChangeInfoReqHandle=aReqHandle;
+ iCFNotification.iCurrentCFCondition=aCF;
+ LOGCALL1("Finished CSimCallForwarding::NotifyCallForwardingStatusChange");
+ return KErrNone;
+ }
+
+TInt CSimCallForwarding::NotifyCallForwardingStatusChangeCancel(const TTsyReqHandle aReqHandle)
+ /**
+ Cancels the request to be notified of call forwarding status change
+ @param aReqHandle handle to the request
+ */
+ {
+ if(iCFNotification.iCFChangeInfoNotificationPending)
+ {
+ iCFNotification.iCFChangeInfoNotificationPending=EFalse;
+ iPhone->ReqCompleted(aReqHandle,KErrCancel);
+ }
+ return KErrNone;
+ }
+
+TInt CSimCallForwarding::SetCallForwardingStatus(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhoneCFCondition* aCF, RMobilePhone::TMobilePhoneCFChangeV1* aInfo)
+ /**
+ Sets the status of call forwarding
+ @param aReqHandle handle to the request
+ @param aCF condition for which the client wants to set the status
+ @param aInfo value of Call forwarding to set
+ */
+ {
+ TRAPD(err, UpdateCFListL(aCF,aInfo));
+ if ( err != KErrNone )
+ {
+ iPhone->ReqCompleted(aReqHandle,err);
+ return KErrNone;
+ }
+
+ if(iCFNotification.iCFChangeInfoNotificationPending)
+ {
+ *(iCFNotification.iCurrentCFCondition)=*aCF;
+ iCFNotification.iCFChangeInfoNotificationPending=EFalse;
+ iPhone->ReqCompleted(iCFNotification.iCFChangeInfoReqHandle,KErrNone);
+ }
+
+ iPhone->ReqCompleted(aReqHandle,err);
+ LOGCALL1("Finished CSimCallForwarding::SetCallForwardingStatus");
+ return KErrNone;
+ }
+
+TInt CSimCallForwarding::SetCallForwardingStatusCancel(const TTsyReqHandle aReqHandle)
+ /**
+ Cancels the request to set the status of call forwarding
+ @param aReqHandle handle to the request
+ */
+ {
+ iPhone->ReqCompleted(aReqHandle,KErrCancel);
+ return KErrNone;
+ }
+
+
+TInt CSimCallForwarding::GetCallForwardingStatusPhase1(const TTsyReqHandle aTsyReqHandle,
+ CRetrieveMobilePhoneCFList::TGetCallForwardingRequest* aReqData,
+ TInt* aBufSize)
+ {
+ /**
+ 1st phase retrieval of the status of call forwarding
+ @param aTsyReqHandle handle to the request
+ @param aReqData contains details of the request
+ @param aBufSize size of the buffer the client needs to allocate for phase 2
+ */
+ LOGCALL1("CSimPhone::GetCallForwardingStatusPhase1");
+ TInt ret=KErrNone;
+
+ // for forwarding we cannot querry for all conditions;
+ // conditions - specific
+ // services - individual and all
+ if ((aReqData->iCondition==RMobilePhone::ECallForwardingUnspecified)
+ || (aReqData->iCondition==RMobilePhone::ECallForwardingAllCases)
+ || (aReqData->iCondition==RMobilePhone::ECallForwardingAllConditionalCases))
+ {
+ iPhone->ReqCompleted(aTsyReqHandle,KErrArgument);
+ }
+ else
+ {
+ TInt leaveCode=KErrNone;
+ TRAP(leaveCode, ret=ProcessGetCallForwardingStatusPhase1L(aTsyReqHandle, aReqData, aBufSize););
+ if (leaveCode != KErrNone)
+ iPhone->ReqCompleted(aTsyReqHandle,leaveCode);
+ }
+ LOGCALL1("CSimPhone::GetCallForwardingStatusPhase1");
+ return ret;
+ }
+
+TInt CSimCallForwarding::ProcessGetCallForwardingStatusPhase1L(const TTsyReqHandle aTsyReqHandle,
+ CRetrieveMobilePhoneCFList::TGetCallForwardingRequest* aReqData,
+ TInt* aBufSize)
+ {
+ /** Retrieve call forwarding status of each line from phone,
+ store each CF status response as a list entry,
+ stream the list and then return size of this buffer to client
+ @param aReqHandle Handle to the request
+ @param aReqData information about the request
+ @param aBufSize Size of the buffer the client has to allocate for the 2nd pahase
+ */
+
+ LOGCALL1("CSimPhone::ProcessGetCallForwardingStatusPhase1L");
+
+ CMobilePhoneCFList* list=CMobilePhoneCFList::NewL();
+ CleanupStack::PushL(list);
+
+ TInt cnt=0;//Only interested by entries with a particular condition
+ TInt maxNum=iCFList->Enumerate();
+ TBool isAllGroups = (aReqData->iServiceGroup == RMobilePhone::EAllServices);
+ for(TInt i=0;i<maxNum;i++)
+ {
+ RMobilePhone::TMobilePhoneCFInfoEntryV1 entry = iCFList->GetEntryL(i);
+
+ // Check that the data structure is supported by the simulated TSY version
+ TInt err = iPhone->CheckSimTsyVersion(entry);
+ if(err != KErrNone)
+ {
+ iPhone->ReqCompleted(aTsyReqHandle, err);
+ return KErrNone;
+ }
+
+ if((entry.iCondition == aReqData->iCondition)
+ &&(entry.iStatus != RMobilePhone::ECallForwardingStatusNotRegistered))
+ {
+ if ( !isAllGroups && (entry.iServiceGroup != aReqData->iServiceGroup))
+ {
+ continue;
+ }
+ list->AddEntryL(entry);
+ cnt++;
+ }
+ }
+ // Store the streamed list and the client ID
+ CListReadAllAttempt* read=CListReadAllAttempt::NewL(aReqData->iClient,aTsyReqHandle);
+ CleanupStack::PushL(read);
+
+ read->iListBuf = list->StoreLC();
+ CleanupStack::Pop(); // pop the CBufBase allocated by StoreLC
+
+ iGetCFStatus->AppendL(read);
+ CleanupStack::Pop(read); // pop the CListReadAllAttempt
+
+ // return the CBufBase’s size to client
+ *aBufSize=(read->iListBuf)->Size();
+
+ CleanupStack::PopAndDestroy(list); // pop&destroy list
+
+ // Complete first phase of list retrieval
+ iPhone->ReqCompleted(aTsyReqHandle,KErrNone);
+ LOGCALL1("CSimPhone::ProcessGetCallForwardingStatusPhase1L");
+ return KErrNone;
+ }
+
+TInt CSimCallForwarding::GetCallForwardingStatusPhase2(const TTsyReqHandle aTsyReqHandle,
+ RMobilePhone::TClientId* aClient, TDes8* aBuf)
+ /**
+ 2nd phase retrieval of the status of call forwarding
+ @param aTsyRqHandle handle to the request
+ @param aClient pointer to the client
+ @param aBuf buffer that contains the call forwarding list
+ */
+ {
+ LOGCALL1("CSimPhone::GetCallForwardingStatusPhase2");
+ CListReadAllAttempt* read=NULL;
+ // Find the get detected network attempt from this client
+ for (TInt i=0; i<iGetCFStatus->Count(); ++i)
+ {
+ read = iGetCFStatus->At(i);
+ if ((read->iClient.iSessionHandle==aClient->iSessionHandle) &&
+ (read->iClient.iSubSessionHandle==aClient->iSubSessionHandle))
+ {
+ TPtr8 bufPtr((read->iListBuf)->Ptr(0));
+ // Copy the streamed list to the client
+ aBuf->Copy(bufPtr);
+ delete read;
+ iGetCFStatus->Delete(i);
+ iPhone->ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+ }
+ // Should handle error case of not finding the matching client from read all phase 1
+ LOGCALL1("CSimPhone::GetCallForwardingStatusPhase2");
+ return KErrNotFound;
+ }
+
+
+TInt CSimCallForwarding::GetCallForwardingStatusCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ /**
+ Cancel the request to retrieve the status of call forwarding
+ @param aTsyReqHandle handle to the request
+ */
+ LOGCALL1("CSimPhone::GetCallForwardingStatusCancel");
+ iPhone->ReqCompleted(aTsyReqHandle,KErrNone);
+ // Remove the read all attempt from iGetCFStatus
+ CListReadAllAttempt* read=NULL;
+ for (TInt i=0; i<iGetCFStatus->Count(); ++i)
+ {
+ read = iGetCFStatus->At(i);
+ if (read->iReqHandle == aTsyReqHandle)
+ {
+ delete read;
+ iGetCFStatus->Delete(i);
+ break;
+ }
+ }
+ iPhone->ReqCompleted(aTsyReqHandle,KErrCancel);
+ LOGCALL1("CSimPhone::GetCallForwardingStatusCancel");
+ return KErrNone;
+ }
+
+void CSimCallForwarding::UpdateCFListL(RMobilePhone::TMobilePhoneCFCondition* aCF,
+ RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo )
+ {
+ /**
+ Modifies the status of call forwarding
+ @param aCF condition
+ @param aCFInfo details of the request
+ */
+ User::LeaveIfNull(aCF);
+ User::LeaveIfNull(aCFInfo);
+
+ if (*aCF == RMobilePhone::ECallForwardingUnspecified)
+ {
+ // not supported - tell user it is a wrong argument
+ User::Leave(KErrArgument);
+ }
+
+ if ((*aCF == RMobilePhone::ECallForwardingAllCases)
+ ||(*aCF == RMobilePhone::ECallForwardingAllConditionalCases))
+ {
+ // not supported - tell user it is a wrong argument
+ User::Leave(KErrNotSupported);
+ }
+
+ switch (aCFInfo->iAction)
+ {
+ case RMobilePhone::EServiceActionRegister:
+ RegisterL(aCF, aCFInfo);
+ break;
+
+ case RMobilePhone::EServiceActionActivate:
+ ActivateL(aCF, aCFInfo);
+ break;
+
+ case RMobilePhone::EServiceActionInvoke:
+ // currently not supported
+ // tell user it is a wrong argument
+ User::Leave(KErrArgument);
+ break;
+
+ case RMobilePhone::EServiceActionDeactivate:
+ DeactivateL(aCF, aCFInfo);
+ break;
+
+ case RMobilePhone::EServiceActionErase:
+ EraseL(aCF, aCFInfo);
+ break;
+
+ case RMobilePhone::EServiceActionUnspecified:
+ default:
+ // not supported - tell user it is a wrong argument
+ User::Leave(KErrArgument);
+ break;
+ }
+ }
+
+
+inline void SplitOneCFEntryIntoSeparateGroupsL(CMobilePhoneCFList* aCFList,
+ RMobilePhone::TMobilePhoneCFInfoEntryV1& aOrigEntry,
+ RMobilePhone::TMobileService aExceptServiceGroup)
+ {
+ /*
+ Splits one entry valid for all basic service groups into individual entries
+ and places them into a CMobilePhoneCFList. This excludes one service group.
+ @param aCBList The list to which to store the entries
+ @param aOrigEntry The original entry; details of which should be passed to individual group entries
+ @param aExceptServiceGroup The group which has to be avoided
+ */
+ // we have to split the entry into entries
+ // per group with the same condition; excluding the specified service group
+ RMobilePhone::TMobilePhoneCFInfoEntryV1 anotherEntry(aOrigEntry);
+
+ RMobilePhone::TMobileService service;
+
+ for (TInt i = KMobServiceIndxStart;i <= KMobServiceIndxEnd;i++)
+ {
+ service=static_cast<RMobilePhone::TMobileService>(i);
+
+ if( service != aExceptServiceGroup )
+ {
+ anotherEntry.iServiceGroup=service;
+ aCFList->AddEntryL(anotherEntry);
+ }
+ }//end for (another)
+ }
+
+
+void CSimCallForwarding::UpdateCFQuiescentConditionL(TBool aActivate,
+ RMobilePhone::TMobilePhoneCFCondition aCF)
+ {
+ // only the Call Forward Unconditional can alter any other CF condition
+ if(aCF == RMobilePhone::ECallForwardingUnconditional)
+ {
+ TBool cFBChangeRequired = EFalse;
+
+ RMobilePhone::TMobilePhoneCFInfoEntryV1 theEntry;
+
+ const TInt count = iCFList->Enumerate();
+
+ // look for any instances of the ECallForwardingBusy
+ for (TInt indx=0; indx < count; indx++)
+ {
+ theEntry = iCFList->GetEntryL(indx);
+
+ if(theEntry.iCondition == RMobilePhone::ECallForwardingBusy &&
+ (theEntry.iStatus == RMobilePhone::ECallForwardingStatusActive ||
+ theEntry.iStatus == RMobilePhone::ECallForwardingStatusQuiescent))
+ {
+ cFBChangeRequired = ETrue;
+ }
+ }
+
+ if(cFBChangeRequired)
+ {
+ // retain prev version of the list in local variable and in Cleanup stack
+ CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL();
+ CleanupStack::PushL(thePrevCFList);
+
+ // copy existing data into the temp storage
+ for (TInt indx=0; indx < count; indx++)
+ {
+ thePrevCFList->AddEntryL(iCFList->GetEntryL(indx));
+ }
+
+ delete iCFList;
+ iCFList = NULL;
+
+ // create a new version and hold it in the class member
+ iCFList = CMobilePhoneCFList::NewL();
+
+ // get a hold of it in a local variable
+ CMobilePhoneCFList* theNewCFList = iCFList;
+
+ for(TInt indx=0; indx < count; indx++)
+ {
+ theEntry = thePrevCFList->GetEntryL(indx);
+
+ if(theEntry.iCondition == RMobilePhone::ECallForwardingBusy)
+ {
+ if(aActivate)
+ {
+ if(theEntry.iStatus == RMobilePhone::ECallForwardingStatusActive)
+ {
+ theEntry.iStatus = RMobilePhone::ECallForwardingStatusQuiescent;
+ }
+ }
+ else
+ {
+ if(theEntry.iStatus == RMobilePhone::ECallForwardingStatusQuiescent)
+ {
+ theEntry.iStatus = RMobilePhone::ECallForwardingStatusActive;
+ }
+ }
+ }
+ theNewCFList->AddEntryL(theEntry);
+ }
+
+ // now delete the old memory
+ CleanupStack::PopAndDestroy(thePrevCFList);
+ }
+ }
+ }
+
+void CSimCallForwarding::ActivateL(RMobilePhone::TMobilePhoneCFCondition* aCF,
+ RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo )
+ {
+ // NOTE: An assumption is made that the calling method has checked the parameters
+ // are not NULL.
+ RMobilePhone::TMobilePhoneCFInfoEntryV1 theNewEntry;
+
+ theNewEntry.iCondition = *aCF;
+ theNewEntry.iServiceGroup = aCFInfo->iServiceGroup;
+ theNewEntry.iStatus= RMobilePhone::ECallForwardingStatusNotActive;
+ theNewEntry.iNumber = aCFInfo->iNumber;
+
+ if (*aCF == RMobilePhone::ECallForwardingNoReply)
+ {
+ theNewEntry.iTimeout = aCFInfo->iTimeout;
+ }
+ else
+ {
+ theNewEntry.iTimeout = KInvalidTimeout;
+ }
+
+
+ // retain prev version of the list in local variable and in Cleanup stack
+ CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL();
+ CleanupStack::PushL(thePrevCFList);
+
+ const TInt count = iCFList->Enumerate();
+
+ TBool CFUActive = EFalse;
+
+ // copy existing data into the temp storage
+ for (TInt indx = 0; indx < count; indx++)
+ {
+ thePrevCFList->AddEntryL(iCFList->GetEntryL(indx));
+
+ RMobilePhone::TMobilePhoneCFInfoEntryV1 copyEntry = iCFList->GetEntryL(indx);
+
+ if(copyEntry.iCondition == RMobilePhone::ECallForwardingUnconditional &&
+ copyEntry.iStatus == RMobilePhone::ECallForwardingStatusActive)
+ {
+ CFUActive = ETrue;
+ }
+ }
+
+ delete iCFList;
+ iCFList = NULL;
+
+ // create a new version and hold it in the class member
+ iCFList = CMobilePhoneCFList::NewL();
+
+ // get a hold of it in a local variable
+ CMobilePhoneCFList* theNewCFList = iCFList;
+
+ TBool callForwardActivated = EFalse;
+
+ RMobilePhone::TMobilePhoneCFInfoEntryV1 entry;
+
+ for (TInt i = 0; i < count; i++)
+ {
+ entry = thePrevCFList->GetEntryL(i);
+
+ if(theNewEntry.iCondition == entry.iCondition)
+ {
+ if(theNewEntry.iServiceGroup == entry.iServiceGroup)
+ {
+ // only activate service if previously in a not active state
+ if(entry.iStatus == RMobilePhone::ECallForwardingStatusNotActive)
+ {
+ if(entry.iCondition == RMobilePhone::ECallForwardingBusy && CFUActive != EFalse)
+ {
+ // do nothing, condition's service will not be activated as callforwarding
+ // unconditional is active
+ }
+ else
+ {
+ entry.iStatus = RMobilePhone::ECallForwardingStatusActive;
+ callForwardActivated = ETrue;
+ }
+ }
+ }
+ else if(entry.iServiceGroup == RMobilePhone::EAllServices)
+ {
+ if(entry.iStatus == RMobilePhone::ECallForwardingStatusNotActive)
+ {
+ SplitOneCFEntryIntoSeparateGroupsL(theNewCFList,
+ entry,
+ theNewEntry.iServiceGroup);
+
+ callForwardActivated = ETrue;
+ entry = theNewEntry;
+ }
+ }
+ }
+
+ theNewCFList->AddEntryL(entry);
+ }
+
+ if(callForwardActivated)
+ {
+ // only need to check quiescent status if an activation has occurred
+ UpdateCFQuiescentConditionL(ETrue, theNewEntry.iCondition);
+ }
+
+ CleanupStack::PopAndDestroy(thePrevCFList);
+ }
+
+void CSimCallForwarding::RegisterL(RMobilePhone::TMobilePhoneCFCondition* aCF, RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo)
+ {
+ TInt count = iCFList->Enumerate();
+ RMobilePhone::TMobilePhoneCFInfoEntryV1 theNewEntry;
+
+ theNewEntry.iCondition = *aCF;
+ theNewEntry.iServiceGroup = aCFInfo->iServiceGroup;
+ theNewEntry.iStatus= RMobilePhone::ECallForwardingStatusNotActive;
+
+ theNewEntry.iNumber = aCFInfo->iNumber;
+ if (*aCF == RMobilePhone::ECallForwardingNoReply)
+ {
+ theNewEntry.iTimeout = aCFInfo->iTimeout;
+ }
+ else
+ {
+ theNewEntry.iTimeout = KInvalidTimeout;
+ }
+
+ // retain prev version of the list in local variable and in Cleanup stack
+ CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL();
+ CleanupStack::PushL(thePrevCFList);
+ // copy existing data into the temp storage
+ for (TInt indx=0; indx<count; indx++)
+ {
+ thePrevCFList->AddEntryL(iCFList->GetEntryL(indx));
+ }
+ delete iCFList;
+ iCFList = NULL;
+ // create a new version and hold it in the class member
+ iCFList = CMobilePhoneCFList::NewL();
+ // get a hold of it in a local variable
+ CMobilePhoneCFList* theNewCFList = iCFList;
+
+ if (theNewEntry.iServiceGroup==RMobilePhone::EAllServices)
+ {
+ //nothing for all conds
+
+ //action is to Regiser (and activate)AllServices with a particular condition;
+ //Only copy entries with a different condition
+ //entries with same condition should not be copied as they will
+ //be represented by 1 with allservices
+ for (TInt i = 0; i<count; i++)
+ {
+ RMobilePhone::TMobilePhoneCFInfoEntryV1 entry = thePrevCFList->GetEntryL(i);
+
+ if (entry.iCondition != theNewEntry.iCondition)
+ // check if the existing entry is encompassed by the new one
+ theNewCFList->AddEntryL(entry);
+ }
+ theNewCFList->AddEntryL(theNewEntry);
+ }
+ else
+ {
+ //ActivateOne;
+ for (TInt i = 0; i<count; i++)
+ {
+ RMobilePhone::TMobilePhoneCFInfoEntryV1 entry = thePrevCFList->GetEntryL(i);
+
+ if (theNewEntry.iCondition==entry.iCondition
+ && entry.iServiceGroup==theNewEntry.iServiceGroup)
+ {
+ theNewCFList->AddEntryL(theNewEntry);
+ continue;
+ }
+ if (entry.iCondition != theNewEntry.iCondition
+ || (entry.iCondition == theNewEntry.iCondition
+ && entry.iServiceGroup != theNewEntry.iServiceGroup
+ && entry.iServiceGroup != RMobilePhone::EAllServices))
+ {
+ theNewCFList->AddEntryL(entry);
+ continue;
+ }
+
+ if(theNewEntry.iCondition==entry.iCondition
+ && entry.iServiceGroup==RMobilePhone::EAllServices)
+ {
+
+ SplitOneCFEntryIntoSeparateGroupsL(
+ theNewCFList,
+ entry,
+ theNewEntry.iServiceGroup
+ );
+
+ theNewCFList->AddEntryL(theNewEntry);
+ }//end if
+ }//end for
+ }//end else
+ // now delete the old memory
+ CleanupStack::PopAndDestroy(thePrevCFList);
+ }
+
+void CSimCallForwarding::DeactivateL(RMobilePhone::TMobilePhoneCFCondition* aCF,
+ RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo )
+ {
+ // NOTE: An assumption is made that the calling method has checked the parameters
+ // are not NULL.
+
+ RMobilePhone::TMobilePhoneCFInfoEntryV1 theNewEntry;
+
+ theNewEntry.iCondition = *aCF;
+ theNewEntry.iServiceGroup = aCFInfo->iServiceGroup;
+ theNewEntry.iStatus= RMobilePhone::ECallForwardingStatusNotActive;
+
+ // retain prev version of the list in local variable and in Cleanup stack
+ CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL();
+ CleanupStack::PushL(thePrevCFList);
+
+ const TInt count = iCFList->Enumerate();
+
+ // copy existing data into the temp storage
+ for (TInt indx = 0; indx < count; indx++)
+ {
+ thePrevCFList->AddEntryL(iCFList->GetEntryL(indx));
+ }
+
+ delete iCFList;
+ iCFList = NULL;
+
+ // create a new version and hold it in the class member
+ iCFList = CMobilePhoneCFList::NewL();
+
+ // get a hold of it in a local variable
+ CMobilePhoneCFList* theNewCFList = iCFList;
+
+ TBool callForwardDeactivated = EFalse;
+
+ RMobilePhone::TMobilePhoneCFInfoEntryV1 entry;
+
+ //Deactivate will deactivate active entries
+ for (TInt indx = 0; indx < count; indx++)
+ {
+ entry = thePrevCFList->GetEntryL(indx);
+
+ if(entry.iCondition == theNewEntry.iCondition)
+ {
+ if(entry.iServiceGroup == theNewEntry.iServiceGroup)
+ {
+ if(entry.iStatus == RMobilePhone::ECallForwardingStatusActive)
+ {
+ entry.iStatus = RMobilePhone::ECallForwardingStatusNotActive;
+ callForwardDeactivated = ETrue;
+ }
+ }
+ else if(entry.iServiceGroup == RMobilePhone::EAllServices)
+ {
+ if(entry.iStatus == RMobilePhone::ECallForwardingStatusActive)
+ {
+ SplitOneCFEntryIntoSeparateGroupsL(theNewCFList,
+ entry,
+ theNewEntry.iServiceGroup);
+
+ entry = theNewEntry;
+ callForwardDeactivated = ETrue;
+ }
+ }
+ }
+
+ theNewCFList->AddEntryL(entry);
+ }//end for
+
+ // this method will check if any de-activation has caused another Condition to become
+ // cleared of the quiescent state
+ if(callForwardDeactivated)
+ {
+ // pass a FALSE to the function to notify of a service de-activation
+ UpdateCFQuiescentConditionL(EFalse, theNewEntry.iCondition);
+ }
+
+ // now delete the old memory
+ CleanupStack::PopAndDestroy(thePrevCFList);
+ }
+
+void CSimCallForwarding::EraseL(RMobilePhone::TMobilePhoneCFCondition* aCF,
+ RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo )
+ {
+ // NOTE: An assumption is made that the calling method has checked the parameters
+ // are not NULL.
+
+ RMobilePhone::TMobilePhoneCFInfoEntryV1 theNewEntry;
+
+ theNewEntry.iCondition = *aCF;
+ theNewEntry.iServiceGroup = aCFInfo->iServiceGroup;
+ theNewEntry.iNumber.iTelNumber.Copy(KEmptyString);
+ theNewEntry.iTimeout = KErrNotFound;
+ theNewEntry.iStatus = RMobilePhone::ECallForwardingStatusNotRegistered;
+
+ // retain prev version of the list in local variable and in Cleanup stack
+ CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL();
+ CleanupStack::PushL(thePrevCFList);
+
+ const TInt count = iCFList->Enumerate();
+
+ // copy existing data into the temp storage
+ for (TInt indx = 0; indx < count; indx++)
+ {
+ thePrevCFList->AddEntryL(iCFList->GetEntryL(indx));
+ }
+
+ delete iCFList;
+ iCFList = NULL;
+
+ // create a new version and hold it in the class member
+ iCFList = CMobilePhoneCFList::NewL();
+
+ // get a hold of it in a local variable
+ CMobilePhoneCFList* theNewCFList = iCFList;
+
+ RMobilePhone::TMobilePhoneCFInfoEntryV1 entry;
+
+ for(TInt i = 0; i < count; i++)
+ {
+ entry = thePrevCFList->GetEntryL(i);
+
+ if(entry.iCondition == theNewEntry.iCondition)
+ {
+ if(entry.iServiceGroup == theNewEntry.iServiceGroup)
+ {
+ if(entry.iStatus == RMobilePhone::ECallForwardingStatusNotActive)
+ {
+ entry = theNewEntry;
+ }
+ }
+ else if(entry.iServiceGroup == RMobilePhone::EAllServices)
+ {
+ if(entry.iStatus == RMobilePhone::ECallForwardingStatusActive)
+ {
+ SplitOneCFEntryIntoSeparateGroupsL(theNewCFList,
+ entry,
+ theNewEntry.iServiceGroup);
+
+ entry = theNewEntry;
+ }
+ }
+ }
+ theNewCFList->AddEntryL(entry);
+ }
+
+ // now delete the old memory
+ CleanupStack::PopAndDestroy(thePrevCFList);
+ }
+
+const CTestConfigSection* CSimCallForwarding::CfgFile()
+/**
+ * Returns a pointer to the current configuration file section.
+ *
+ * @return CTestConfigSection A pointer to the current configuration file data section.
+ */
+ {
+ return iPhone->CfgFile();
+ }
+
+