diff -r 6b1d113cdff3 -r 6638e7f4bd8f telephonyserverplugins/simtsy/src/CSimCallWaiting.cpp --- a/telephonyserverplugins/simtsy/src/CSimCallWaiting.cpp Mon May 03 13:37:20 2010 +0300 +++ b/telephonyserverplugins/simtsy/src/CSimCallWaiting.cpp Thu May 06 15:10:38 2010 +0100 @@ -1,553 +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 -#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(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;iItem(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;iAddEntryL(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; iCount(); ++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; iCount(); ++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(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; indxEnumerate(); 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; iGetEntryL(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; iGetEntryL(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); - } - +// 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 +#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(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;iItem(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;iAddEntryL(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; iCount(); ++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; iCount(); ++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(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; indxEnumerate(); 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; iGetEntryL(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; iGetEntryL(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); + } +