--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyserverplugins/simtsy/src/CSimCallWaiting.cpp Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,553 @@
+// 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
+// CallWaiting status and registration information.
+//
+//
+
+/**
+ @file
+*/
+
+#include <testconfigfileparser.h>
+#include "CSimCallWaiting.h"
+#include "CSimPhone.h"
+#include "Simlog.h"
+
+const TInt KMobServiceIndxStart = 1;
+const TInt KMobServiceIndxEnd = 5;
+
+
+CSimCallWaiting* CSimCallWaiting::NewL(CSimPhone* aPhone)
+/**
+ * Standard two-phase constructor.
+ * @param aPhone The parent phone object.
+ * @return CSimCallWaiting The new call waiting class.
+ */
+ {
+ CSimCallWaiting* self=new(ELeave) CSimCallWaiting(aPhone);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+CSimCallWaiting::CSimCallWaiting(CSimPhone* aPhone)
+ : iPhone(aPhone)
+/**
+ * Trivial first phase construction.
+ * @param aPhone The parent phone object.
+ */
+ {
+ }
+
+void CSimCallWaiting::ConstructL()
+/**
+ Second phase of 2-Phase Constructor
+ Retrieves all the Call waiting related tags from the config file
+*/
+ {
+ LOGCALL1("Starting to parse Call waiting config parameters...");
+
+ iGetCWStatus = new(ELeave) CArrayPtrFlat<CListReadAllAttempt>(1);
+ FindAndCreateCWListL();
+ LOGCALL1("...Finished parsing Call waiting config parameters...");
+ }
+
+void CSimCallWaiting::FindAndCreateCWListL()
+{
+/**
+ Retrieves all the Call waiting tags that define the
+ original status of Call waiting from the config file
+*/
+ LOGCALL1("CSimPhone::FindAndCreateCWListL");
+ RMobilePhone::TMobilePhoneCWInfoEntryV1 entry;
+
+ iCWList = CMobilePhoneCWList::NewL();
+ TInt count=CfgFile()->ItemCount(KCWList);
+ const CTestConfigItem* item=NULL;
+ TInt ret=KErrNone;
+
+ LOGCALL1("Starting to Load and Parse CWList Config parameters");
+ TInt i;
+ for(i=0;i<count;i++)
+ {
+ item=CfgFile()->Item(KCWList,i);
+ if(!item)
+ break;
+
+ TInt serviceGroup, status;
+
+ ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,serviceGroup);
+ if(ret!=KErrNone)
+ {
+ LOGPARSERR("serviceGroup",ret,0,&KCWList);
+ continue;
+ }
+
+ ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,status);
+ if(ret!=KErrNone)
+ {
+ LOGPARSERR("status",ret,1,&KCWList);
+ continue;
+ }
+
+ entry.iServiceGroup=(RMobilePhone::TMobileService)serviceGroup;
+ entry.iStatus=(RMobilePhone::TMobilePhoneCWStatus)status;
+
+ iCWList->AddEntryL(entry);
+ }
+ }
+
+CSimCallWaiting::~CSimCallWaiting()
+ {
+ delete iCWList;
+ if (iGetCWStatus)
+ iGetCWStatus->ResetAndDestroy();
+ delete iGetCWStatus;
+ }
+
+TInt CSimCallWaiting::ExtFuncL(const TTsyReqHandle aReqHandle,const TInt aIpc, const TDataPackage& aPckg)
+ {
+ /**
+ Handles the phone based requests that apply to call waiting
+ @param aReqHandle Handle to the request
+ @param aIpc request identifier
+ @param aPckg contains additional information for the requests
+ */
+
+ 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 EMobilePhoneSetCallWaitingStatus:
+ return SetCallWaitingStatusL(aReqHandle,
+ REINTERPRET_CAST(RMobilePhone::TMobileService*, dataPtr),
+ REINTERPRET_CAST(RMobilePhone::TMobilePhoneServiceAction*,dataPtr2));
+ case EMobilePhoneNotifyCallWaitingStatusChange:
+ return NotifyCallWaitingStatusChange(aReqHandle, REINTERPRET_CAST(RMobilePhone::TMobilePhoneCWInfoEntryV1*, dataPtr));
+ case EMobilePhoneGetWaitingStatusPhase1:
+ return GetCallWaitingStatusPhase1(aReqHandle,
+ REINTERPRET_CAST(CRetrieveMobilePhoneCWList::TGetCallWaitingRequest*, dataPtr),
+ REINTERPRET_CAST(TInt*, dataPtr2));
+ case EMobilePhoneGetWaitingStatusPhase2:
+ return GetCallWaitingStatusPhase2(aReqHandle,
+ REINTERPRET_CAST(RMobilePhone::TClientId*, dataPtr), aPckg.Des2n());
+ default:
+ break;
+ }
+ return KErrNotSupported;
+ }
+
+TInt CSimCallWaiting::CancelService(const TInt aIpc, const TTsyReqHandle aReqHandle)
+ {
+ /**
+ Cancels any phone based request regarding call waiting
+ @param aIpc the IPC to cancel
+ @param aReqHandle handle to the request
+ */
+ switch(aIpc)
+ {
+ case EMobilePhoneSetCallWaitingStatus:
+ return SetCallWaitingStatusCancel(aReqHandle);
+ case EMobilePhoneNotifyCallWaitingStatusChange:
+ return NotifyCallWaitingStatusChangeCancel(aReqHandle);
+ default:
+ break;
+ }
+ return KErrNone;
+ }
+
+TInt CSimCallWaiting::NotifyCallWaitingStatusChange(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhoneCWInfoEntryV1* aCW)
+ {
+ /**
+ Requests to be notified of change in the Call Waiting status
+ @param aReqHandle Handle to the request
+ @param aCW contains the service group and new status that has changed
+ */
+ __ASSERT_ALWAYS(!iCWNotification.iCWChangeInfoNotificationPending,SimPanic(ENotificationReqAlreadyOutstanding));
+ iCWNotification.iCWChangeInfoNotificationPending=ETrue;
+ iCWNotification.iCWChangeInfoReqHandle=aReqHandle;
+ iCWNotification.iCWInfo=aCW;
+ LOGCALL1("Finished CSimCallWaiting::NotifyCallWaitingStatusChange");
+ return KErrNone;
+ }
+
+TInt CSimCallWaiting::NotifyCallWaitingStatusChangeCancel(const TTsyReqHandle aReqHandle)
+ {
+ /**
+ Cancels request to be notified of call Waiting status change
+ @param aReqHandle Handle to the request
+ */
+ if(iCWNotification.iCWChangeInfoNotificationPending)
+ {
+ iCWNotification.iCWChangeInfoNotificationPending=EFalse;
+ iPhone->ReqCompleted(aReqHandle,KErrCancel);
+ }
+ return KErrNone;
+ }
+
+TInt CSimCallWaiting::SetCallWaitingStatusL(const TTsyReqHandle aReqHandle, RMobilePhone::TMobileService* aService, RMobilePhone::TMobilePhoneServiceAction* aAction)
+ {
+ /**
+ Sets the status for call Waiting
+ @param aReqHandle Handle to the request
+ @param aCB condition for which the client whishes to set the call Waiting status
+ @param aInfo additional parameters to set the call Waiting status
+ */
+
+ // make sure we know that the operation concluded sucessfully
+ TRAPD(ret,UpdateCWListL(aService,aAction));
+ if ( ret != KErrNone )
+ {
+ iPhone->ReqCompleted(aReqHandle,ret);
+ }
+
+ // otherwise proceed and notify all went well
+ // Notify change
+ if (iCWNotification.iCWChangeInfoNotificationPending)
+ {
+
+ (iCWNotification.iCWInfo->iServiceGroup)=*aService;
+
+ switch (*aAction)
+ {
+ case RMobilePhone::EServiceActionRegister:
+ case RMobilePhone::EServiceActionActivate:
+ iCWNotification.iCWInfo->iStatus= RMobilePhone::ECallWaitingStatusActive;
+ break;
+ case RMobilePhone::EServiceActionDeactivate:
+ case RMobilePhone::EServiceActionErase:
+ iCWNotification.iCWInfo->iStatus= RMobilePhone::ECallWaitingStatusNotActive;
+ break;
+ case RMobilePhone::EServiceActionUnspecified:
+ default:
+ iCWNotification.iCWInfo->iStatus= RMobilePhone::ECallWaitingStatusUnknown;
+ // no sense doing any further operation - leave
+ User::Leave( KErrArgument );
+ break;
+ }
+
+ iCWNotification.iCWChangeInfoNotificationPending=EFalse;
+ iPhone->ReqCompleted(iCWNotification.iCWChangeInfoReqHandle,KErrNone);
+ }
+
+ iPhone->ReqCompleted(aReqHandle,KErrNone);
+
+ return KErrNone;
+ }
+
+TInt CSimCallWaiting::SetCallWaitingStatusCancel(const TTsyReqHandle aReqHandle)
+ {
+ /**
+ Cancels the request to sets the status for call waiting
+ @param aReqHandle Handle to the request
+ */
+
+ iPhone->ReqCompleted(aReqHandle,KErrCancel);
+ return KErrNone;
+ }
+
+
+
+const CTestConfigSection* CSimCallWaiting::CfgFile()
+/**
+ * Returns a pointer to the current configuration file section.
+ *
+ * @return CTestConfigSection A pointer to the current configuration file data section.
+ */
+ {
+ return iPhone->CfgFile();
+ }
+
+TInt CSimCallWaiting::GetCallWaitingStatusPhase1(const TTsyReqHandle aTsyReqHandle,
+ CRetrieveMobilePhoneCWList::TGetCallWaitingRequest* aReqData,
+ TInt* aBufSize)
+ {
+ /**
+ 1st phase retrieval of the the call waiting status list
+ @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("CSimCallWaiting::GetCalWaitingStatusPhase1");
+
+ TInt ret=KErrNone;
+ TInt leaveCode=KErrNone;
+ TRAP(leaveCode, ret=ProcessGetCallWaitingStatusPhase1L(aTsyReqHandle, aReqData, aBufSize););
+ if (leaveCode != KErrNone)
+ iPhone->ReqCompleted(aTsyReqHandle,leaveCode);
+
+ LOGCALL1("CSimCallWaiting::GetCalWaitingStatusPhase1");
+ return ret;
+ }
+
+TInt CSimCallWaiting::ProcessGetCallWaitingStatusPhase1L(const TTsyReqHandle aTsyReqHandle,
+ CRetrieveMobilePhoneCWList::TGetCallWaitingRequest* aReqData,
+ TInt* aBufSize)
+ {
+ /** Retrieve call waiting status of each line from phone,
+ store each CB 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("CSimCallWaiting::ProcessGetCallWaitingStatusPhase1L");
+
+ CMobilePhoneCWList* list=CMobilePhoneCWList::NewL();
+ CleanupStack::PushL(list);
+
+ TInt maxNum=iCWList->Enumerate();
+ //if testing all CB are non-active
+ // then we have to return a single entry EAllServices
+ if ( maxNum )
+ {
+ for(TInt i=0;i<maxNum;i++)
+ {
+ list->AddEntryL(iCWList->GetEntryL(i));
+ }
+ }
+ else
+ {
+ // if the list is empty and the querry general then we have to return general info
+ RMobilePhone::TMobilePhoneCWInfoEntryV1 entry;
+
+ // 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;
+ }
+
+ entry.iServiceGroup = RMobilePhone::EAllServices;
+ entry.iStatus = RMobilePhone::ECallWaitingStatusNotActive;
+ list->AddEntryL( entry );
+ }
+
+ // 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
+
+ iGetCWStatus->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("CSimCallWaiting::ProcessGetCallWaitingStatusPhase1L");
+ return KErrNone;
+ }
+
+TInt CSimCallWaiting::GetCallWaitingStatusPhase2(const TTsyReqHandle aTsyReqHandle,
+ RMobilePhone::TClientId* aClient, TDes8* aBuf)
+ {
+ /**
+ 2nd phase retrieval of the the call waiting status list
+ @param aReqHandle Handle to the request
+ @param aClient Ponter to the client
+ @param aBuf Buffer containiong the call waiting status list
+ */
+ LOGCALL1("CSimCallWaiting::GetCallWaitingStatusPhase2");
+ CListReadAllAttempt* read=NULL;
+ // Find the get detected network attempt from this client
+ for (TInt i=0; i<iGetCWStatus->Count(); ++i)
+ {
+ read = iGetCWStatus->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;
+ iGetCWStatus->Delete(i);
+ iPhone->ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+ }
+ // Should handle error case of not finding the matching client from read all phase 1
+ LOGCALL1("CSimCallWaiting::GetCallWaitingStatusPhase2");
+ return KErrNotFound;
+ }
+
+TInt CSimCallWaiting::GetCallWaitingStatusCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ /*
+ Cancels a Request to retrieve the call waiting status list
+ @param aReqHandle Handle to the request
+ */
+ LOGCALL1("CSimCallWaiting::GetCallWaitingStatusCancel");
+ iPhone->ReqCompleted(aTsyReqHandle,KErrNone);
+ // Remove the read all attempt from iGetCBStatus
+ CListReadAllAttempt* read=NULL;
+ for (TInt i=0; i<iGetCWStatus->Count(); ++i)
+ {
+ read = iGetCWStatus->At(i);
+ if (read->iReqHandle == aTsyReqHandle)
+ {
+ delete read;
+ iGetCWStatus->Delete(i);
+ break;
+ }
+ }
+ iPhone->ReqCompleted(aTsyReqHandle,KErrCancel);
+ LOGCALL1("CSimCallWaiting::GetCallWaitingStatusCancel");
+ return KErrNone;
+ }
+
+inline void SplitOneEntryIntoSeparateGroupsL(
+ CMobilePhoneCWList* aCWList,
+ RMobilePhone::TMobilePhoneCWInfoEntryV1 aOrigEntry,
+ RMobilePhone::TMobileService aExceptServiceGroup
+ )
+ {
+ /*
+ Splits one entry valid for all basic service groups into individual entries
+ and places them into a CMobilePhoneCBList. 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::TMobilePhoneCWInfoEntryV1 anotherEntry = aOrigEntry;
+
+ //anotherEntry.iCondition = aOrigEntry.iCondition;
+ //anotherEntry.iStatus = RMobilePhone::ECallBarringStatusActive;
+ RMobilePhone::TMobileService service;
+
+ for (TInt i=KMobServiceIndxStart; i<=KMobServiceIndxEnd;i++)
+ {
+ service=static_cast<RMobilePhone::TMobileService>(i);
+ if( service != aExceptServiceGroup )
+ {
+ anotherEntry.iServiceGroup=service;
+ aCWList->AddEntryL(anotherEntry);
+ }
+ }//end for (another)
+ }
+
+void CSimCallWaiting::UpdateCWListL(RMobilePhone::TMobileService* aServiceGroup, RMobilePhone::TMobilePhoneServiceAction* aAction )
+ {
+ /*
+ Updates the status of call waiting.
+ @param aServiceGroup service group to set
+ @param aAction ation to be performed
+ */
+
+ // no sense processing if either condition or change info are NULLS
+ User::LeaveIfNull(aServiceGroup);
+ User::LeaveIfNull(aAction);
+
+
+ //Lets do some work then
+ RMobilePhone::TMobilePhoneCWInfoEntryV1 theNewEntry;
+
+ theNewEntry.iServiceGroup = *aServiceGroup;
+
+ switch (*aAction)
+ {
+ case RMobilePhone::EServiceActionRegister:
+ case RMobilePhone::EServiceActionActivate:
+ theNewEntry.iStatus= RMobilePhone::ECallWaitingStatusActive;
+ break;
+ case RMobilePhone::EServiceActionDeactivate:
+ case RMobilePhone::EServiceActionErase:
+ theNewEntry.iStatus= RMobilePhone::ECallWaitingStatusNotActive;
+ break;
+ case RMobilePhone::EServiceActionUnspecified:
+ default:
+ theNewEntry.iStatus= RMobilePhone::ECallWaitingStatusUnknown;
+ // no sense doing any further operation - leave
+ User::Leave( KErrArgument );
+ break;
+ }
+
+ // retain prev version of the list in local variable and in Cleanup stack
+ CMobilePhoneCWList* thePrevCWList = CMobilePhoneCWList::NewL();
+ CleanupStack::PushL(thePrevCWList);
+ // copy existing data into the temp storage
+ for (TInt indx=0; indx<iCWList->Enumerate(); indx++)
+ {
+ thePrevCWList->AddEntryL(iCWList->GetEntryL(indx));
+ }
+ delete iCWList;
+ iCWList = NULL;
+
+ // create a new version and hold it in the class member
+ iCWList = CMobilePhoneCWList::NewL();
+ // get a hold of it in a local variable
+ CMobilePhoneCWList* theNewCWList = iCWList;
+ RMobilePhone::TMobilePhoneCWInfoEntryV1 entry;
+
+ TInt count = thePrevCWList->Enumerate();
+
+ if (theNewEntry.iStatus == RMobilePhone::ECallWaitingStatusActive)
+ {
+ if (theNewEntry.iServiceGroup==RMobilePhone::EAllServices)
+ {
+ theNewCWList->AddEntryL(theNewEntry);
+ }
+ else
+ {
+ for (TInt i = 0; i<count; i++)
+ {
+ entry = thePrevCWList->GetEntryL(i);
+ if(entry.iServiceGroup!=theNewEntry.iServiceGroup
+ && entry.iServiceGroup!=RMobilePhone::EAllServices)
+ theNewCWList->AddEntryL(entry);
+ }
+ theNewCWList->AddEntryL(theNewEntry);
+ }
+ }
+ else //deactivate
+ {
+ if (theNewEntry.iServiceGroup==RMobilePhone::EAllServices)
+ {
+ theNewCWList->AddEntryL(theNewEntry);
+ }
+ else
+ {
+ for (TInt i = 0; i<count; i++)
+ {
+ entry = thePrevCWList->GetEntryL(i);
+ if(entry.iServiceGroup==RMobilePhone::EAllServices)
+ {
+ //add to the list active entries for all servive groups but the one to be deactivated
+ SplitOneEntryIntoSeparateGroupsL(theNewCWList,entry, theNewEntry.iServiceGroup);
+ continue;
+ }
+ if(entry.iServiceGroup!=theNewEntry.iServiceGroup)
+ {
+ theNewCWList->AddEntryL(entry);
+ }
+ }
+ }
+
+ }
+ // now delete the old memory
+ CleanupStack::PopAndDestroy(thePrevCWList);
+ }
+