--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyserverplugins/simtsy/src/CSimCallForwarding.cpp Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +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::UpdateCFQuiescentCondition(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
+ UpdateCFQuiescentCondition(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
+ UpdateCFQuiescentCondition(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();
+ }
+
+