diff -r 6b1d113cdff3 -r 6638e7f4bd8f telephonyserverplugins/simtsy/src/CSimCallBarring.cpp --- a/telephonyserverplugins/simtsy/src/CSimCallBarring.cpp Mon May 03 13:37:20 2010 +0300 +++ b/telephonyserverplugins/simtsy/src/CSimCallBarring.cpp Thu May 06 15:10:38 2010 +0100 @@ -1,700 +1,700 @@ -// 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 -// callBarring status and registration information. -// -// - -/** - @file -*/ - -#include -#include "CSimCallBarring.h" -#include "CSimPhone.h" -#include "Simlog.h" - -// The Mobile Basic Service Groups used - originally were magic numbers from 1 to 6 incl; -const TInt KMobServiceIndxStart = 1; -const TInt KMobServiceIndxEnd = 6; - - -CSimCallBarring* CSimCallBarring::NewL(CSimPhone* aPhone) -/** - * Standard two-phase constructor. - * @param aPhone The parent phone object. - * @return CSimNetworkStatus The new network status class. - */ - { - CSimCallBarring* self=new(ELeave) CSimCallBarring(aPhone); - CleanupStack::PushL(self); - self->ConstructL(); - CleanupStack::Pop(); - return self; - } - -CSimCallBarring::CSimCallBarring(CSimPhone* aPhone) - : iPhone(aPhone) -/** - * Trivial first phase construction. - * @param aPhone The parent phone object. - */ - { - } - -void CSimCallBarring::ConstructL() -/** - Second phase of 2-Phase Constructor - Retrieves all the Call Barring related tags from the config file -*/ - { - LOGCALL1("Starting to parse Call Barring config parameters..."); - - iPassword.Copy(CfgFile()->ItemValue(KCBPassword,KCBDefaultPassword)); - - iGetCBStatus = new(ELeave) CArrayPtrFlat(1); - FindAndCreateCBListL(); - LOGCALL1("...Finished parsing Call Barring config parameters..."); - } - -void CSimCallBarring::FindAndCreateCBListL() -{ -/** - Retrieves all the Call barring tags that define the - original status of Call barring from the config file -*/ - LOGCALL1("CSimPhone::FindAndCreateCBListL"); - RMobilePhone::TMobilePhoneCBInfoEntryV1 entry; - - iCBList = CMobilePhoneCBList::NewL(); - TInt count=CfgFile()->ItemCount(KCBList); - const CTestConfigItem* item=NULL; - TInt ret=KErrNone; - - LOGCALL1("Starting to Load and Parse CBList Config parameters"); - TInt i; - for(i=0;iItem(KCBList,i); - if(!item) - break; - - TInt condition, serviceGroup, status; - ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,condition); - if(ret!=KErrNone) - { - LOGPARSERR("condition",ret,0,&KCBList); - continue; - } - ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,serviceGroup); - if(ret!=KErrNone) - { - LOGPARSERR("serviceGroup",ret,1,&KCBList); - continue; - } - - ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,status); - if(ret!=KErrNone) - { - LOGPARSERR("status",ret,2,&KCBList); - continue; - } - - entry.iCondition=(RMobilePhone::TMobilePhoneCBCondition)condition; - entry.iServiceGroup=(RMobilePhone::TMobileService)serviceGroup; - entry.iStatus=(RMobilePhone::TMobilePhoneCBStatus)status; - - iCBList->AddEntryL(entry); - } - } - -CSimCallBarring::~CSimCallBarring() - { - delete iCBList; - if (iGetCBStatus) - iGetCBStatus->ResetAndDestroy(); - delete iGetCBStatus; - } - -TInt CSimCallBarring::ExtFunc(const TTsyReqHandle aReqHandle,const TInt aIpc, const TDataPackage& aPckg) - { - /** - Handles the phone based requests that apply to call barring - @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 EMobilePhoneSetCallBarringStatus: - return SetCallBarringStatus(aReqHandle, - reinterpret_cast(dataPtr), - reinterpret_cast(dataPtr2)); - case EMobilePhoneSetCallBarringPassword: - return SetCallBarringPassword(aReqHandle,reinterpret_cast(dataPtr)); - case EMobilePhoneNotifyCallBarringStatusChange: - return NotifyCallBarringStatusChange(aReqHandle, reinterpret_cast(dataPtr)); - case EMobilePhoneGetBarringStatusPhase1: - return GetCallBarringStatusPhase1(aReqHandle, - REINTERPRET_CAST(CRetrieveMobilePhoneCBList::TGetCallBarringRequest*, dataPtr), - REINTERPRET_CAST(TInt*, dataPtr2)); - case EMobilePhoneGetBarringStatusPhase2: - return GetCallBarringStatusPhase2(aReqHandle, - REINTERPRET_CAST(RMobilePhone::TClientId*, dataPtr), aPckg.Des2n()); - default: - break; - } - return KErrNotSupported; - } - -TInt CSimCallBarring::CancelService(const TInt aIpc, const TTsyReqHandle aReqHandle) - { - /** - Cancels any phone based request regarding call barring - @param aIpc the IPC to cancel - @param aReqHandle handle to the request - */ - switch(aIpc) - { - case EMobilePhoneSetCallBarringStatus: - return SetCallBarringStatusCancel(aReqHandle); - case EMobilePhoneSetCallBarringPassword: - return SetCallBarringPasswordCancel(aReqHandle); - case EMobilePhoneNotifyCallBarringStatusChange: - return NotifyCallBarringStatusChangeCancel(aReqHandle); - default: - break; - } - return KErrNone; - } - -TInt CSimCallBarring::NotifyCallBarringStatusChange(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhoneCBCondition* aCB) - { - /** - Requests to be notified of change in the Call baring status - @param aReqHandle Handle to the request - @param aCB condition for which the client is interested in being notified - */ - __ASSERT_ALWAYS(!iCBNotification.iCBChangeInfoNotificationPending,SimPanic(ENotificationReqAlreadyOutstanding)); - iCBNotification.iCBChangeInfoNotificationPending=ETrue; - iCBNotification.iCBChangeInfoReqHandle=aReqHandle; - iCBNotification.iCurrentCBCondition=aCB; - LOGCALL1("Finished CSimCallBarring::NotifyCallBarringStatusChange"); - return KErrNone; - } - -TInt CSimCallBarring::NotifyCallBarringStatusChangeCancel(const TTsyReqHandle aReqHandle) - { - /** - Cancels request to be notified of call barring status change - @param aReqHandle Handle to the request - */ - if(iCBNotification.iCBChangeInfoNotificationPending) - { - iCBNotification.iCBChangeInfoNotificationPending=EFalse; - iPhone->ReqCompleted(aReqHandle,KErrCancel); - } - return KErrNone; - } - -TInt CSimCallBarring::SetCallBarringStatus(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhoneCBCondition* aCB, RMobilePhone::TMobilePhoneCBChangeV1* aInfo) - { - /** - Sets the status for call barring - @param aReqHandle Handle to the request - @param aCB condition for which the client whishes to set the call barring status - @param aInfo additional parameters to set the call barring status - */ - //Password does not correspond, return KErrAccessDenied .. is that right ? Not specified in SDK! - if (iPassword != aInfo->iPassword) - { - iPhone->ReqCompleted(aReqHandle,KErrAccessDenied); - return KErrNone; - } - - // make sure we know that the operation concluded sucessfully - TRAPD(ret,UpdateCBListL(aCB,aInfo)); - if ( ret != KErrNone ) - { - iPhone->ReqCompleted(aReqHandle,ret); - return KErrNone; - } - - // otherwise proceed and notify all went well - // Notify change - if (iCBNotification.iCBChangeInfoNotificationPending) - { - *(iCBNotification.iCurrentCBCondition)=*aCB; - iCBNotification.iCBChangeInfoNotificationPending=EFalse; - iPhone->ReqCompleted(iCBNotification.iCBChangeInfoReqHandle,KErrNone); - } - - iPhone->ReqCompleted(aReqHandle,KErrNone); - - return KErrNone; - } - -TInt CSimCallBarring::SetCallBarringStatusCancel(const TTsyReqHandle aReqHandle) - { - /** - Cancels the request to sets the status for call barring - @param aReqHandle Handle to the request - */ - - iPhone->ReqCompleted(aReqHandle,KErrCancel); - return KErrNone; - } - -TInt CSimCallBarring::SetCallBarringPassword(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhonePasswordChangeV1* aInfo) - { - /** - Sets the password that prevents the call barring status to be modified - @param aReqHandle Handle to the request - @param aInfo The old and new password - */ - if (iPassword == aInfo->iOldPassword) - { - iPassword = aInfo->iNewPassword; - iPhone->ReqCompleted(aReqHandle,KErrNone); - } - else - { - iPhone->ReqCompleted(aReqHandle,KErrAccessDenied); - } - return KErrNone; - } - -TInt CSimCallBarring::SetCallBarringPasswordCancel(const TTsyReqHandle aReqHandle) - { - /** - cancels a request to set the password that prevents the call barring status to be modified - @param aReqHandle Handle to the request - */ - iPhone->ReqCompleted(aReqHandle,KErrCancel); - return KErrNone; - } - - -const CTestConfigSection* CSimCallBarring::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 CSimCallBarring::GetCallBarringStatusPhase1(const TTsyReqHandle aTsyReqHandle, - CRetrieveMobilePhoneCBList::TGetCallBarringRequest* aReqData, - TInt* aBufSize) - { - /** - 1st phase retrieval of the the call barring 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("CSimPhone::GetCallBarringStatusPhase1"); - - TInt ret=KErrNone; - TInt leaveCode=KErrNone; - TRAP(leaveCode, ret=ProcessGetCallBarringStatusPhase1L(aTsyReqHandle, aReqData, aBufSize);); - if (leaveCode != KErrNone) - iPhone->ReqCompleted(aTsyReqHandle,leaveCode); - - LOGCALL1("CSimPhone::GetCallBarringStatusPhase1"); - return ret; - } - -TInt CSimCallBarring::ProcessGetCallBarringStatusPhase1L(const TTsyReqHandle aTsyReqHandle, - CRetrieveMobilePhoneCBList::TGetCallBarringRequest* aReqData, - TInt* aBufSize) - { - /** Retrieve call barring 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("CSimCallBarring::ProcessGetCallBarringStatusPhase1L"); - - CMobilePhoneCBList* list=CMobilePhoneCBList::NewL(); - CleanupStack::PushL(list); - - - TInt cnt=0;//Only interested by entries with a particular condition - TInt maxNum=iCBList->Enumerate(); - //if testing all conditions and all CB are non-active - // then we have to return a single entry EBarAllCases and EAllServices - if ( maxNum ) - { - for(TInt i=0;iGetEntryL(i).iCondition == aReqData->iCondition) - ||(aReqData->iCondition==RMobilePhone::EBarUnspecified)) - { - list->AddEntryL(iCBList->GetEntryL(i)); - cnt++; - } - } - } - else - { - // if the list is empty and the querry general then we have to return general info - if ( aReqData->iCondition == RMobilePhone::EBarUnspecified ) - { - RMobilePhone::TMobilePhoneCBInfoEntryV1 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.iCondition = RMobilePhone::EBarAllCases; - entry.iServiceGroup = RMobilePhone::EAllServices; - entry.iStatus = RMobilePhone::ECallBarringStatusNotActive; - 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 - - iGetCBStatus->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("CSimCallBarring::ProcessGetCallBarringStatusPhase1L"); - return KErrNone; - } - -TInt CSimCallBarring::GetCallBarringStatusPhase2(const TTsyReqHandle aTsyReqHandle, - RMobilePhone::TClientId* aClient, TDes8* aBuf) - { - /** - 2nd phase retrieval of the the call barring status list - @param aReqHandle Handle to the request - @param aClient Ponter to the client - @param aBuf Buffer containiong the call barring status list - */ - LOGCALL1("CSimCallBarring::GetCallBarringStatusPhase2"); - CListReadAllAttempt* read=NULL; - // Find the get detected network attempt from this client - for (TInt i=0; iCount(); ++i) - { - read = iGetCBStatus->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; - iGetCBStatus->Delete(i); - iPhone->ReqCompleted(aTsyReqHandle,KErrNone); - return KErrNone; - } - } - // Should handle error case of not finding the matching client from read all phase 1 - LOGCALL1("CSimCallBarring::GetCallBarringStatusPhase2"); - return KErrNotFound; - } - -TInt CSimCallBarring::GetCallBarringStatusCancel(const TTsyReqHandle aTsyReqHandle) - { - /* - Cancels a Request to retrieve the call barring status list - @param aReqHandle Handle to the request - */ - LOGCALL1("CSimCallBarring::GetCallBarringStatusCancel"); - iPhone->ReqCompleted(aTsyReqHandle,KErrNone); - // Remove the read all attempt from iGetCBStatus - CListReadAllAttempt* read=NULL; - for (TInt i=0; iCount(); ++i) - { - read = iGetCBStatus->At(i); - if (read->iReqHandle == aTsyReqHandle) - { - delete read; - iGetCBStatus->Delete(i); - break; - } - } - iPhone->ReqCompleted(aTsyReqHandle,KErrCancel); - LOGCALL1("CSimCallBarring::GetCallBarringStatusCancel"); - return KErrNone; - } - -// some useful functions for checking the type of conditions -inline TBool IsOutgoingCondition( RMobilePhone::TMobilePhoneCBCondition aCondition ) - { - return ( (aCondition)==RMobilePhone::EBarAllOutgoing || - (aCondition)==RMobilePhone::EBarOutgoingInternational || - (aCondition)==RMobilePhone::EBarOutgoingInternationalExHC ); - } - -inline TBool IsIncomingCondition( RMobilePhone::TMobilePhoneCBCondition aCondition ) - { - return ( (aCondition)==RMobilePhone::EBarAllIncoming || - (aCondition)==RMobilePhone::EBarIncomingRoaming ); - } - -inline TBool IsDeactivationConditionOnly( RMobilePhone::TMobilePhoneCBCondition aCondition ) - { - return ( (aCondition)==RMobilePhone::EBarAllCases || - (aCondition)==RMobilePhone::EBarAllOutgoingServices || - (aCondition)==RMobilePhone::EBarAllIncomingServices ); - } - -inline void SplitOneEntryIntoSeparateGroupsL( - CMobilePhoneCBList* aCBList, - RMobilePhone::TMobilePhoneCBInfoEntryV1 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::TMobilePhoneCBInfoEntryV1 anotherEntry = aOrigEntry; - - // NOTE: A call to CheckSimTsyVersion must be inserted here if there is a - // change to the version of the structure declared above - - //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; - aCBList->AddEntryL(anotherEntry); - } - }//end for (another) - } - -void CSimCallBarring::UpdateCBListL(RMobilePhone::TMobilePhoneCBCondition* aCB, RMobilePhone::TMobilePhoneCBChangeV1* aCBInfo ) - { - /* - Updates the status of call barring. - @param aCB condition to set - @param aCBInfo details of the call barring status to set - */ - // no sense processing if either condition or change info are NULLS - User::LeaveIfNull(aCBInfo); - User::LeaveIfNull(aCB); - - // check for more conditions as some of the combinations really do not make sense - // and no need to do processing in this case - if (*aCB == RMobilePhone::EBarUnspecified) - User::Leave(KErrArgument); - if ( IsDeactivationConditionOnly(*aCB) - && ( !( (aCBInfo->iAction == RMobilePhone::EServiceActionDeactivate ) - || (aCBInfo->iAction == RMobilePhone::EServiceActionErase )))) - User::Leave(KErrArgument); - - //Lets do some work then - RMobilePhone::TMobilePhoneCBInfoEntryV1 theNewEntry; - - theNewEntry.iCondition = *aCB; - theNewEntry.iServiceGroup = aCBInfo->iServiceGroup; - switch (aCBInfo->iAction) - { - case RMobilePhone::EServiceActionRegister: - case RMobilePhone::EServiceActionActivate: - theNewEntry.iStatus= RMobilePhone::ECallBarringStatusActive; - break; - case RMobilePhone::EServiceActionDeactivate: - case RMobilePhone::EServiceActionErase: - theNewEntry.iStatus= RMobilePhone::ECallBarringStatusNotActive; - break; - case RMobilePhone::EServiceActionUnspecified: - default: - // no sense doing any further operation - leave - User::Leave(KErrArgument); - break; - } - - // retain prev version of the list in local variable and in Cleanup stack - CMobilePhoneCBList* thePrevCBList = CMobilePhoneCBList::NewL(); - CleanupStack::PushL(thePrevCBList); - // copy existing data into the temp storage - for (TInt indx=0; indxEnumerate(); indx++) - { - thePrevCBList->AddEntryL(iCBList->GetEntryL(indx)); - } - delete iCBList; - iCBList = NULL; - // get a hold of it in a local variable - iCBList = CMobilePhoneCBList::NewL(); - // get a hold of it in a local variable - CMobilePhoneCBList* theNewCBList = iCBList; - RMobilePhone::TMobilePhoneCBInfoEntryV1 entry; - - TInt count = thePrevCBList->Enumerate(); - - if (theNewEntry.iStatus == RMobilePhone::ECallBarringStatusActive) - { - if (theNewEntry.iServiceGroup==RMobilePhone::EAllServices) - { - //Activate all conds - //action is to ActivateAllServices with a particular condition; - //Only copy entries with a different condition - for (TInt i = 0; iGetEntryL(i); - //check if the new entry will encompass conditions already defined - // if it does the existing entry is not needed - if (!( - theNewEntry.iCondition==entry.iCondition - || - ( IsOutgoingCondition(entry.iCondition) && IsOutgoingCondition(theNewEntry.iCondition)) - || - ( IsIncomingCondition(entry.iCondition) && IsIncomingCondition(theNewEntry.iCondition)) - )) - theNewCBList->AddEntryL(entry); - }//end for - theNewCBList->AddEntryL(theNewEntry); - } - else - { - //ActivateOne; - // working under the assumption that if EBarOutgoingInternational is enabled - // for EAllServices then setting the fax group, for example to EBarOutgoingInternational - // specifically, will be ignored due to inclusion. Also setting the same condition - // for the same service group(s) again will be ignored. - TBool addNewElem = TRUE; - - for (TInt i = 0; iGetEntryL(i); - // are in the same direction? - if ( (IsOutgoingCondition(theNewEntry.iCondition) && IsOutgoingCondition(entry.iCondition)) - || (IsIncomingCondition(theNewEntry.iCondition) && IsIncomingCondition(entry.iCondition))) - { - // they are in the same direction - // is the current entry specific to a group or not ? - if (entry.iServiceGroup != RMobilePhone::EAllServices) - { - if (theNewEntry.iServiceGroup != entry.iServiceGroup) - theNewCBList->AddEntryL(entry); - } - else - { - // the entry is for all groups - if (theNewEntry.iCondition == entry.iCondition) - { - // the group already precludes this condition; - // just add the existing - theNewCBList->AddEntryL(entry); - addNewElem = FALSE; - } - else - { - // we have to split the entry into entries - // per group with the same condition - SplitOneEntryIntoSeparateGroupsL( - theNewCBList, entry, theNewEntry.iServiceGroup - ); - }// end split entry - } - } - else - { - // they are in different directions - // no need to check further; just add it - theNewCBList->AddEntryL(entry); - }//end are in the same direction? - }// for loop - if (addNewElem) - { - theNewCBList->AddEntryL(theNewEntry); - } - }//end else - } - else //deactivate - { - if ( - (theNewEntry.iServiceGroup==RMobilePhone::EAllServices) - &&(theNewEntry.iCondition==RMobilePhone::EBarAllCases) - ) - ;//Deactivate all conditions: do nothing, list is empty. - else - { - for (TInt i = 0; iGetEntryL(i); - - if (theNewEntry.iCondition == RMobilePhone::EBarAllCases - || - (( theNewEntry.iCondition == RMobilePhone::EBarAllOutgoingServices || IsOutgoingCondition(theNewEntry.iCondition)) - && IsOutgoingCondition(entry.iCondition)) - || - ((theNewEntry.iCondition == RMobilePhone::EBarAllIncomingServices || IsIncomingCondition(theNewEntry.iCondition)) - && IsIncomingCondition(entry.iCondition))) - { - if(theNewEntry.iServiceGroup!=RMobilePhone::EAllServices - && entry.iServiceGroup==RMobilePhone::EAllServices) - { - SplitOneEntryIntoSeparateGroupsL( - theNewCBList, entry, theNewEntry.iServiceGroup - ); - }//end if(create others) - else - {//action applies to different service group - if((theNewEntry.iServiceGroup!=RMobilePhone::EAllServices ) - && (theNewEntry.iServiceGroup!=entry.iServiceGroup)) - theNewCBList->AddEntryL(entry); - } - - }//end if - else - {//action applies to different condition - theNewCBList->AddEntryL(entry); - }//end else - }//end for (entries) - }//end else(all) - }//end else(deactivate) - - //destroy the previous version, the local theNewCBList will be destroyed - CleanupStack::PopAndDestroy(thePrevCBList); - } +// 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 +// callBarring status and registration information. +// +// + +/** + @file +*/ + +#include +#include "CSimCallBarring.h" +#include "CSimPhone.h" +#include "Simlog.h" + +// The Mobile Basic Service Groups used - originally were magic numbers from 1 to 6 incl; +const TInt KMobServiceIndxStart = 1; +const TInt KMobServiceIndxEnd = 6; + + +CSimCallBarring* CSimCallBarring::NewL(CSimPhone* aPhone) +/** + * Standard two-phase constructor. + * @param aPhone The parent phone object. + * @return CSimNetworkStatus The new network status class. + */ + { + CSimCallBarring* self=new(ELeave) CSimCallBarring(aPhone); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +CSimCallBarring::CSimCallBarring(CSimPhone* aPhone) + : iPhone(aPhone) +/** + * Trivial first phase construction. + * @param aPhone The parent phone object. + */ + { + } + +void CSimCallBarring::ConstructL() +/** + Second phase of 2-Phase Constructor + Retrieves all the Call Barring related tags from the config file +*/ + { + LOGCALL1("Starting to parse Call Barring config parameters..."); + + iPassword.Copy(CfgFile()->ItemValue(KCBPassword,KCBDefaultPassword)); + + iGetCBStatus = new(ELeave) CArrayPtrFlat(1); + FindAndCreateCBListL(); + LOGCALL1("...Finished parsing Call Barring config parameters..."); + } + +void CSimCallBarring::FindAndCreateCBListL() +{ +/** + Retrieves all the Call barring tags that define the + original status of Call barring from the config file +*/ + LOGCALL1("CSimPhone::FindAndCreateCBListL"); + RMobilePhone::TMobilePhoneCBInfoEntryV1 entry; + + iCBList = CMobilePhoneCBList::NewL(); + TInt count=CfgFile()->ItemCount(KCBList); + const CTestConfigItem* item=NULL; + TInt ret=KErrNone; + + LOGCALL1("Starting to Load and Parse CBList Config parameters"); + TInt i; + for(i=0;iItem(KCBList,i); + if(!item) + break; + + TInt condition, serviceGroup, status; + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,condition); + if(ret!=KErrNone) + { + LOGPARSERR("condition",ret,0,&KCBList); + continue; + } + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,serviceGroup); + if(ret!=KErrNone) + { + LOGPARSERR("serviceGroup",ret,1,&KCBList); + continue; + } + + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,status); + if(ret!=KErrNone) + { + LOGPARSERR("status",ret,2,&KCBList); + continue; + } + + entry.iCondition=(RMobilePhone::TMobilePhoneCBCondition)condition; + entry.iServiceGroup=(RMobilePhone::TMobileService)serviceGroup; + entry.iStatus=(RMobilePhone::TMobilePhoneCBStatus)status; + + iCBList->AddEntryL(entry); + } + } + +CSimCallBarring::~CSimCallBarring() + { + delete iCBList; + if (iGetCBStatus) + iGetCBStatus->ResetAndDestroy(); + delete iGetCBStatus; + } + +TInt CSimCallBarring::ExtFunc(const TTsyReqHandle aReqHandle,const TInt aIpc, const TDataPackage& aPckg) + { + /** + Handles the phone based requests that apply to call barring + @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 EMobilePhoneSetCallBarringStatus: + return SetCallBarringStatus(aReqHandle, + reinterpret_cast(dataPtr), + reinterpret_cast(dataPtr2)); + case EMobilePhoneSetCallBarringPassword: + return SetCallBarringPassword(aReqHandle,reinterpret_cast(dataPtr)); + case EMobilePhoneNotifyCallBarringStatusChange: + return NotifyCallBarringStatusChange(aReqHandle, reinterpret_cast(dataPtr)); + case EMobilePhoneGetBarringStatusPhase1: + return GetCallBarringStatusPhase1(aReqHandle, + REINTERPRET_CAST(CRetrieveMobilePhoneCBList::TGetCallBarringRequest*, dataPtr), + REINTERPRET_CAST(TInt*, dataPtr2)); + case EMobilePhoneGetBarringStatusPhase2: + return GetCallBarringStatusPhase2(aReqHandle, + REINTERPRET_CAST(RMobilePhone::TClientId*, dataPtr), aPckg.Des2n()); + default: + break; + } + return KErrNotSupported; + } + +TInt CSimCallBarring::CancelService(const TInt aIpc, const TTsyReqHandle aReqHandle) + { + /** + Cancels any phone based request regarding call barring + @param aIpc the IPC to cancel + @param aReqHandle handle to the request + */ + switch(aIpc) + { + case EMobilePhoneSetCallBarringStatus: + return SetCallBarringStatusCancel(aReqHandle); + case EMobilePhoneSetCallBarringPassword: + return SetCallBarringPasswordCancel(aReqHandle); + case EMobilePhoneNotifyCallBarringStatusChange: + return NotifyCallBarringStatusChangeCancel(aReqHandle); + default: + break; + } + return KErrNone; + } + +TInt CSimCallBarring::NotifyCallBarringStatusChange(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhoneCBCondition* aCB) + { + /** + Requests to be notified of change in the Call baring status + @param aReqHandle Handle to the request + @param aCB condition for which the client is interested in being notified + */ + __ASSERT_ALWAYS(!iCBNotification.iCBChangeInfoNotificationPending,SimPanic(ENotificationReqAlreadyOutstanding)); + iCBNotification.iCBChangeInfoNotificationPending=ETrue; + iCBNotification.iCBChangeInfoReqHandle=aReqHandle; + iCBNotification.iCurrentCBCondition=aCB; + LOGCALL1("Finished CSimCallBarring::NotifyCallBarringStatusChange"); + return KErrNone; + } + +TInt CSimCallBarring::NotifyCallBarringStatusChangeCancel(const TTsyReqHandle aReqHandle) + { + /** + Cancels request to be notified of call barring status change + @param aReqHandle Handle to the request + */ + if(iCBNotification.iCBChangeInfoNotificationPending) + { + iCBNotification.iCBChangeInfoNotificationPending=EFalse; + iPhone->ReqCompleted(aReqHandle,KErrCancel); + } + return KErrNone; + } + +TInt CSimCallBarring::SetCallBarringStatus(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhoneCBCondition* aCB, RMobilePhone::TMobilePhoneCBChangeV1* aInfo) + { + /** + Sets the status for call barring + @param aReqHandle Handle to the request + @param aCB condition for which the client whishes to set the call barring status + @param aInfo additional parameters to set the call barring status + */ + //Password does not correspond, return KErrAccessDenied .. is that right ? Not specified in SDK! + if (iPassword != aInfo->iPassword) + { + iPhone->ReqCompleted(aReqHandle,KErrAccessDenied); + return KErrNone; + } + + // make sure we know that the operation concluded sucessfully + TRAPD(ret,UpdateCBListL(aCB,aInfo)); + if ( ret != KErrNone ) + { + iPhone->ReqCompleted(aReqHandle,ret); + return KErrNone; + } + + // otherwise proceed and notify all went well + // Notify change + if (iCBNotification.iCBChangeInfoNotificationPending) + { + *(iCBNotification.iCurrentCBCondition)=*aCB; + iCBNotification.iCBChangeInfoNotificationPending=EFalse; + iPhone->ReqCompleted(iCBNotification.iCBChangeInfoReqHandle,KErrNone); + } + + iPhone->ReqCompleted(aReqHandle,KErrNone); + + return KErrNone; + } + +TInt CSimCallBarring::SetCallBarringStatusCancel(const TTsyReqHandle aReqHandle) + { + /** + Cancels the request to sets the status for call barring + @param aReqHandle Handle to the request + */ + + iPhone->ReqCompleted(aReqHandle,KErrCancel); + return KErrNone; + } + +TInt CSimCallBarring::SetCallBarringPassword(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhonePasswordChangeV1* aInfo) + { + /** + Sets the password that prevents the call barring status to be modified + @param aReqHandle Handle to the request + @param aInfo The old and new password + */ + if (iPassword == aInfo->iOldPassword) + { + iPassword = aInfo->iNewPassword; + iPhone->ReqCompleted(aReqHandle,KErrNone); + } + else + { + iPhone->ReqCompleted(aReqHandle,KErrAccessDenied); + } + return KErrNone; + } + +TInt CSimCallBarring::SetCallBarringPasswordCancel(const TTsyReqHandle aReqHandle) + { + /** + cancels a request to set the password that prevents the call barring status to be modified + @param aReqHandle Handle to the request + */ + iPhone->ReqCompleted(aReqHandle,KErrCancel); + return KErrNone; + } + + +const CTestConfigSection* CSimCallBarring::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 CSimCallBarring::GetCallBarringStatusPhase1(const TTsyReqHandle aTsyReqHandle, + CRetrieveMobilePhoneCBList::TGetCallBarringRequest* aReqData, + TInt* aBufSize) + { + /** + 1st phase retrieval of the the call barring 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("CSimPhone::GetCallBarringStatusPhase1"); + + TInt ret=KErrNone; + TInt leaveCode=KErrNone; + TRAP(leaveCode, ret=ProcessGetCallBarringStatusPhase1L(aTsyReqHandle, aReqData, aBufSize);); + if (leaveCode != KErrNone) + iPhone->ReqCompleted(aTsyReqHandle,leaveCode); + + LOGCALL1("CSimPhone::GetCallBarringStatusPhase1"); + return ret; + } + +TInt CSimCallBarring::ProcessGetCallBarringStatusPhase1L(const TTsyReqHandle aTsyReqHandle, + CRetrieveMobilePhoneCBList::TGetCallBarringRequest* aReqData, + TInt* aBufSize) + { + /** Retrieve call barring 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("CSimCallBarring::ProcessGetCallBarringStatusPhase1L"); + + CMobilePhoneCBList* list=CMobilePhoneCBList::NewL(); + CleanupStack::PushL(list); + + + TInt cnt=0;//Only interested by entries with a particular condition + TInt maxNum=iCBList->Enumerate(); + //if testing all conditions and all CB are non-active + // then we have to return a single entry EBarAllCases and EAllServices + if ( maxNum ) + { + for(TInt i=0;iGetEntryL(i).iCondition == aReqData->iCondition) + ||(aReqData->iCondition==RMobilePhone::EBarUnspecified)) + { + list->AddEntryL(iCBList->GetEntryL(i)); + cnt++; + } + } + } + else + { + // if the list is empty and the querry general then we have to return general info + if ( aReqData->iCondition == RMobilePhone::EBarUnspecified ) + { + RMobilePhone::TMobilePhoneCBInfoEntryV1 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.iCondition = RMobilePhone::EBarAllCases; + entry.iServiceGroup = RMobilePhone::EAllServices; + entry.iStatus = RMobilePhone::ECallBarringStatusNotActive; + 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 + + iGetCBStatus->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("CSimCallBarring::ProcessGetCallBarringStatusPhase1L"); + return KErrNone; + } + +TInt CSimCallBarring::GetCallBarringStatusPhase2(const TTsyReqHandle aTsyReqHandle, + RMobilePhone::TClientId* aClient, TDes8* aBuf) + { + /** + 2nd phase retrieval of the the call barring status list + @param aReqHandle Handle to the request + @param aClient Ponter to the client + @param aBuf Buffer containiong the call barring status list + */ + LOGCALL1("CSimCallBarring::GetCallBarringStatusPhase2"); + CListReadAllAttempt* read=NULL; + // Find the get detected network attempt from this client + for (TInt i=0; iCount(); ++i) + { + read = iGetCBStatus->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; + iGetCBStatus->Delete(i); + iPhone->ReqCompleted(aTsyReqHandle,KErrNone); + return KErrNone; + } + } + // Should handle error case of not finding the matching client from read all phase 1 + LOGCALL1("CSimCallBarring::GetCallBarringStatusPhase2"); + return KErrNotFound; + } + +TInt CSimCallBarring::GetCallBarringStatusCancel(const TTsyReqHandle aTsyReqHandle) + { + /* + Cancels a Request to retrieve the call barring status list + @param aReqHandle Handle to the request + */ + LOGCALL1("CSimCallBarring::GetCallBarringStatusCancel"); + iPhone->ReqCompleted(aTsyReqHandle,KErrNone); + // Remove the read all attempt from iGetCBStatus + CListReadAllAttempt* read=NULL; + for (TInt i=0; iCount(); ++i) + { + read = iGetCBStatus->At(i); + if (read->iReqHandle == aTsyReqHandle) + { + delete read; + iGetCBStatus->Delete(i); + break; + } + } + iPhone->ReqCompleted(aTsyReqHandle,KErrCancel); + LOGCALL1("CSimCallBarring::GetCallBarringStatusCancel"); + return KErrNone; + } + +// some useful functions for checking the type of conditions +inline TBool IsOutgoingCondition( RMobilePhone::TMobilePhoneCBCondition aCondition ) + { + return ( (aCondition)==RMobilePhone::EBarAllOutgoing || + (aCondition)==RMobilePhone::EBarOutgoingInternational || + (aCondition)==RMobilePhone::EBarOutgoingInternationalExHC ); + } + +inline TBool IsIncomingCondition( RMobilePhone::TMobilePhoneCBCondition aCondition ) + { + return ( (aCondition)==RMobilePhone::EBarAllIncoming || + (aCondition)==RMobilePhone::EBarIncomingRoaming ); + } + +inline TBool IsDeactivationConditionOnly( RMobilePhone::TMobilePhoneCBCondition aCondition ) + { + return ( (aCondition)==RMobilePhone::EBarAllCases || + (aCondition)==RMobilePhone::EBarAllOutgoingServices || + (aCondition)==RMobilePhone::EBarAllIncomingServices ); + } + +inline void SplitOneEntryIntoSeparateGroupsL( + CMobilePhoneCBList* aCBList, + RMobilePhone::TMobilePhoneCBInfoEntryV1 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::TMobilePhoneCBInfoEntryV1 anotherEntry = aOrigEntry; + + // NOTE: A call to CheckSimTsyVersion must be inserted here if there is a + // change to the version of the structure declared above + + //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; + aCBList->AddEntryL(anotherEntry); + } + }//end for (another) + } + +void CSimCallBarring::UpdateCBListL(RMobilePhone::TMobilePhoneCBCondition* aCB, RMobilePhone::TMobilePhoneCBChangeV1* aCBInfo ) + { + /* + Updates the status of call barring. + @param aCB condition to set + @param aCBInfo details of the call barring status to set + */ + // no sense processing if either condition or change info are NULLS + User::LeaveIfNull(aCBInfo); + User::LeaveIfNull(aCB); + + // check for more conditions as some of the combinations really do not make sense + // and no need to do processing in this case + if (*aCB == RMobilePhone::EBarUnspecified) + User::Leave(KErrArgument); + if ( IsDeactivationConditionOnly(*aCB) + && ( !( (aCBInfo->iAction == RMobilePhone::EServiceActionDeactivate ) + || (aCBInfo->iAction == RMobilePhone::EServiceActionErase )))) + User::Leave(KErrArgument); + + //Lets do some work then + RMobilePhone::TMobilePhoneCBInfoEntryV1 theNewEntry; + + theNewEntry.iCondition = *aCB; + theNewEntry.iServiceGroup = aCBInfo->iServiceGroup; + switch (aCBInfo->iAction) + { + case RMobilePhone::EServiceActionRegister: + case RMobilePhone::EServiceActionActivate: + theNewEntry.iStatus= RMobilePhone::ECallBarringStatusActive; + break; + case RMobilePhone::EServiceActionDeactivate: + case RMobilePhone::EServiceActionErase: + theNewEntry.iStatus= RMobilePhone::ECallBarringStatusNotActive; + break; + case RMobilePhone::EServiceActionUnspecified: + default: + // no sense doing any further operation - leave + User::Leave(KErrArgument); + break; + } + + // retain prev version of the list in local variable and in Cleanup stack + CMobilePhoneCBList* thePrevCBList = CMobilePhoneCBList::NewL(); + CleanupStack::PushL(thePrevCBList); + // copy existing data into the temp storage + for (TInt indx=0; indxEnumerate(); indx++) + { + thePrevCBList->AddEntryL(iCBList->GetEntryL(indx)); + } + delete iCBList; + iCBList = NULL; + // get a hold of it in a local variable + iCBList = CMobilePhoneCBList::NewL(); + // get a hold of it in a local variable + CMobilePhoneCBList* theNewCBList = iCBList; + RMobilePhone::TMobilePhoneCBInfoEntryV1 entry; + + TInt count = thePrevCBList->Enumerate(); + + if (theNewEntry.iStatus == RMobilePhone::ECallBarringStatusActive) + { + if (theNewEntry.iServiceGroup==RMobilePhone::EAllServices) + { + //Activate all conds + //action is to ActivateAllServices with a particular condition; + //Only copy entries with a different condition + for (TInt i = 0; iGetEntryL(i); + //check if the new entry will encompass conditions already defined + // if it does the existing entry is not needed + if (!( + theNewEntry.iCondition==entry.iCondition + || + ( IsOutgoingCondition(entry.iCondition) && IsOutgoingCondition(theNewEntry.iCondition)) + || + ( IsIncomingCondition(entry.iCondition) && IsIncomingCondition(theNewEntry.iCondition)) + )) + theNewCBList->AddEntryL(entry); + }//end for + theNewCBList->AddEntryL(theNewEntry); + } + else + { + //ActivateOne; + // working under the assumption that if EBarOutgoingInternational is enabled + // for EAllServices then setting the fax group, for example to EBarOutgoingInternational + // specifically, will be ignored due to inclusion. Also setting the same condition + // for the same service group(s) again will be ignored. + TBool addNewElem = TRUE; + + for (TInt i = 0; iGetEntryL(i); + // are in the same direction? + if ( (IsOutgoingCondition(theNewEntry.iCondition) && IsOutgoingCondition(entry.iCondition)) + || (IsIncomingCondition(theNewEntry.iCondition) && IsIncomingCondition(entry.iCondition))) + { + // they are in the same direction + // is the current entry specific to a group or not ? + if (entry.iServiceGroup != RMobilePhone::EAllServices) + { + if (theNewEntry.iServiceGroup != entry.iServiceGroup) + theNewCBList->AddEntryL(entry); + } + else + { + // the entry is for all groups + if (theNewEntry.iCondition == entry.iCondition) + { + // the group already precludes this condition; + // just add the existing + theNewCBList->AddEntryL(entry); + addNewElem = FALSE; + } + else + { + // we have to split the entry into entries + // per group with the same condition + SplitOneEntryIntoSeparateGroupsL( + theNewCBList, entry, theNewEntry.iServiceGroup + ); + }// end split entry + } + } + else + { + // they are in different directions + // no need to check further; just add it + theNewCBList->AddEntryL(entry); + }//end are in the same direction? + }// for loop + if (addNewElem) + { + theNewCBList->AddEntryL(theNewEntry); + } + }//end else + } + else //deactivate + { + if ( + (theNewEntry.iServiceGroup==RMobilePhone::EAllServices) + &&(theNewEntry.iCondition==RMobilePhone::EBarAllCases) + ) + ;//Deactivate all conditions: do nothing, list is empty. + else + { + for (TInt i = 0; iGetEntryL(i); + + if (theNewEntry.iCondition == RMobilePhone::EBarAllCases + || + (( theNewEntry.iCondition == RMobilePhone::EBarAllOutgoingServices || IsOutgoingCondition(theNewEntry.iCondition)) + && IsOutgoingCondition(entry.iCondition)) + || + ((theNewEntry.iCondition == RMobilePhone::EBarAllIncomingServices || IsIncomingCondition(theNewEntry.iCondition)) + && IsIncomingCondition(entry.iCondition))) + { + if(theNewEntry.iServiceGroup!=RMobilePhone::EAllServices + && entry.iServiceGroup==RMobilePhone::EAllServices) + { + SplitOneEntryIntoSeparateGroupsL( + theNewCBList, entry, theNewEntry.iServiceGroup + ); + }//end if(create others) + else + {//action applies to different service group + if((theNewEntry.iServiceGroup!=RMobilePhone::EAllServices ) + && (theNewEntry.iServiceGroup!=entry.iServiceGroup)) + theNewCBList->AddEntryL(entry); + } + + }//end if + else + {//action applies to different condition + theNewCBList->AddEntryL(entry); + }//end else + }//end for (entries) + }//end else(all) + }//end else(deactivate) + + //destroy the previous version, the local theNewCBList will be destroyed + CleanupStack::PopAndDestroy(thePrevCBList); + }