diff -r 6b1d113cdff3 -r 6638e7f4bd8f telephonyserverplugins/simtsy/src/CSimPhBkStore.cpp --- a/telephonyserverplugins/simtsy/src/CSimPhBkStore.cpp Mon May 03 13:37:20 2010 +0300 +++ b/telephonyserverplugins/simtsy/src/CSimPhBkStore.cpp Thu May 06 15:10:38 2010 +0100 @@ -1,1295 +1,1295 @@ -// 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 Phonebook Store manipulation code. -// -// - -/** - @file -*/ - -#include "CSimPhBkStore.h" -#include "CSimPhone.h" -#include "Simlog.h" -#include - -const TUint16 KNpiTonInternational=145; // < The Number Plan Identifier and Type of Number for an international telephone number. -const TUint16 KNpiTonNational=129; // < The Number Plan Identifier and Type of Number for a national telephone number. -const TInt KPhonebookErrorGranularity=3; // < Granularity of phonebook error list array. -// -// CSimPhBkStore -// -void CSimPhBkStore::ClosePhone(TAny* aObj) -/** - * A utility function for cleaning up the stack. - */ - { - ((CObject*)aObj)->Close(); - } - -CSimPhBkStore* CSimPhBkStore::NewL(CSimPhone* aPhone, const TDesC8& aName, TInt aMaxNumSlots, TInt aMaxNumLen, TInt aMaxTextLen) -/** - * Standard two phase constructor. - * @param aPhone The phone object from which this Phonebook was opened. - * @param aName The name of the created Phonebook. - * @param aMaxNumSlots The maximum number of slots in the Phonebook. - * @return CSimPhBkStore* The newly created object. - */ - { - CSimPhBkStore* store=new(ELeave) CSimPhBkStore(aPhone); - TCleanupItem newObjClose(ClosePhone,store); - CleanupStack::PushL(newObjClose); - store->ConstructL(aName,aMaxNumSlots,aMaxNumLen,aMaxTextLen); - CleanupStack::Pop(); - return store; - } - -CSimPhBkStore::CSimPhBkStore(CSimPhone* aPhone) - : CSimPhone(iDummyPhoneBaseRef), iPhone(aPhone),iIpcCnt(0),iEvOutstandingReq(EFalse) -/** - * Trivial first phase constructor. - * @param aPhone The phone object from which this phonebook was opened. - */ - {} - -void CSimPhBkStore::ConstructL(const TDesC8& aName, TInt aMaxNumSlots, TInt aMaxNumLen, TInt aMaxTextLen) -/** - * Second phase constructor that allocates memory for the phonebook, batch read buffer and - * a delayed completion timer. The constructor also reads the individual and batch read - * delays from the configuration file. - * - * @param aName The name of the created phonebook. - * @param aMaxNumLen The maximum length of a telephone number. - * @param aMaxTextLen The maximum length of an alpha tag. - */ - { - LOGPHBK1("Starting to parse Phonebook store additional config parameters..."); - __ASSERT_ALWAYS(aMaxNumLen<=KPhBkMaxTelNumSize,SimPanic(EPhonebookNameOrNumberTooLarge)); - __ASSERT_ALWAYS(aMaxTextLen<=KPhBkMaxAlphaTagSize,SimPanic(EPhonebookNameOrNumberTooLarge)); - - iPhBkStoreEntries=new(ELeave) TPhBkStoreEntry[aMaxNumSlots+1]; //slot 0 is unused - iPhBkMaxNumSlots=aMaxNumSlots; - iPhBkMaxTelNumLen=aMaxNumLen; - iPhBkMaxTextLen=aMaxTextLen; - iPhBkStoreName.Copy(aName); - - iReqTimer=CSimTimer::NewL(iPhone); - iOOBWriteTimer=CSimTimer::NewL(iPhone); - iOOBDeleteTimer=CSimTimer::NewL(iPhone); - iPhBkRwBuffer=new(ELeave) CPhoneBookBuffer(); - iPhBkError=new(ELeave) CArrayFixFlat(KPhonebookErrorGranularity); - - const CTestConfigItem* item=NULL; - TInt ret=KErrNone; - item=CfgFile()->Item(KTriggerEventIPC,0); - if(item) - { - TInt ipc, cnt, event; - - ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,ipc); - if(ret!=KErrNone) - { - LOGPARSERR("ipc",ret,0,&KTriggerEventIPC); - } - else - iTriggerEventIPC.iIPC=ipc; - - ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,cnt); - if(ret!=KErrNone) - { - LOGPARSERR("cnt",ret,1,&KTriggerEventIPC); - } - else - iTriggerEventIPC.iIPCCnt=cnt; - - ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,event); - if(ret!=KErrNone) - { - LOGPARSERR("event",ret,2,&KTriggerEventIPC); - } - else - iTriggerEventIPC.iEvent=RMobilePhone::TMobilePhoneSecurityEvent(event); - - - } - - const CTestConfigItem* item0=NULL; - item0=CfgFile()->Item(KPhBkPhoneStoreCaps,0); - if (item0) - { - TPtrC8 value0; - TInt ret0=CTestConfig::GetElement(item0->Value(),KStdDelimiter,0,value0); - if(ret0!=KErrNone) - { - iPhBkStoreCaps=KDefaultPhBkPhoneStoreCaps; - LOGPARSERR("value0",ret0,0,&KPhBkPhoneStoreCaps); - } - else - { - TUint32 intValue; - TInt ret = AsciiToNum(value0, intValue); - if(ret!=KErrNone) - iPhBkStoreCaps=KDefaultPhBkPhoneStoreCaps; - else - iPhBkStoreCaps = intValue; - } - } - else - iPhBkStoreCaps=KDefaultPhBkPhoneStoreCaps; - - - LOGPHBK1("...Finished parsing Phonebook store additional config parameters..."); - } - -void CSimPhBkStore::PopulateStoreFromConfigFileL() -/** - * Populate the Phonebook Store from information in the configuration file. This is performed - * after the standard Phonebook Store construction in order to prevent reseting the configuation - * file accessor class' pointers while possibly multiple Phonebook Stores are created. - * - * The store entries comply to the following format: - * "PhBkStoreEntry = , , , " - */ - { - LOGPHBK1("Starting to read Phonebook store entries..."); - iPhBkIndividualPause=CfgFile()->ItemValue(KPhBkStoreIndividualReqPause,KDefaultPhBkStoreIndividualReqPause); - iPhBkBatchPause=CfgFile()->ItemValue(KPhBkStoreBatchReqPause,KDefaultPhBkStoreBatchReqPause); - - TInt count=CfgFile()->ItemCount(KPhBkStoreEntry); - const CTestConfigItem* item=NULL; - TInt ret=KErrNone; - - TInt i; - for(i=0;iItem(KPhBkStoreEntry,i); - if(!item) - break; - - TPtrC8 phonebookName,alphaTag,telNum; - TInt index; - TUint8 npiTon; - ret=GetPhBkEntry(item,0,phonebookName,index,telNum,alphaTag,npiTon); - if(ret!=KErrNone) - { - LOGPARSERR("Phonebook Entry",ret,index,&KPhBkStoreEntry); - continue; - } - if(phonebookName.MatchF(iPhBkStoreName)!=0)// Not this phonebook - continue; - - iPhBkStoreEntries[index].iAlphaTag.Copy(alphaTag); - iPhBkStoreEntries[index].iTelNum.Copy(telNum); - iPhBkStoreEntries[index].iTonNpi=npiTon; - } - - count=CfgFile()->ItemCount(KPhBkError); - item=NULL; - - for(i=0;iItem(KPhBkError,i); - if(!item) - break; - - TInt count,error; - TPtrC8 phonebookName, phonebookStore; - - ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,count); - if(ret!=KErrNone) - { - LOGPARSERR("count",ret,0,&KPhBkError); - continue; - } - ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,error); - if(ret!=KErrNone) - { - LOGPARSERR("error",ret,1,&KPhBkError); - continue; - } - ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,phonebookName); - if(ret!=KErrNone) - { - LOGPARSERR("phonebookName",ret,2,&KPhBkError); - continue; - } - ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,phonebookStore); - if(ret!=KErrNone) - { - LOGPARSERR("phonebookStore",ret,3,&KPhBkError); - } - else //not for the global phonebook - continue; - - if(phonebookName.MatchF(iPhBkStoreName)!=0)// Not this phonebook - continue; - - - TPhBkError entry; - entry.iCount=count; - entry.iError=error; - iPhBkError->AppendL(entry); - } - PopulateOOBWrite(); - PopulateOOBDelete(); - LOGPHBK1("...Finished reading Phonebook store entries..."); - - if(iPhBkOOBWriteDuration!=-1) - iOOBWriteTimer->Start(iPhBkOOBWriteDuration,this,ETimerIdPhBkStorOOBWrite); - if(iPhBkOOBDeleteDuration!=-1) - iOOBDeleteTimer->Start(iPhBkOOBDeleteDuration,this,ETimerIdPhBkStorOOBDelete); - } - -void CSimPhBkStore::PopulateOOBWrite() -/** - * Populate the member variables required to operate the OOB Store functionality from - * the configuration file. - * The OOBPhBkStore configuration file tag should have the following format: - * "OOBPhBkStore= , , , , " - */ - { - iPhBkOOBWriteDuration=KErrNotFound; - const CTestConfigItem* item=CfgFile()->Item(KOOBPhBkWrite); - if(!item) - return; - - TInt count; - TInt ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,count); - if(ret!=KErrNone) - { - LOGPARSERR("count",ret,0,&KOOBPhBkWrite); - return; - } - - TPtrC8 phonebookName,alphaTag,telNum; - TInt index; - TUint8 npiTon; - ret=GetPhBkEntry(item,1,phonebookName,index,telNum,alphaTag,npiTon); - if(ret!=KErrNone) - { - LOGPARSERR("npiTon",ret,index,&KOOBPhBkWrite); - return; - } - if(phonebookName.MatchF(iPhBkStoreName)!=0) - return; // Not this phonebook - - iPhBkOOBWriteDuration=count; - iPhBkOOBWriteIndex=index; - iPhBkOOBWrite.iAlphaTag.Copy(alphaTag); - iPhBkOOBWrite.iTelNum.Copy(telNum); - iPhBkOOBWrite.iTonNpi=npiTon; - } - -void CSimPhBkStore::PopulateOOBDelete() -/** - * Populate the member variables required to operate the OOB Delete functionality from - * the configuration file. - * The OOBPhBkDelete configuration file tag should have the following format: - * "OOBPhBkDelete= , , - */ - { - iPhBkOOBDeleteDuration=KErrNotFound; - const CTestConfigItem* item=CfgFile()->Item(KOOBPhBkDelete); - if(!item) - return; - - TInt count; - TInt ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,count); - if(ret!=KErrNone) - { - LOGPARSERR("count",ret,0,&KOOBPhBkDelete); - return; - } - - TPtrC8 phonebookName; - ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,phonebookName); - if(ret!=KErrNone) - { - LOGPARSERR("phonebookName",ret,1,&KOOBPhBkDelete); - return; - } - if(phonebookName.MatchF(iPhBkStoreName)!=0) - return; // Not this phonebook - - TInt index; - ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,index); - if(ret!=KErrNone) - { - LOGPARSERR("index",ret,2,&KOOBPhBkDelete); - return; - } - - iPhBkOOBDeleteDuration=count; - iPhBkOOBDeleteIndex=index; - } - -TInt CSimPhBkStore::GetPhBkEntry(const CTestConfigItem* aItem, TInt aItemIndex, - TPtrC8& aPhonebookName, TInt& aIndex, - TPtrC8& aTelNum, TPtrC8& aAlphaTag, TUint8& aNpiTon) -/** - * Retrieve a phonebook entry from the configuration file, starting at a given item index - * value. - * @param aItem Pointer to the config file item from which the phonebook entry will be read. - * @param aItemIndex The index number within the item from which the phonebook entry will be read. - * @param aPhonebookName The returned phonebook name - * @param aIndex The returned index number - * @param aTelNum The returned telephone number - * @param aAlphaTag The returned alpha tag - * @param aNpiTon The returned Number Plan Identifier and Type of Number information - * @return TInt Standard error value. - */ - { - TInt ret; - ret=CTestConfig::GetElement(aItem->Value(),KStdDelimiter,aItemIndex++,aPhonebookName); - if(ret!=KErrNone) - return ret; - - ret=CTestConfig::GetElement(aItem->Value(),KStdDelimiter,aItemIndex++,aIndex); - if(ret!=KErrNone) - return ret; - - if(aIndex>iPhBkMaxNumSlots) //the max number of slot is a valid slot - return KErrArgument; - - ret=CTestConfig::GetElement(aItem->Value(),KStdDelimiter,aItemIndex++,aTelNum); - if(ret!=KErrNone) - return ret; - if(aTelNum.Length()>iPhBkMaxTelNumLen) - return KErrArgument; - - ret=CTestConfig::GetElement(aItem->Value(),KStdDelimiter,aItemIndex++,aAlphaTag); - if(ret!=KErrNone) - return ret; - if(aAlphaTag.Length()>iPhBkMaxTextLen) - return KErrArgument; - - if((aTelNum.Length()>0) && (aTelNum[0]=='+')) - { - aTelNum.Set(aTelNum.Mid(1)); - aNpiTon=KNpiTonInternational; - } - else - aNpiTon=KNpiTonNational; - return ret; - } - -CSimPhBkStore::~CSimPhBkStore() -/** - * Standard destructor. Any objects created by the ::ConstructL() function - * will be destroyed here. - */ - { - delete[] iPhBkStoreEntries; - delete iPhBkError; - delete iPhBkRwBuffer; - delete iOOBWriteTimer; - delete iOOBDeleteTimer; - delete iReqTimer; - } - -TInt CSimPhBkStore::ExtFunc(const TTsyReqHandle aReqHandle,const TInt aIpc, const TDataPackage& aPckg) -/** - * Dispatch function for all Phonebook Store requests. - * @param aReqHandle The TSY request handle for this request. - * @param aIpc The IPC number of this request. - * @param aPckg The parameter package related to this request. - * @return TInt The return error condition. - */ - { - iIpcCnt++; - TInt error=KErrNone; - if(FindIpcErrorMatch(error)) - { - ReqCompleted(aReqHandle,error); - return KErrNone; - } - -// The following requests can be completed even if the completion of another request is pending. - switch(aIpc) - { - case EMobilePhoneStoreGetInfo: - error = GetInfo(aReqHandle,aPckg.Des1n()); - if(iTriggerEventIPC.iIPC==aIpc) - { - iTriggerCnt++; - if(iTriggerEventIPC.iIPCCnt==iTriggerCnt) - iPhone->SecurityEvent(iTriggerEventIPC.iEvent); - } - return error; - - case EMobilePhoneStoreNotifyStoreEvent: - error = NotifyStoreEvent(aReqHandle,aPckg.Des1n(),aPckg.Des2n()); - if(iTriggerEventIPC.iIPC==aIpc) - { - iTriggerCnt++; - if(iTriggerEventIPC.iIPCCnt==iTriggerCnt) - iPhone->SecurityEvent(iTriggerEventIPC.iEvent); - } - return error; - - default: - break; - } - - -// The TSY can only process one of the following requests at a time. If a second is received -// while processing the first, then it will be errored with KErrInUse. This restriction will -// be removed later, by inserting a request queuing mechanism. Note that the standard TSY -// "flow control" mechanism works phone-wide and so is not suitable. - - if(iReqTimer->IsActive()) - { - ReqCompleted(aReqHandle,KErrInUse); - return KErrNone; - } - - switch(aIpc) - { -// The standard multimode store read and write are not supported. - case EMobilePhoneStoreRead: - case EMobilePhoneStoreWrite: - case EMobilePhoneStoreReadAllPhase1: - case EMobilePhoneStoreReadAllPhase2: - ReqCompleted(aReqHandle,KErrNotSupported); - return KErrNone; - - case EMobilePhoneBookStoreRead: - error = Read(aReqHandle,aPckg.Des1n(),aPckg.Des2n()); - if(iTriggerEventIPC.iIPC==aIpc) - { - iTriggerCnt++; - if(iTriggerEventIPC.iIPCCnt==iTriggerCnt) - iPhone->SecurityEvent(iTriggerEventIPC.iEvent); - } - return error; - - case EMobilePhoneBookStoreWrite: - error = Write(aReqHandle,aPckg.Des1n(),aPckg.Des2n()); - if(iTriggerEventIPC.iIPC==aIpc) - { - iTriggerCnt++; - if(iTriggerEventIPC.iIPCCnt==iTriggerCnt) - iPhone->SecurityEvent(iTriggerEventIPC.iEvent); - } - return error; - - case EMobilePhoneStoreDelete: - error = Delete(aReqHandle,aPckg.Des1n()); - if(iTriggerEventIPC.iIPC==aIpc) - { - iTriggerCnt++; - if(iTriggerEventIPC.iIPCCnt==iTriggerCnt) - iPhone->SecurityEvent(iTriggerEventIPC.iEvent); - } - return error; - - case EMobilePhoneStoreDeleteAll: - error = DeleteAll(aReqHandle); - if(iTriggerEventIPC.iIPC==aIpc) - { - iTriggerCnt++; - if(iTriggerEventIPC.iIPCCnt==iTriggerCnt) - iPhone->SecurityEvent(iTriggerEventIPC.iEvent); - } - return error; - - default: - break; - } - - return KErrNotSupported; - } - -CTelObject* CSimPhBkStore::OpenNewObjectByNameL(const TDesC& /*aName*/) -/** - * The API does not support any objects that could be opened from this one. - */ - { - User::Leave(KErrNotSupported); - return NULL; - } - -CTelObject* CSimPhBkStore::OpenNewObjectL(TDes&) -/** - * The API does not support any objects that could be opened from this one. - */ - { - User::Leave(KErrNotSupported); - return NULL; - } - -CTelObject::TReqMode CSimPhBkStore::ReqModeL(const TInt aIpc) -/** - * This function returns the Request Mode for the request with the passed IPC value. - * @param aIpc The IPC number of the request. - * @return TReqMode The request mode. - */ - { - CTelObject::TReqMode ret=0; - - switch(aIpc) - { - case EMobilePhoneStoreGetInfo: - case EMobilePhoneStoreDelete: - case EMobilePhoneStoreDeleteAll: - case EMobilePhoneBookStoreRead: - case EMobilePhoneBookStoreWrite: - break; - - case EMobilePhoneStoreNotifyStoreEvent: - ret=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately; - break; - - default: - User::Leave(KErrNotSupported); - break; - } - - return ret; - } - -TInt CSimPhBkStore::RegisterNotification(const TInt /*aIpc*/) -/** - * The ETel Server calls this function when the first client makes a notification - * request. If supported by the underlying protocol controlling the - * signalling stack, this can be used to start requesting updates for the relevant - * service. - */ - { - return KErrNone; - } - -TInt CSimPhBkStore::DeregisterNotification(const TInt /*aIpc*/) -/** - * The ETel Server calls this function when the last client that had previously - * made a notification request closes its ETel Server handle. If supported by - * the underlying protocol controlling the signalling stack, this can be used - * to stop requesting updates for the relevant service. - */ - { - return KErrNone; - } - -TInt CSimPhBkStore::NumberOfSlotsL(const TInt /*aIpc*/) -/** - * Return the number of slots that the ETel Server should allocate for buffering requests - * of the given IPC number. - */ - { - return KDefaultNumberOfSlots; - } - -TInt CSimPhBkStore::CancelService(const TInt aIpc,const TTsyReqHandle /*aTsyReqHandle*/) -/** - * Cancel an outstanding request. - * @param aIpc The IPC number of the request that is to be cancelled. - * @param aTsyReqHandle The TSY request handle of the request that is to be cancelled. - * @param TInt Standard return value. - */ - { - switch(aIpc) - { - case EMobilePhoneStoreGetInfo: - case EMobilePhoneStoreDelete: - case EMobilePhoneStoreDeleteAll: - case EMobilePhoneBookStoreRead: - case EMobilePhoneBookStoreWrite: - break; - - case EMobilePhoneStoreNotifyStoreEvent: - NotifyStoreEventCancel(); - break; - - default: - break; - } - return KErrNone; - } - -void CSimPhBkStore::Init() -/** - * This function can be used to perform any necessary synchronous initialisation. - */ - { - } - -TInt CSimPhBkStore::GetInfo(TTsyReqHandle aReqHandle, TDes8* aPckg) -/** - * Retrieve Phonebook Store information. This request is completed immediately, as it is assumed - * that in a real TSY, all this data will be cached in the TSY. - * - * @param aReqHandle The TSY request handle associated with this request. - * @param aPckg The parameter package associated with this request. - */ - { - - if(iPhone->IsICCLocked()!=EFalse) - { - ReqCompleted(aReqHandle, KErrAccessDenied); - return KErrNone; - } - - RMobilePhoneBookStore::TMobilePhoneBookInfoV1Pckg* getInfoPckg=(RMobilePhoneBookStore::TMobilePhoneBookInfoV1Pckg*)aPckg; - RMobilePhoneBookStore::TMobilePhoneBookInfoV1& getInfo=(*getInfoPckg)(); - - PopulatePhBkStoreInfo(&getInfo); - - if(&getInfo!=NULL) // This will be the case if the version checking within PopulatePhBkStoreInfo has failed. - { - ReqCompleted(aReqHandle,KErrNone); - } - else - { - ReqCompleted(aReqHandle,KErrNotSupported); - } - - return KErrNone; - } - -void CSimPhBkStore::PopulatePhBkStoreInfo(RMobilePhoneStore::TMobilePhoneStoreInfoV1* aStoreInfo) -/** - * Populate the passed parameter with Phonebook Store information. - * @param aStoreInfo Pointer to phonebook store information structure to be populated. - */ - { - __ASSERT_ALWAYS(aStoreInfo, SimPanic(EIllegalNullPtrParameter)); - - aStoreInfo->iType=RMobilePhoneStore::EPhoneBookStore; - aStoreInfo->iTotalEntries=MaxSlots(); - aStoreInfo->iCaps=iPhBkStoreCaps; - aStoreInfo->iName.Copy(iPhBkStoreName); - aStoreInfo->iUsedEntries=UsedEntries(); - - if(aStoreInfo->ExtensionId()==RMobilePhoneStore::KETelMobilePhonebookStoreV1) - { - RMobilePhoneBookStore::TMobilePhoneBookInfoV1* getExtraInfo=(RMobilePhoneBookStore::TMobilePhoneBookInfoV1*)aStoreInfo; - - // Check that the data structure is supported by the simulated TSY version - TInt err = iPhone->CheckSimTsyVersion(*getExtraInfo); - if(err != KErrNone) - { - getExtraInfo = NULL; - return; - } - - getExtraInfo->iMaxNumLength=iPhBkMaxTelNumLen; - getExtraInfo->iMaxTextLength=iPhBkMaxTextLen; - getExtraInfo->iLocation=RMobilePhoneBookStore::ELocationIccMemory; - getExtraInfo->iChangeCounter=0; - getExtraInfo->iIdentity.Copy(iPhone->GetImsi()); - } - else if(aStoreInfo->ExtensionId()==RMobilePhoneStore::KETelMobilePhonebookStoreV2) - { - RMobilePhoneBookStore::TMobilePhoneBookInfoV2* getExtraInfo=(RMobilePhoneBookStore::TMobilePhoneBookInfoV2*)aStoreInfo; - - // Check that the data structure is supported by the simulated TSY version - TInt err = iPhone->CheckSimTsyVersion(*getExtraInfo); - if(err != KErrNone) - { - getExtraInfo = NULL; - return; - } - - getExtraInfo->iMaxNumLength=iPhBkMaxTelNumLen; - getExtraInfo->iMaxTextLength=iPhBkMaxTextLen; - getExtraInfo->iLocation=RMobilePhoneBookStore::ELocationIccMemory; - getExtraInfo->iChangeCounter=0; - getExtraInfo->iIdentity.Copy(iPhone->GetImsi()); - - getExtraInfo->iPhBkMode.Zero(); - } - else if(aStoreInfo->ExtensionId()==RMobilePhoneStore::KETelMobilePhonebookStoreV5) - { - RMobilePhoneBookStore::TMobilePhoneBookInfoV5* getExtraInfo=(RMobilePhoneBookStore::TMobilePhoneBookInfoV5*)aStoreInfo; - - // Check that the data structure is supported by the simulated TSY version - TInt err = iPhone->CheckSimTsyVersion(*getExtraInfo); - if(err != KErrNone) - { - getExtraInfo = NULL; - return; - } - - getExtraInfo->iMaxNumLength=iPhBkMaxTelNumLen; - getExtraInfo->iMaxTextLength=iPhBkMaxTextLen; - getExtraInfo->iLocation=RMobilePhoneBookStore::ELocationIccMemory; - getExtraInfo->iChangeCounter=0; - getExtraInfo->iIdentity.Copy(iPhone->GetImsi()); - - getExtraInfo->iPhBkMode.Zero(); - - getExtraInfo->iMaxSecondNames = 0; - getExtraInfo->iMaxTextLengthSecondName = 0; - getExtraInfo->iMaxAdditionalNumbers = 0; - getExtraInfo->iMaxTextLengthAdditionalNumber = 0; - getExtraInfo->iMaxNumLengthAdditionalNumber = 0; - getExtraInfo->iMaxGroupNames = 0; - getExtraInfo->iMaxTextLengthGroupName = 0; - getExtraInfo->iMaxEmailAddr = 0; - getExtraInfo->iMaxTextLengthEmailAddr = 0; - } - } - -TInt CSimPhBkStore::Read(TTsyReqHandle aReqHandle, TDes8* aPckg1,TDes8* aPckg2) -/** - * Read Phonebook store entries. The completion of this request is delayed in order to - * simulate a real TSY that would have to go and get the information from a SIM card. - * - * @param aReqHandle The TSY request handle associated with this request. - * @param aPckg1 The first parameter package associated with this request. - * It contains the index from which the read should start and - * the number of entries which should be read. - * @param aPckg2 The second parameter package associated with this request. - * It contains the buffer, which will be populated with the retrieved - * values. - * @return TInt Standard return value. - */ - { - if(iPhone->IsICCLocked()!=EFalse) - { - ReqCompleted(aReqHandle, KErrAccessDenied); - return KErrNone; - } - - TPckg* indexNumPckg=(TPckg*)aPckg1; - RMobilePhoneBookStore::TPBIndexAndNumEntries& indexNum=(*indexNumPckg)(); - - if(indexNum.iNumSlots==iPhBkMaxNumSlots) - { - if (!(iPhBkStoreCaps & static_cast(RMobilePhoneStore::KCapsWholeStore) && iPhBkStoreCaps & RMobilePhoneStore::KCapsReadAccess)) - { - ReqCompleted(aReqHandle, KErrAccessDenied); - return KErrNone; - } - } - else if((indexNum.iIndex+indexNum.iNumSlots - 1)>iPhBkMaxNumSlots) - { - ReqCompleted(aReqHandle,KErrArgument); - return KErrNone; - } - - else if (!(iPhBkStoreCaps & RMobilePhoneStore::KCapsIndividualEntry && iPhBkStoreCaps & RMobilePhoneStore::KCapsReadAccess)) - { - ReqCompleted(aReqHandle, KErrAccessDenied); - return KErrNone; - } - - iPhBkRwBuffer->Set(aPckg2); - - TInt cnt=0; - TInt ret=0; - TBool partial=EFalse; - for(TInt i=indexNum.iIndex;i<=iPhBkMaxNumSlots;i++) - { - if((iPhBkStoreEntries[i].iTelNum.Length()!=0)||(iPhBkStoreEntries[i].iAlphaTag.Length()!=0)) - { - ret=iPhBkRwBuffer->AddNewEntryTag(); - if(ret!=KErrNone) - break; - - partial=ETrue; - ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBAdnIndex,(TUint16)i); - if(ret!=KErrNone) - break; - ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBText,iPhBkStoreEntries[i].iAlphaTag); - if(ret!=KErrNone) - break; - ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBTonNpi,iPhBkStoreEntries[i].iTonNpi); - if(ret!=KErrNone) - break; - ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBNumber,iPhBkStoreEntries[i].iTelNum); - if(ret!=KErrNone) - break; - - partial=EFalse; - if(++cnt>=indexNum.iNumSlots) - break; - } - } - if(partial) - // EXPORT - but return value not relevant - (void)iPhBkRwBuffer->RemovePartialEntry(); - - indexNum.iNumSlots=cnt; - - if((cnt==0)&&(partial)) - ReqCompleted(aReqHandle,KErrArgument); // An entry was found, but the buffer was too small to return it. - else if((cnt==0)&&(!partial)) - ReqCompleted(aReqHandle,KErrNotFound); // No entries found. - else - ReqCompleted(aReqHandle,KErrNone); - - return KErrNone; - } - -TInt CSimPhBkStore::Write(TTsyReqHandle aReqHandle,TDes8* aPckg1,TDes8* aPckg2) -/** - * Write a phonebook store entries. The completion of this request is delayed in order to - * simulate a real TSY that would have to write the information to a SIM card. A store - * event may be triggered by this request. - * - * @param aReqHandle The TSY request handle associated with this request. - * @param aPckg1 The first parameter package associated with this request. - * This contains the TLV phonebook entry to be written. - * @param aPckg2 The second parameter package associated with this request. - * This contains the slot index number to which the entry must be written. - */ - { - if(iPhone->IsICCLocked()!=EFalse) - { - ReqCompleted(aReqHandle, KErrAccessDenied); - return KErrNone; - } - - if (!(iPhBkStoreCaps & RMobilePhoneStore::KCapsIndividualEntry && iPhBkStoreCaps & RMobilePhoneStore::KCapsWriteAccess)) - { - ReqCompleted(aReqHandle, KErrAccessDenied); - return KErrNone; - } - - TPckg* indexPckg=(TPckg*)aPckg2; - TInt& index=(*indexPckg)(); - -// If the index is -1, then use the first available free slot. - if(index==-1) - { - for(TInt i=1;i<=iPhBkMaxNumSlots;i++) - { - if((iPhBkStoreEntries[i].iTelNum.Length()==0)&&(iPhBkStoreEntries[i].iAlphaTag.Length()==0)) - { - index=i; - break; - } - } - } - - if(index==-1) - { - ReqCompleted(aReqHandle,EXTENDEDERROR(KErrNoMemory, KErrPhonebookNoMemory)); - return KErrNone; - } - - if((index<1)||(index>iPhBkMaxNumSlots)) - { - ReqCompleted(aReqHandle,KErrArgument); - return KErrNone; - } - - TBool isSlotAlreadyUsed=EFalse; - if(iPhBkStoreEntries[index].iTelNum.Length()!=0) - isSlotAlreadyUsed=ETrue; - -// Unpick the phonebook entry. - iPhBkRwBuffer->Set(aPckg1); - iPhBkRwBuffer->StartRead(); - - TUint8 tagVal; - TUint8 npiTon=0; - TPtrC alphaTag; - TPtrC telNum; - TPtrC alphaTag2; - TBool skipToNextEntry=EFalse; - CPhoneBookBuffer::TPhBkTagType tagType; - TInt ret=KErrNone; - - while(ret==KErrNone) - { - ret=iPhBkRwBuffer->GetTagAndType(tagVal,tagType); - if(ret==KErrNotFound) - { - ret=KErrNone; - break; - } - else if(ret!=KErrNone) - break; - - - switch(tagVal) - { - case RMobilePhoneBookStore::ETagPBNewEntry: - skipToNextEntry=EFalse; - break; - - case RMobilePhoneBookStore::ETagPBText: - if(!skipToNextEntry) - ret=iPhBkRwBuffer->GetValue(alphaTag); - else - { - TPtrC throwAway; - ret=iPhBkRwBuffer->GetValue(throwAway); - } - break; - - case RMobilePhoneBookStore::ETagPBNumber: - if(!skipToNextEntry) - ret=iPhBkRwBuffer->GetValue(telNum); - else - { - TPtrC throwAway; - ret=iPhBkRwBuffer->GetValue(throwAway); - } - break; - - case RMobilePhoneBookStore::ETagPBTonNpi: - if(!skipToNextEntry) - ret=iPhBkRwBuffer->GetValue(npiTon); - else - { - TUint8 throwAway; - ret=iPhBkRwBuffer->GetValue(throwAway); - } - break; - - // Alexandros - phbksync "shortcut" should be discussed and removed - case RMobilePhoneBookStore::ETagPBAnrStart: - skipToNextEntry=ETrue; - break; - - case RMobilePhoneBookStore::ETagPBEmailAddress: - case RMobilePhoneBookStore::ETagPBGroupName: - case RMobilePhoneBookStore::ETagPBSecondName: - ret=iPhBkRwBuffer->GetValue(alphaTag2); - break; - case RMobilePhoneBookStore::ETagPBHiddenInfo: - TUint8 throwAway; - ret=iPhBkRwBuffer->GetValue(throwAway); - break; - - default: - //DEF001769 - SIM TSY should ignore extra fields in short entries - //ret=KErrNotSupported; - break; - } - } - - if(ret!=KErrNone) - { - ReqCompleted(aReqHandle,ret); - return KErrNone; - } - - LOGPHBK2("alphaTag Length = (%d)",alphaTag.Length()); - LOGPHBK2("Phonebook Max Text Length = (%d)",iPhBkMaxTextLen); - LOGPHBK2("TelNum Length = (%d)",telNum.Length()); - LOGPHBK2("TelNum Max Length = (%d)",iPhBkMaxTelNumLen); - - if(alphaTag.Length()>iPhBkMaxTextLen) - { - ReqCompleted(aReqHandle, EXTENDEDERROR(KErrOverflow, KErrPhonebookTextOverflow)); - return KErrNone; - } - else if(telNum.Length()>iPhBkMaxTelNumLen) - { - ReqCompleted(aReqHandle, EXTENDEDERROR(KErrOverflow, KErrPhonebookNumberOverflow)); - return KErrNone; - } - - iPhBkStoreEntries[index].iAlphaTag.Copy(alphaTag); - iPhBkStoreEntries[index].iTelNum.Copy(telNum); - iPhBkStoreEntries[index].iTonNpi=npiTon; - if(isSlotAlreadyUsed) - DelayCompletion(iPhBkIndividualPause,aReqHandle,EStoreEventChanged,index); - else - DelayCompletion(iPhBkIndividualPause,aReqHandle,EStoreEventAdded,index); - return KErrNone; - } - -TInt CSimPhBkStore::Delete(TTsyReqHandle aReqHandle,TDes8* aPckg) -/** - * Delete a single Phonebook store entry. The completion of this request is delayed in order to - * simulate a real TSY that would have to write the information to a SIM card. A store - * event may be triggered by this request. - * - * @param aReqHandle The TSY request handle associated with this request. - * @param aPckg The parameter package associated with this request. - * @return Standard return value. - */ - { - if(iPhone->IsICCLocked()!=EFalse) - { - ReqCompleted(aReqHandle, KErrAccessDenied); - return KErrNone; - } - - if (!(iPhBkStoreCaps & RMobilePhoneStore::KCapsIndividualEntry && iPhBkStoreCaps & RMobilePhoneStore::KCapsWriteAccess)) - { - ReqCompleted(aReqHandle, KErrAccessDenied); - return KErrNone; - } - - - TPckg* intPckg=(TPckg*)aPckg; - TInt& index=(*intPckg)(); - - if((index<1)||(index>iPhBkMaxNumSlots)) - { - ReqCompleted(aReqHandle,KErrArgument); - return KErrNone; - } - - iPhBkStoreEntries[index].iTelNum.Zero(); - iPhBkStoreEntries[index].iAlphaTag.Zero(); - DelayCompletion(iPhBkIndividualPause,aReqHandle,EStoreEventDeleted,index); - return KErrNone; - } - -TInt CSimPhBkStore::DeleteAll(TTsyReqHandle aReqHandle) -/** - * Delete all entries in the Phonebook Store. The completion of this function is delayed in - * order to simulate the SIM operations a real TSY would have to carry out. This function - * may trigger an Phonebook Store notification. - * - * @param aReqHandle The TSY request handle associated with this request. - * @return Standard return value. - */ - { - if(iPhone->IsICCLocked()!=EFalse) - { - ReqCompleted(aReqHandle, KErrAccessDenied); - return KErrNone; - } - - if (!(iPhBkStoreCaps & static_cast(RMobilePhoneStore::KCapsWholeStore) && iPhBkStoreCaps & RMobilePhoneStore::KCapsWriteAccess)) - { - ReqCompleted(aReqHandle, KErrAccessDenied); - return KErrNone; - } - - for(TInt i=1;i<=iPhBkMaxNumSlots;i++) - { - iPhBkStoreEntries[i].iTelNum.Zero(); - iPhBkStoreEntries[i].iAlphaTag.Zero(); - } - DelayCompletion(iPhBkBatchPause,aReqHandle,EStoreEventDeleted,-1); - return KErrNone; - } - -TInt CSimPhBkStore::NotifyStoreEvent(TTsyReqHandle aReqHandle,TDes8* aPckg1,TDes8* aPckg2) -/** - * Register a client's interest in Phonebook Store events. - * - * @param aReqHandle The TSY request handle associated with this request. - * @param aPckg1 The first parameter package associated with this request. - * It contains the event flags that will be returned to the client. - * @param aPckg2 The second parameter package associated with this request. - * It contains the index value associated with the event - * that will be returned to the client. - * @return Standard return value. - */ - { - TPckg* eventPckg=(TPckg*)aPckg1; - TUint32& event=(*eventPckg)(); - TPckg* indexPckg=(TPckg*)aPckg2; - TInt& index=(*indexPckg)(); - - iEvOutstandingReq=ETrue; - iEvReqHandle=aReqHandle; - iEvEvent=&event; - iEvIndex=&index; - return KErrNone; - } - -void CSimPhBkStore::NotifyStoreEventCancel() -/** - * Cancel an outstanding notify store request. - */ - { - if(iEvOutstandingReq) - { - iEvOutstandingReq=EFalse; - ReqCompleted(iEvReqHandle,KErrCancel); - } - } - -TPtrC8 CSimPhBkStore::Name() -/** - * Accessor function fot the Phonebook Store name. - * - * @return TPtrC8 The name of this Phonebook Store. - */ - { - return iPhBkStoreName; - } - -TInt CSimPhBkStore::UsedEntries() -/** - * Count the number of used entries in the Phonebook Store. - * @return TInt The number of used entries in the store. - */ - { - TInt cnt=0; - for(TInt i=1;i<=iPhBkMaxNumSlots;i++) - { - if((iPhBkStoreEntries[i].iTelNum.Length()!=0)||(iPhBkStoreEntries[i].iAlphaTag.Length()!=0)) - cnt++; - } - return cnt; - } - -TInt CSimPhBkStore::MaxSlots() -/** - * Retrieve the maximum number of slots in this Phonebook Store. - * @return TInt The maximum number of slots in this Phonebook Store. - */ - { - return iPhBkMaxNumSlots; - } - -void CSimPhBkStore::DelayCompletion(TInt aDelayDuration,TTsyReqHandle aReqHandle) -/** - * A shell function for functions that wish to delay completion but do not trigger store - * events. - */ - { - DelayCompletion(aDelayDuration,aReqHandle,EStoreEventNoEvent,0); - } - -void CSimPhBkStore::DelayCompletion(TInt aDelayDuration,TTsyReqHandle aReqHandle,TStoreEvent aEvent,TInt aIndex) -/** - * Delay the completion of a TSY request. It is assumed that the member variable - * manipulation associated with the request has already taken place, and so all that is - * left to do is call the ETel server's request completion function when the timer expires. - * So, just record the parameters and kick off the timer. - * - * @param aDelayDuration The time (in seconds) for which the request completion is to be delayed. - * @param aReqHandle The TSY request handle related to the delayed completion. - * @param aEvent The store event related to the delayed completion. - * @param aIndex The index related to the event passed in aEvent. - */ - { - iPendingReqCompletion=aReqHandle; - iPendingEvent=aEvent; - iPendingIndex=aIndex; - iReqTimer->Start(aDelayDuration,this,ETimerIdPhBkStorReq); - } - -void CSimPhBkStore::TimerCallBack(TInt aId) -/** - * Process a timer call back event. There are three timers associated with this class - * and this callback will be used for all of them. The timers can be identified from the - * aId parameter passed with the callback. - * - * The "Request" timer is used to kick requests which have had their completions delayed. - * The "Out of Band Write" timer is used to schedule a non-client phonebook write. - * The "Out of Band Delete" timer is used to schedule a non-client phonebook delete. - * - * @param aId The Id of the timer to which this callback relates. - */ - { - switch(aId) - { - case ETimerIdPhBkStorReq: - StoreEvent(iPendingEvent,iPendingIndex); - ReqCompleted(iPendingReqCompletion,KErrNone); - break; - - case ETimerIdPhBkStorOOBWrite: - iPhBkStoreEntries[iPhBkOOBWriteIndex].iAlphaTag.Copy(iPhBkOOBWrite.iAlphaTag); - iPhBkStoreEntries[iPhBkOOBWriteIndex].iTelNum.Copy(iPhBkOOBWrite.iTelNum); - iPhBkStoreEntries[iPhBkOOBWriteIndex].iTonNpi=iPhBkOOBWrite.iTonNpi; - StoreEvent(EStoreEventAdded,iPhBkOOBWriteIndex); - break; - - case ETimerIdPhBkStorOOBDelete: - iPhBkStoreEntries[iPhBkOOBDeleteIndex].iAlphaTag.Zero(); - iPhBkStoreEntries[iPhBkOOBDeleteIndex].iTelNum.Zero(); - iPhBkStoreEntries[iPhBkOOBDeleteIndex].iTonNpi=0; - StoreEvent(EStoreEventDeleted,iPhBkOOBDeleteIndex); - break; - - default: - break; - } - } - -void CSimPhBkStore::StoreEvent(TStoreEvent aEvent,TInt aIndex) -/** - * Determine if a store event notification should be completed. - * @param aEvent The store event. - * @param aIndex The index related to the store event. - */ - { - if(iEvOutstandingReq) - { - TUint event=0; - switch(aEvent) - { - case EStoreEventNoEvent: - return; - - case EStoreEventAdded: - event|=RMobilePhoneStore::KStoreEntryAdded; - break; - - case EStoreEventDeleted: - event|=RMobilePhoneStore::KStoreEntryDeleted; - break; - - case EStoreEventChanged: - event|=RMobilePhoneStore::KStoreEntryChanged; - break; - - default: - break; - } - - TInt cnt=UsedEntries(); - if(cnt==0) - event|=RMobilePhoneStore::KStoreEmpty; - - if(cnt==iPhBkMaxNumSlots) - event|=RMobilePhoneStore::KStoreFull; - else - event|=RMobilePhoneStore::KStoreHasSpace; - - *iEvEvent=event; - *iEvIndex=aIndex; - iEvOutstandingReq=EFalse; - ReqCompleted(iEvReqHandle,KErrNone); - } - } - -TBool CSimPhBkStore::FindIpcErrorMatch(TInt& aError) -/** - * Determine whether the IPC counter has signalled that the current request should - * be errored, rather than executed. - * - * @param aError If the function returns ETrue, this parameter will pass back the - * number of the error to be propagated. - * @return TBool Returns ETrue if a match with the IPC count is found, EFalse if not. - */ - { - TInt i; - for(i=0;iCount();i++) - { - TInt pi=iPhBkError->At(i).iCount; - if(pi==iIpcCnt) - { - aError=iPhBkError->At(i).iError; - return ETrue; - } - } - return EFalse; - } - -const CTestConfigSection* CSimPhBkStore::CfgFile() -/** -* Returns a pointer to the config file section -* -* @return CTestConfigSection a pointer to the configuration file data section -*/ - { - LOGPHBK1(">>CSimPhBkStore::CfgFile"); - return iPhone->CfgFile(); - } +// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Implements the Phonebook Store manipulation code. +// +// + +/** + @file +*/ + +#include "CSimPhBkStore.h" +#include "CSimPhone.h" +#include "Simlog.h" +#include + +const TUint16 KNpiTonInternational=145; // < The Number Plan Identifier and Type of Number for an international telephone number. +const TUint16 KNpiTonNational=129; // < The Number Plan Identifier and Type of Number for a national telephone number. +const TInt KPhonebookErrorGranularity=3; // < Granularity of phonebook error list array. +// +// CSimPhBkStore +// +void CSimPhBkStore::ClosePhone(TAny* aObj) +/** + * A utility function for cleaning up the stack. + */ + { + ((CObject*)aObj)->Close(); + } + +CSimPhBkStore* CSimPhBkStore::NewL(CSimPhone* aPhone, const TDesC8& aName, TInt aMaxNumSlots, TInt aMaxNumLen, TInt aMaxTextLen) +/** + * Standard two phase constructor. + * @param aPhone The phone object from which this Phonebook was opened. + * @param aName The name of the created Phonebook. + * @param aMaxNumSlots The maximum number of slots in the Phonebook. + * @return CSimPhBkStore* The newly created object. + */ + { + CSimPhBkStore* store=new(ELeave) CSimPhBkStore(aPhone); + TCleanupItem newObjClose(ClosePhone,store); + CleanupStack::PushL(newObjClose); + store->ConstructL(aName,aMaxNumSlots,aMaxNumLen,aMaxTextLen); + CleanupStack::Pop(); + return store; + } + +CSimPhBkStore::CSimPhBkStore(CSimPhone* aPhone) + : CSimPhone(iDummyPhoneBaseRef), iPhone(aPhone),iIpcCnt(0),iEvOutstandingReq(EFalse) +/** + * Trivial first phase constructor. + * @param aPhone The phone object from which this phonebook was opened. + */ + {} + +void CSimPhBkStore::ConstructL(const TDesC8& aName, TInt aMaxNumSlots, TInt aMaxNumLen, TInt aMaxTextLen) +/** + * Second phase constructor that allocates memory for the phonebook, batch read buffer and + * a delayed completion timer. The constructor also reads the individual and batch read + * delays from the configuration file. + * + * @param aName The name of the created phonebook. + * @param aMaxNumLen The maximum length of a telephone number. + * @param aMaxTextLen The maximum length of an alpha tag. + */ + { + LOGPHBK1("Starting to parse Phonebook store additional config parameters..."); + __ASSERT_ALWAYS(aMaxNumLen<=KPhBkMaxTelNumSize,SimPanic(EPhonebookNameOrNumberTooLarge)); + __ASSERT_ALWAYS(aMaxTextLen<=KPhBkMaxAlphaTagSize,SimPanic(EPhonebookNameOrNumberTooLarge)); + + iPhBkStoreEntries=new(ELeave) TPhBkStoreEntry[aMaxNumSlots+1]; //slot 0 is unused + iPhBkMaxNumSlots=aMaxNumSlots; + iPhBkMaxTelNumLen=aMaxNumLen; + iPhBkMaxTextLen=aMaxTextLen; + iPhBkStoreName.Copy(aName); + + iReqTimer=CSimTimer::NewL(iPhone); + iOOBWriteTimer=CSimTimer::NewL(iPhone); + iOOBDeleteTimer=CSimTimer::NewL(iPhone); + iPhBkRwBuffer=new(ELeave) CPhoneBookBuffer(); + iPhBkError=new(ELeave) CArrayFixFlat(KPhonebookErrorGranularity); + + const CTestConfigItem* item=NULL; + TInt ret=KErrNone; + item=CfgFile()->Item(KTriggerEventIPC,0); + if(item) + { + TInt ipc, cnt, event; + + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,ipc); + if(ret!=KErrNone) + { + LOGPARSERR("ipc",ret,0,&KTriggerEventIPC); + } + else + iTriggerEventIPC.iIPC=ipc; + + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,cnt); + if(ret!=KErrNone) + { + LOGPARSERR("cnt",ret,1,&KTriggerEventIPC); + } + else + iTriggerEventIPC.iIPCCnt=cnt; + + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,event); + if(ret!=KErrNone) + { + LOGPARSERR("event",ret,2,&KTriggerEventIPC); + } + else + iTriggerEventIPC.iEvent=RMobilePhone::TMobilePhoneSecurityEvent(event); + + + } + + const CTestConfigItem* item0=NULL; + item0=CfgFile()->Item(KPhBkPhoneStoreCaps,0); + if (item0) + { + TPtrC8 value0; + TInt ret0=CTestConfig::GetElement(item0->Value(),KStdDelimiter,0,value0); + if(ret0!=KErrNone) + { + iPhBkStoreCaps=KDefaultPhBkPhoneStoreCaps; + LOGPARSERR("value0",ret0,0,&KPhBkPhoneStoreCaps); + } + else + { + TUint32 intValue; + TInt ret = AsciiToNum(value0, intValue); + if(ret!=KErrNone) + iPhBkStoreCaps=KDefaultPhBkPhoneStoreCaps; + else + iPhBkStoreCaps = intValue; + } + } + else + iPhBkStoreCaps=KDefaultPhBkPhoneStoreCaps; + + + LOGPHBK1("...Finished parsing Phonebook store additional config parameters..."); + } + +void CSimPhBkStore::PopulateStoreFromConfigFileL() +/** + * Populate the Phonebook Store from information in the configuration file. This is performed + * after the standard Phonebook Store construction in order to prevent reseting the configuation + * file accessor class' pointers while possibly multiple Phonebook Stores are created. + * + * The store entries comply to the following format: + * "PhBkStoreEntry = , , , " + */ + { + LOGPHBK1("Starting to read Phonebook store entries..."); + iPhBkIndividualPause=CfgFile()->ItemValue(KPhBkStoreIndividualReqPause,KDefaultPhBkStoreIndividualReqPause); + iPhBkBatchPause=CfgFile()->ItemValue(KPhBkStoreBatchReqPause,KDefaultPhBkStoreBatchReqPause); + + TInt count=CfgFile()->ItemCount(KPhBkStoreEntry); + const CTestConfigItem* item=NULL; + TInt ret=KErrNone; + + TInt i; + for(i=0;iItem(KPhBkStoreEntry,i); + if(!item) + break; + + TPtrC8 phonebookName,alphaTag,telNum; + TInt index; + TUint8 npiTon; + ret=GetPhBkEntry(item,0,phonebookName,index,telNum,alphaTag,npiTon); + if(ret!=KErrNone) + { + LOGPARSERR("Phonebook Entry",ret,index,&KPhBkStoreEntry); + continue; + } + if(phonebookName.MatchF(iPhBkStoreName)!=0)// Not this phonebook + continue; + + iPhBkStoreEntries[index].iAlphaTag.Copy(alphaTag); + iPhBkStoreEntries[index].iTelNum.Copy(telNum); + iPhBkStoreEntries[index].iTonNpi=npiTon; + } + + count=CfgFile()->ItemCount(KPhBkError); + item=NULL; + + for(i=0;iItem(KPhBkError,i); + if(!item) + break; + + TInt count,error; + TPtrC8 phonebookName, phonebookStore; + + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,count); + if(ret!=KErrNone) + { + LOGPARSERR("count",ret,0,&KPhBkError); + continue; + } + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,error); + if(ret!=KErrNone) + { + LOGPARSERR("error",ret,1,&KPhBkError); + continue; + } + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,phonebookName); + if(ret!=KErrNone) + { + LOGPARSERR("phonebookName",ret,2,&KPhBkError); + continue; + } + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,phonebookStore); + if(ret!=KErrNone) + { + LOGPARSERR("phonebookStore",ret,3,&KPhBkError); + } + else //not for the global phonebook + continue; + + if(phonebookName.MatchF(iPhBkStoreName)!=0)// Not this phonebook + continue; + + + TPhBkError entry; + entry.iCount=count; + entry.iError=error; + iPhBkError->AppendL(entry); + } + PopulateOOBWrite(); + PopulateOOBDelete(); + LOGPHBK1("...Finished reading Phonebook store entries..."); + + if(iPhBkOOBWriteDuration!=-1) + iOOBWriteTimer->Start(iPhBkOOBWriteDuration,this,ETimerIdPhBkStorOOBWrite); + if(iPhBkOOBDeleteDuration!=-1) + iOOBDeleteTimer->Start(iPhBkOOBDeleteDuration,this,ETimerIdPhBkStorOOBDelete); + } + +void CSimPhBkStore::PopulateOOBWrite() +/** + * Populate the member variables required to operate the OOB Store functionality from + * the configuration file. + * The OOBPhBkStore configuration file tag should have the following format: + * "OOBPhBkStore= , , , , " + */ + { + iPhBkOOBWriteDuration=KErrNotFound; + const CTestConfigItem* item=CfgFile()->Item(KOOBPhBkWrite); + if(!item) + return; + + TInt count; + TInt ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,count); + if(ret!=KErrNone) + { + LOGPARSERR("count",ret,0,&KOOBPhBkWrite); + return; + } + + TPtrC8 phonebookName,alphaTag,telNum; + TInt index; + TUint8 npiTon; + ret=GetPhBkEntry(item,1,phonebookName,index,telNum,alphaTag,npiTon); + if(ret!=KErrNone) + { + LOGPARSERR("npiTon",ret,index,&KOOBPhBkWrite); + return; + } + if(phonebookName.MatchF(iPhBkStoreName)!=0) + return; // Not this phonebook + + iPhBkOOBWriteDuration=count; + iPhBkOOBWriteIndex=index; + iPhBkOOBWrite.iAlphaTag.Copy(alphaTag); + iPhBkOOBWrite.iTelNum.Copy(telNum); + iPhBkOOBWrite.iTonNpi=npiTon; + } + +void CSimPhBkStore::PopulateOOBDelete() +/** + * Populate the member variables required to operate the OOB Delete functionality from + * the configuration file. + * The OOBPhBkDelete configuration file tag should have the following format: + * "OOBPhBkDelete= , , + */ + { + iPhBkOOBDeleteDuration=KErrNotFound; + const CTestConfigItem* item=CfgFile()->Item(KOOBPhBkDelete); + if(!item) + return; + + TInt count; + TInt ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,count); + if(ret!=KErrNone) + { + LOGPARSERR("count",ret,0,&KOOBPhBkDelete); + return; + } + + TPtrC8 phonebookName; + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,phonebookName); + if(ret!=KErrNone) + { + LOGPARSERR("phonebookName",ret,1,&KOOBPhBkDelete); + return; + } + if(phonebookName.MatchF(iPhBkStoreName)!=0) + return; // Not this phonebook + + TInt index; + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,index); + if(ret!=KErrNone) + { + LOGPARSERR("index",ret,2,&KOOBPhBkDelete); + return; + } + + iPhBkOOBDeleteDuration=count; + iPhBkOOBDeleteIndex=index; + } + +TInt CSimPhBkStore::GetPhBkEntry(const CTestConfigItem* aItem, TInt aItemIndex, + TPtrC8& aPhonebookName, TInt& aIndex, + TPtrC8& aTelNum, TPtrC8& aAlphaTag, TUint8& aNpiTon) +/** + * Retrieve a phonebook entry from the configuration file, starting at a given item index + * value. + * @param aItem Pointer to the config file item from which the phonebook entry will be read. + * @param aItemIndex The index number within the item from which the phonebook entry will be read. + * @param aPhonebookName The returned phonebook name + * @param aIndex The returned index number + * @param aTelNum The returned telephone number + * @param aAlphaTag The returned alpha tag + * @param aNpiTon The returned Number Plan Identifier and Type of Number information + * @return TInt Standard error value. + */ + { + TInt ret; + ret=CTestConfig::GetElement(aItem->Value(),KStdDelimiter,aItemIndex++,aPhonebookName); + if(ret!=KErrNone) + return ret; + + ret=CTestConfig::GetElement(aItem->Value(),KStdDelimiter,aItemIndex++,aIndex); + if(ret!=KErrNone) + return ret; + + if(aIndex>iPhBkMaxNumSlots) //the max number of slot is a valid slot + return KErrArgument; + + ret=CTestConfig::GetElement(aItem->Value(),KStdDelimiter,aItemIndex++,aTelNum); + if(ret!=KErrNone) + return ret; + if(aTelNum.Length()>iPhBkMaxTelNumLen) + return KErrArgument; + + ret=CTestConfig::GetElement(aItem->Value(),KStdDelimiter,aItemIndex++,aAlphaTag); + if(ret!=KErrNone) + return ret; + if(aAlphaTag.Length()>iPhBkMaxTextLen) + return KErrArgument; + + if((aTelNum.Length()>0) && (aTelNum[0]=='+')) + { + aTelNum.Set(aTelNum.Mid(1)); + aNpiTon=KNpiTonInternational; + } + else + aNpiTon=KNpiTonNational; + return ret; + } + +CSimPhBkStore::~CSimPhBkStore() +/** + * Standard destructor. Any objects created by the ::ConstructL() function + * will be destroyed here. + */ + { + delete[] iPhBkStoreEntries; + delete iPhBkError; + delete iPhBkRwBuffer; + delete iOOBWriteTimer; + delete iOOBDeleteTimer; + delete iReqTimer; + } + +TInt CSimPhBkStore::ExtFunc(const TTsyReqHandle aReqHandle,const TInt aIpc, const TDataPackage& aPckg) +/** + * Dispatch function for all Phonebook Store requests. + * @param aReqHandle The TSY request handle for this request. + * @param aIpc The IPC number of this request. + * @param aPckg The parameter package related to this request. + * @return TInt The return error condition. + */ + { + iIpcCnt++; + TInt error=KErrNone; + if(FindIpcErrorMatch(error)) + { + ReqCompleted(aReqHandle,error); + return KErrNone; + } + +// The following requests can be completed even if the completion of another request is pending. + switch(aIpc) + { + case EMobilePhoneStoreGetInfo: + error = GetInfo(aReqHandle,aPckg.Des1n()); + if(iTriggerEventIPC.iIPC==aIpc) + { + iTriggerCnt++; + if(iTriggerEventIPC.iIPCCnt==iTriggerCnt) + iPhone->SecurityEvent(iTriggerEventIPC.iEvent); + } + return error; + + case EMobilePhoneStoreNotifyStoreEvent: + error = NotifyStoreEvent(aReqHandle,aPckg.Des1n(),aPckg.Des2n()); + if(iTriggerEventIPC.iIPC==aIpc) + { + iTriggerCnt++; + if(iTriggerEventIPC.iIPCCnt==iTriggerCnt) + iPhone->SecurityEvent(iTriggerEventIPC.iEvent); + } + return error; + + default: + break; + } + + +// The TSY can only process one of the following requests at a time. If a second is received +// while processing the first, then it will be errored with KErrInUse. This restriction will +// be removed later, by inserting a request queuing mechanism. Note that the standard TSY +// "flow control" mechanism works phone-wide and so is not suitable. + + if(iReqTimer->IsActive()) + { + ReqCompleted(aReqHandle,KErrInUse); + return KErrNone; + } + + switch(aIpc) + { +// The standard multimode store read and write are not supported. + case EMobilePhoneStoreRead: + case EMobilePhoneStoreWrite: + case EMobilePhoneStoreReadAllPhase1: + case EMobilePhoneStoreReadAllPhase2: + ReqCompleted(aReqHandle,KErrNotSupported); + return KErrNone; + + case EMobilePhoneBookStoreRead: + error = Read(aReqHandle,aPckg.Des1n(),aPckg.Des2n()); + if(iTriggerEventIPC.iIPC==aIpc) + { + iTriggerCnt++; + if(iTriggerEventIPC.iIPCCnt==iTriggerCnt) + iPhone->SecurityEvent(iTriggerEventIPC.iEvent); + } + return error; + + case EMobilePhoneBookStoreWrite: + error = Write(aReqHandle,aPckg.Des1n(),aPckg.Des2n()); + if(iTriggerEventIPC.iIPC==aIpc) + { + iTriggerCnt++; + if(iTriggerEventIPC.iIPCCnt==iTriggerCnt) + iPhone->SecurityEvent(iTriggerEventIPC.iEvent); + } + return error; + + case EMobilePhoneStoreDelete: + error = Delete(aReqHandle,aPckg.Des1n()); + if(iTriggerEventIPC.iIPC==aIpc) + { + iTriggerCnt++; + if(iTriggerEventIPC.iIPCCnt==iTriggerCnt) + iPhone->SecurityEvent(iTriggerEventIPC.iEvent); + } + return error; + + case EMobilePhoneStoreDeleteAll: + error = DeleteAll(aReqHandle); + if(iTriggerEventIPC.iIPC==aIpc) + { + iTriggerCnt++; + if(iTriggerEventIPC.iIPCCnt==iTriggerCnt) + iPhone->SecurityEvent(iTriggerEventIPC.iEvent); + } + return error; + + default: + break; + } + + return KErrNotSupported; + } + +CTelObject* CSimPhBkStore::OpenNewObjectByNameL(const TDesC& /*aName*/) +/** + * The API does not support any objects that could be opened from this one. + */ + { + User::Leave(KErrNotSupported); + return NULL; + } + +CTelObject* CSimPhBkStore::OpenNewObjectL(TDes&) +/** + * The API does not support any objects that could be opened from this one. + */ + { + User::Leave(KErrNotSupported); + return NULL; + } + +CTelObject::TReqMode CSimPhBkStore::ReqModeL(const TInt aIpc) +/** + * This function returns the Request Mode for the request with the passed IPC value. + * @param aIpc The IPC number of the request. + * @return TReqMode The request mode. + */ + { + CTelObject::TReqMode ret=0; + + switch(aIpc) + { + case EMobilePhoneStoreGetInfo: + case EMobilePhoneStoreDelete: + case EMobilePhoneStoreDeleteAll: + case EMobilePhoneBookStoreRead: + case EMobilePhoneBookStoreWrite: + break; + + case EMobilePhoneStoreNotifyStoreEvent: + ret=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately; + break; + + default: + User::Leave(KErrNotSupported); + break; + } + + return ret; + } + +TInt CSimPhBkStore::RegisterNotification(const TInt /*aIpc*/) +/** + * The ETel Server calls this function when the first client makes a notification + * request. If supported by the underlying protocol controlling the + * signalling stack, this can be used to start requesting updates for the relevant + * service. + */ + { + return KErrNone; + } + +TInt CSimPhBkStore::DeregisterNotification(const TInt /*aIpc*/) +/** + * The ETel Server calls this function when the last client that had previously + * made a notification request closes its ETel Server handle. If supported by + * the underlying protocol controlling the signalling stack, this can be used + * to stop requesting updates for the relevant service. + */ + { + return KErrNone; + } + +TInt CSimPhBkStore::NumberOfSlotsL(const TInt /*aIpc*/) +/** + * Return the number of slots that the ETel Server should allocate for buffering requests + * of the given IPC number. + */ + { + return KDefaultNumberOfSlots; + } + +TInt CSimPhBkStore::CancelService(const TInt aIpc,const TTsyReqHandle /*aTsyReqHandle*/) +/** + * Cancel an outstanding request. + * @param aIpc The IPC number of the request that is to be cancelled. + * @param aTsyReqHandle The TSY request handle of the request that is to be cancelled. + * @param TInt Standard return value. + */ + { + switch(aIpc) + { + case EMobilePhoneStoreGetInfo: + case EMobilePhoneStoreDelete: + case EMobilePhoneStoreDeleteAll: + case EMobilePhoneBookStoreRead: + case EMobilePhoneBookStoreWrite: + break; + + case EMobilePhoneStoreNotifyStoreEvent: + NotifyStoreEventCancel(); + break; + + default: + break; + } + return KErrNone; + } + +void CSimPhBkStore::Init() +/** + * This function can be used to perform any necessary synchronous initialisation. + */ + { + } + +TInt CSimPhBkStore::GetInfo(TTsyReqHandle aReqHandle, TDes8* aPckg) +/** + * Retrieve Phonebook Store information. This request is completed immediately, as it is assumed + * that in a real TSY, all this data will be cached in the TSY. + * + * @param aReqHandle The TSY request handle associated with this request. + * @param aPckg The parameter package associated with this request. + */ + { + + if(iPhone->IsICCLocked()!=EFalse) + { + ReqCompleted(aReqHandle, KErrAccessDenied); + return KErrNone; + } + + RMobilePhoneBookStore::TMobilePhoneBookInfoV1Pckg* getInfoPckg=(RMobilePhoneBookStore::TMobilePhoneBookInfoV1Pckg*)aPckg; + RMobilePhoneBookStore::TMobilePhoneBookInfoV1& getInfo=(*getInfoPckg)(); + + PopulatePhBkStoreInfo(&getInfo); + + if(&getInfo!=NULL) // This will be the case if the version checking within PopulatePhBkStoreInfo has failed. + { + ReqCompleted(aReqHandle,KErrNone); + } + else + { + ReqCompleted(aReqHandle,KErrNotSupported); + } + + return KErrNone; + } + +void CSimPhBkStore::PopulatePhBkStoreInfo(RMobilePhoneStore::TMobilePhoneStoreInfoV1* aStoreInfo) +/** + * Populate the passed parameter with Phonebook Store information. + * @param aStoreInfo Pointer to phonebook store information structure to be populated. + */ + { + __ASSERT_ALWAYS(aStoreInfo, SimPanic(EIllegalNullPtrParameter)); + + aStoreInfo->iType=RMobilePhoneStore::EPhoneBookStore; + aStoreInfo->iTotalEntries=MaxSlots(); + aStoreInfo->iCaps=iPhBkStoreCaps; + aStoreInfo->iName.Copy(iPhBkStoreName); + aStoreInfo->iUsedEntries=UsedEntries(); + + if(aStoreInfo->ExtensionId()==RMobilePhoneStore::KETelMobilePhonebookStoreV1) + { + RMobilePhoneBookStore::TMobilePhoneBookInfoV1* getExtraInfo=(RMobilePhoneBookStore::TMobilePhoneBookInfoV1*)aStoreInfo; + + // Check that the data structure is supported by the simulated TSY version + TInt err = iPhone->CheckSimTsyVersion(*getExtraInfo); + if(err != KErrNone) + { + getExtraInfo = NULL; + return; + } + + getExtraInfo->iMaxNumLength=iPhBkMaxTelNumLen; + getExtraInfo->iMaxTextLength=iPhBkMaxTextLen; + getExtraInfo->iLocation=RMobilePhoneBookStore::ELocationIccMemory; + getExtraInfo->iChangeCounter=0; + getExtraInfo->iIdentity.Copy(iPhone->GetImsi()); + } + else if(aStoreInfo->ExtensionId()==RMobilePhoneStore::KETelMobilePhonebookStoreV2) + { + RMobilePhoneBookStore::TMobilePhoneBookInfoV2* getExtraInfo=(RMobilePhoneBookStore::TMobilePhoneBookInfoV2*)aStoreInfo; + + // Check that the data structure is supported by the simulated TSY version + TInt err = iPhone->CheckSimTsyVersion(*getExtraInfo); + if(err != KErrNone) + { + getExtraInfo = NULL; + return; + } + + getExtraInfo->iMaxNumLength=iPhBkMaxTelNumLen; + getExtraInfo->iMaxTextLength=iPhBkMaxTextLen; + getExtraInfo->iLocation=RMobilePhoneBookStore::ELocationIccMemory; + getExtraInfo->iChangeCounter=0; + getExtraInfo->iIdentity.Copy(iPhone->GetImsi()); + + getExtraInfo->iPhBkMode.Zero(); + } + else if(aStoreInfo->ExtensionId()==RMobilePhoneStore::KETelMobilePhonebookStoreV5) + { + RMobilePhoneBookStore::TMobilePhoneBookInfoV5* getExtraInfo=(RMobilePhoneBookStore::TMobilePhoneBookInfoV5*)aStoreInfo; + + // Check that the data structure is supported by the simulated TSY version + TInt err = iPhone->CheckSimTsyVersion(*getExtraInfo); + if(err != KErrNone) + { + getExtraInfo = NULL; + return; + } + + getExtraInfo->iMaxNumLength=iPhBkMaxTelNumLen; + getExtraInfo->iMaxTextLength=iPhBkMaxTextLen; + getExtraInfo->iLocation=RMobilePhoneBookStore::ELocationIccMemory; + getExtraInfo->iChangeCounter=0; + getExtraInfo->iIdentity.Copy(iPhone->GetImsi()); + + getExtraInfo->iPhBkMode.Zero(); + + getExtraInfo->iMaxSecondNames = 0; + getExtraInfo->iMaxTextLengthSecondName = 0; + getExtraInfo->iMaxAdditionalNumbers = 0; + getExtraInfo->iMaxTextLengthAdditionalNumber = 0; + getExtraInfo->iMaxNumLengthAdditionalNumber = 0; + getExtraInfo->iMaxGroupNames = 0; + getExtraInfo->iMaxTextLengthGroupName = 0; + getExtraInfo->iMaxEmailAddr = 0; + getExtraInfo->iMaxTextLengthEmailAddr = 0; + } + } + +TInt CSimPhBkStore::Read(TTsyReqHandle aReqHandle, TDes8* aPckg1,TDes8* aPckg2) +/** + * Read Phonebook store entries. The completion of this request is delayed in order to + * simulate a real TSY that would have to go and get the information from a SIM card. + * + * @param aReqHandle The TSY request handle associated with this request. + * @param aPckg1 The first parameter package associated with this request. + * It contains the index from which the read should start and + * the number of entries which should be read. + * @param aPckg2 The second parameter package associated with this request. + * It contains the buffer, which will be populated with the retrieved + * values. + * @return TInt Standard return value. + */ + { + if(iPhone->IsICCLocked()!=EFalse) + { + ReqCompleted(aReqHandle, KErrAccessDenied); + return KErrNone; + } + + TPckg* indexNumPckg=(TPckg*)aPckg1; + RMobilePhoneBookStore::TPBIndexAndNumEntries& indexNum=(*indexNumPckg)(); + + if(indexNum.iNumSlots==iPhBkMaxNumSlots) + { + if (!(iPhBkStoreCaps & static_cast(RMobilePhoneStore::KCapsWholeStore) && iPhBkStoreCaps & RMobilePhoneStore::KCapsReadAccess)) + { + ReqCompleted(aReqHandle, KErrAccessDenied); + return KErrNone; + } + } + else if((indexNum.iIndex+indexNum.iNumSlots - 1)>iPhBkMaxNumSlots) + { + ReqCompleted(aReqHandle,KErrArgument); + return KErrNone; + } + + else if (!(iPhBkStoreCaps & RMobilePhoneStore::KCapsIndividualEntry && iPhBkStoreCaps & RMobilePhoneStore::KCapsReadAccess)) + { + ReqCompleted(aReqHandle, KErrAccessDenied); + return KErrNone; + } + + iPhBkRwBuffer->Set(aPckg2); + + TInt cnt=0; + TInt ret=0; + TBool partial=EFalse; + for(TInt i=indexNum.iIndex;i<=iPhBkMaxNumSlots;i++) + { + if((iPhBkStoreEntries[i].iTelNum.Length()!=0)||(iPhBkStoreEntries[i].iAlphaTag.Length()!=0)) + { + ret=iPhBkRwBuffer->AddNewEntryTag(); + if(ret!=KErrNone) + break; + + partial=ETrue; + ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBAdnIndex,(TUint16)i); + if(ret!=KErrNone) + break; + ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBText,iPhBkStoreEntries[i].iAlphaTag); + if(ret!=KErrNone) + break; + ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBTonNpi,iPhBkStoreEntries[i].iTonNpi); + if(ret!=KErrNone) + break; + ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBNumber,iPhBkStoreEntries[i].iTelNum); + if(ret!=KErrNone) + break; + + partial=EFalse; + if(++cnt>=indexNum.iNumSlots) + break; + } + } + if(partial) + // EXPORT - but return value not relevant + (void)iPhBkRwBuffer->RemovePartialEntry(); + + indexNum.iNumSlots=cnt; + + if((cnt==0)&&(partial)) + ReqCompleted(aReqHandle,KErrArgument); // An entry was found, but the buffer was too small to return it. + else if((cnt==0)&&(!partial)) + ReqCompleted(aReqHandle,KErrNotFound); // No entries found. + else + ReqCompleted(aReqHandle,KErrNone); + + return KErrNone; + } + +TInt CSimPhBkStore::Write(TTsyReqHandle aReqHandle,TDes8* aPckg1,TDes8* aPckg2) +/** + * Write a phonebook store entries. The completion of this request is delayed in order to + * simulate a real TSY that would have to write the information to a SIM card. A store + * event may be triggered by this request. + * + * @param aReqHandle The TSY request handle associated with this request. + * @param aPckg1 The first parameter package associated with this request. + * This contains the TLV phonebook entry to be written. + * @param aPckg2 The second parameter package associated with this request. + * This contains the slot index number to which the entry must be written. + */ + { + if(iPhone->IsICCLocked()!=EFalse) + { + ReqCompleted(aReqHandle, KErrAccessDenied); + return KErrNone; + } + + if (!(iPhBkStoreCaps & RMobilePhoneStore::KCapsIndividualEntry && iPhBkStoreCaps & RMobilePhoneStore::KCapsWriteAccess)) + { + ReqCompleted(aReqHandle, KErrAccessDenied); + return KErrNone; + } + + TPckg* indexPckg=(TPckg*)aPckg2; + TInt& index=(*indexPckg)(); + +// If the index is -1, then use the first available free slot. + if(index==-1) + { + for(TInt i=1;i<=iPhBkMaxNumSlots;i++) + { + if((iPhBkStoreEntries[i].iTelNum.Length()==0)&&(iPhBkStoreEntries[i].iAlphaTag.Length()==0)) + { + index=i; + break; + } + } + } + + if(index==-1) + { + ReqCompleted(aReqHandle,EXTENDEDERROR(KErrNoMemory, KErrPhonebookNoMemory)); + return KErrNone; + } + + if((index<1)||(index>iPhBkMaxNumSlots)) + { + ReqCompleted(aReqHandle,KErrArgument); + return KErrNone; + } + + TBool isSlotAlreadyUsed=EFalse; + if(iPhBkStoreEntries[index].iTelNum.Length()!=0) + isSlotAlreadyUsed=ETrue; + +// Unpick the phonebook entry. + iPhBkRwBuffer->Set(aPckg1); + iPhBkRwBuffer->StartRead(); + + TUint8 tagVal; + TUint8 npiTon=0; + TPtrC alphaTag; + TPtrC telNum; + TPtrC alphaTag2; + TBool skipToNextEntry=EFalse; + CPhoneBookBuffer::TPhBkTagType tagType; + TInt ret=KErrNone; + + while(ret==KErrNone) + { + ret=iPhBkRwBuffer->GetTagAndType(tagVal,tagType); + if(ret==KErrNotFound) + { + ret=KErrNone; + break; + } + else if(ret!=KErrNone) + break; + + + switch(tagVal) + { + case RMobilePhoneBookStore::ETagPBNewEntry: + skipToNextEntry=EFalse; + break; + + case RMobilePhoneBookStore::ETagPBText: + if(!skipToNextEntry) + ret=iPhBkRwBuffer->GetValue(alphaTag); + else + { + TPtrC throwAway; + ret=iPhBkRwBuffer->GetValue(throwAway); + } + break; + + case RMobilePhoneBookStore::ETagPBNumber: + if(!skipToNextEntry) + ret=iPhBkRwBuffer->GetValue(telNum); + else + { + TPtrC throwAway; + ret=iPhBkRwBuffer->GetValue(throwAway); + } + break; + + case RMobilePhoneBookStore::ETagPBTonNpi: + if(!skipToNextEntry) + ret=iPhBkRwBuffer->GetValue(npiTon); + else + { + TUint8 throwAway; + ret=iPhBkRwBuffer->GetValue(throwAway); + } + break; + + // Alexandros - phbksync "shortcut" should be discussed and removed + case RMobilePhoneBookStore::ETagPBAnrStart: + skipToNextEntry=ETrue; + break; + + case RMobilePhoneBookStore::ETagPBEmailAddress: + case RMobilePhoneBookStore::ETagPBGroupName: + case RMobilePhoneBookStore::ETagPBSecondName: + ret=iPhBkRwBuffer->GetValue(alphaTag2); + break; + case RMobilePhoneBookStore::ETagPBHiddenInfo: + TUint8 throwAway; + ret=iPhBkRwBuffer->GetValue(throwAway); + break; + + default: + //DEF001769 - SIM TSY should ignore extra fields in short entries + //ret=KErrNotSupported; + break; + } + } + + if(ret!=KErrNone) + { + ReqCompleted(aReqHandle,ret); + return KErrNone; + } + + LOGPHBK2("alphaTag Length = (%d)",alphaTag.Length()); + LOGPHBK2("Phonebook Max Text Length = (%d)",iPhBkMaxTextLen); + LOGPHBK2("TelNum Length = (%d)",telNum.Length()); + LOGPHBK2("TelNum Max Length = (%d)",iPhBkMaxTelNumLen); + + if(alphaTag.Length()>iPhBkMaxTextLen) + { + ReqCompleted(aReqHandle, EXTENDEDERROR(KErrOverflow, KErrPhonebookTextOverflow)); + return KErrNone; + } + else if(telNum.Length()>iPhBkMaxTelNumLen) + { + ReqCompleted(aReqHandle, EXTENDEDERROR(KErrOverflow, KErrPhonebookNumberOverflow)); + return KErrNone; + } + + iPhBkStoreEntries[index].iAlphaTag.Copy(alphaTag); + iPhBkStoreEntries[index].iTelNum.Copy(telNum); + iPhBkStoreEntries[index].iTonNpi=npiTon; + if(isSlotAlreadyUsed) + DelayCompletion(iPhBkIndividualPause,aReqHandle,EStoreEventChanged,index); + else + DelayCompletion(iPhBkIndividualPause,aReqHandle,EStoreEventAdded,index); + return KErrNone; + } + +TInt CSimPhBkStore::Delete(TTsyReqHandle aReqHandle,TDes8* aPckg) +/** + * Delete a single Phonebook store entry. The completion of this request is delayed in order to + * simulate a real TSY that would have to write the information to a SIM card. A store + * event may be triggered by this request. + * + * @param aReqHandle The TSY request handle associated with this request. + * @param aPckg The parameter package associated with this request. + * @return Standard return value. + */ + { + if(iPhone->IsICCLocked()!=EFalse) + { + ReqCompleted(aReqHandle, KErrAccessDenied); + return KErrNone; + } + + if (!(iPhBkStoreCaps & RMobilePhoneStore::KCapsIndividualEntry && iPhBkStoreCaps & RMobilePhoneStore::KCapsWriteAccess)) + { + ReqCompleted(aReqHandle, KErrAccessDenied); + return KErrNone; + } + + + TPckg* intPckg=(TPckg*)aPckg; + TInt& index=(*intPckg)(); + + if((index<1)||(index>iPhBkMaxNumSlots)) + { + ReqCompleted(aReqHandle,KErrArgument); + return KErrNone; + } + + iPhBkStoreEntries[index].iTelNum.Zero(); + iPhBkStoreEntries[index].iAlphaTag.Zero(); + DelayCompletion(iPhBkIndividualPause,aReqHandle,EStoreEventDeleted,index); + return KErrNone; + } + +TInt CSimPhBkStore::DeleteAll(TTsyReqHandle aReqHandle) +/** + * Delete all entries in the Phonebook Store. The completion of this function is delayed in + * order to simulate the SIM operations a real TSY would have to carry out. This function + * may trigger an Phonebook Store notification. + * + * @param aReqHandle The TSY request handle associated with this request. + * @return Standard return value. + */ + { + if(iPhone->IsICCLocked()!=EFalse) + { + ReqCompleted(aReqHandle, KErrAccessDenied); + return KErrNone; + } + + if (!(iPhBkStoreCaps & static_cast(RMobilePhoneStore::KCapsWholeStore) && iPhBkStoreCaps & RMobilePhoneStore::KCapsWriteAccess)) + { + ReqCompleted(aReqHandle, KErrAccessDenied); + return KErrNone; + } + + for(TInt i=1;i<=iPhBkMaxNumSlots;i++) + { + iPhBkStoreEntries[i].iTelNum.Zero(); + iPhBkStoreEntries[i].iAlphaTag.Zero(); + } + DelayCompletion(iPhBkBatchPause,aReqHandle,EStoreEventDeleted,-1); + return KErrNone; + } + +TInt CSimPhBkStore::NotifyStoreEvent(TTsyReqHandle aReqHandle,TDes8* aPckg1,TDes8* aPckg2) +/** + * Register a client's interest in Phonebook Store events. + * + * @param aReqHandle The TSY request handle associated with this request. + * @param aPckg1 The first parameter package associated with this request. + * It contains the event flags that will be returned to the client. + * @param aPckg2 The second parameter package associated with this request. + * It contains the index value associated with the event + * that will be returned to the client. + * @return Standard return value. + */ + { + TPckg* eventPckg=(TPckg*)aPckg1; + TUint32& event=(*eventPckg)(); + TPckg* indexPckg=(TPckg*)aPckg2; + TInt& index=(*indexPckg)(); + + iEvOutstandingReq=ETrue; + iEvReqHandle=aReqHandle; + iEvEvent=&event; + iEvIndex=&index; + return KErrNone; + } + +void CSimPhBkStore::NotifyStoreEventCancel() +/** + * Cancel an outstanding notify store request. + */ + { + if(iEvOutstandingReq) + { + iEvOutstandingReq=EFalse; + ReqCompleted(iEvReqHandle,KErrCancel); + } + } + +TPtrC8 CSimPhBkStore::Name() +/** + * Accessor function fot the Phonebook Store name. + * + * @return TPtrC8 The name of this Phonebook Store. + */ + { + return iPhBkStoreName; + } + +TInt CSimPhBkStore::UsedEntries() +/** + * Count the number of used entries in the Phonebook Store. + * @return TInt The number of used entries in the store. + */ + { + TInt cnt=0; + for(TInt i=1;i<=iPhBkMaxNumSlots;i++) + { + if((iPhBkStoreEntries[i].iTelNum.Length()!=0)||(iPhBkStoreEntries[i].iAlphaTag.Length()!=0)) + cnt++; + } + return cnt; + } + +TInt CSimPhBkStore::MaxSlots() +/** + * Retrieve the maximum number of slots in this Phonebook Store. + * @return TInt The maximum number of slots in this Phonebook Store. + */ + { + return iPhBkMaxNumSlots; + } + +void CSimPhBkStore::DelayCompletion(TInt aDelayDuration,TTsyReqHandle aReqHandle) +/** + * A shell function for functions that wish to delay completion but do not trigger store + * events. + */ + { + DelayCompletion(aDelayDuration,aReqHandle,EStoreEventNoEvent,0); + } + +void CSimPhBkStore::DelayCompletion(TInt aDelayDuration,TTsyReqHandle aReqHandle,TStoreEvent aEvent,TInt aIndex) +/** + * Delay the completion of a TSY request. It is assumed that the member variable + * manipulation associated with the request has already taken place, and so all that is + * left to do is call the ETel server's request completion function when the timer expires. + * So, just record the parameters and kick off the timer. + * + * @param aDelayDuration The time (in seconds) for which the request completion is to be delayed. + * @param aReqHandle The TSY request handle related to the delayed completion. + * @param aEvent The store event related to the delayed completion. + * @param aIndex The index related to the event passed in aEvent. + */ + { + iPendingReqCompletion=aReqHandle; + iPendingEvent=aEvent; + iPendingIndex=aIndex; + iReqTimer->Start(aDelayDuration,this,ETimerIdPhBkStorReq); + } + +void CSimPhBkStore::TimerCallBack(TInt aId) +/** + * Process a timer call back event. There are three timers associated with this class + * and this callback will be used for all of them. The timers can be identified from the + * aId parameter passed with the callback. + * + * The "Request" timer is used to kick requests which have had their completions delayed. + * The "Out of Band Write" timer is used to schedule a non-client phonebook write. + * The "Out of Band Delete" timer is used to schedule a non-client phonebook delete. + * + * @param aId The Id of the timer to which this callback relates. + */ + { + switch(aId) + { + case ETimerIdPhBkStorReq: + StoreEvent(iPendingEvent,iPendingIndex); + ReqCompleted(iPendingReqCompletion,KErrNone); + break; + + case ETimerIdPhBkStorOOBWrite: + iPhBkStoreEntries[iPhBkOOBWriteIndex].iAlphaTag.Copy(iPhBkOOBWrite.iAlphaTag); + iPhBkStoreEntries[iPhBkOOBWriteIndex].iTelNum.Copy(iPhBkOOBWrite.iTelNum); + iPhBkStoreEntries[iPhBkOOBWriteIndex].iTonNpi=iPhBkOOBWrite.iTonNpi; + StoreEvent(EStoreEventAdded,iPhBkOOBWriteIndex); + break; + + case ETimerIdPhBkStorOOBDelete: + iPhBkStoreEntries[iPhBkOOBDeleteIndex].iAlphaTag.Zero(); + iPhBkStoreEntries[iPhBkOOBDeleteIndex].iTelNum.Zero(); + iPhBkStoreEntries[iPhBkOOBDeleteIndex].iTonNpi=0; + StoreEvent(EStoreEventDeleted,iPhBkOOBDeleteIndex); + break; + + default: + break; + } + } + +void CSimPhBkStore::StoreEvent(TStoreEvent aEvent,TInt aIndex) +/** + * Determine if a store event notification should be completed. + * @param aEvent The store event. + * @param aIndex The index related to the store event. + */ + { + if(iEvOutstandingReq) + { + TUint event=0; + switch(aEvent) + { + case EStoreEventNoEvent: + return; + + case EStoreEventAdded: + event|=RMobilePhoneStore::KStoreEntryAdded; + break; + + case EStoreEventDeleted: + event|=RMobilePhoneStore::KStoreEntryDeleted; + break; + + case EStoreEventChanged: + event|=RMobilePhoneStore::KStoreEntryChanged; + break; + + default: + break; + } + + TInt cnt=UsedEntries(); + if(cnt==0) + event|=RMobilePhoneStore::KStoreEmpty; + + if(cnt==iPhBkMaxNumSlots) + event|=RMobilePhoneStore::KStoreFull; + else + event|=RMobilePhoneStore::KStoreHasSpace; + + *iEvEvent=event; + *iEvIndex=aIndex; + iEvOutstandingReq=EFalse; + ReqCompleted(iEvReqHandle,KErrNone); + } + } + +TBool CSimPhBkStore::FindIpcErrorMatch(TInt& aError) +/** + * Determine whether the IPC counter has signalled that the current request should + * be errored, rather than executed. + * + * @param aError If the function returns ETrue, this parameter will pass back the + * number of the error to be propagated. + * @return TBool Returns ETrue if a match with the IPC count is found, EFalse if not. + */ + { + TInt i; + for(i=0;iCount();i++) + { + TInt pi=iPhBkError->At(i).iCount; + if(pi==iIpcCnt) + { + aError=iPhBkError->At(i).iError; + return ETrue; + } + } + return EFalse; + } + +const CTestConfigSection* CSimPhBkStore::CfgFile() +/** +* Returns a pointer to the config file section +* +* @return CTestConfigSection a pointer to the configuration file data section +*/ + { + LOGPHBK1(">>CSimPhBkStore::CfgFile"); + return iPhone->CfgFile(); + }