diff -r 000000000000 -r 3553901f7fa8 telephonyserverplugins/simtsy/src/CSimPhBkUsimStore.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/telephonyserverplugins/simtsy/src/CSimPhBkUsimStore.cpp Tue Feb 02 01:41:59 2010 +0200 @@ -0,0 +1,2297 @@ +// 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 "CSimPhBkUsimStore.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 KMaxGroups = 10; // < The maximum allowed number of groups associated with a phonebook entry +const TInt KMaxSecondNames = 1; // < The maximum allowed number of Second Names associated with a phonebook entry +const TInt KPhonebookErrorGranularity=3; // < Granularity of phonebook error list array. +const TUint DELETED=0xdededede; +// +// CSimPhBkUSimStore +// +void CSimPhBkUSimStore::ClosePhone(TAny* aObj) +/** + * A utility function for cleaning up the stack. + */ + { + ((CObject*)aObj)->Close(); + } + +CSimPhBkUSimStore* CSimPhBkUSimStore::NewL(CSimPhone* aPhone, const TDesC8& aStore, const TDesC8& aName, TInt aMaxNumSlots, TInt aMaxNumLen, TInt aMaxTextLen, TInt aAdditional, TInt aMaxEmail, TInt aMaxAdditionalTelNumLen, TInt aMaxAdditionalTextLen) +/** + * 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. + * @param aMaxNumLen The maximum length of the telephone number (<100) + * @param aMaxTextLen The maximum length of the alpha text strings (<100) + * @param aAdditional The maximum number of additional numbers associated with an entry + * @param aMaxEmail The maximum number of email addresses associated with an entry + * @param aMaxAdditionalTelNumLen The maximum length of the an additional telephone number. + * @param aMaxAdditionalTextLen The maximum length of the alpha tag in an additional telephone number. + * @return CSimPhBkUSimStore* The newly created object. + */ + { + CSimPhBkUSimStore* store=new(ELeave) CSimPhBkUSimStore(aPhone); + TCleanupItem newObjClose(ClosePhone,store); + CleanupStack::PushL(newObjClose); + store->ConstructL(aStore,aName,aMaxNumSlots,aMaxNumLen,aMaxTextLen,aAdditional,aMaxEmail, aMaxAdditionalTelNumLen, aMaxAdditionalTextLen); + CleanupStack::Pop(); + return store; + } + +CSimPhBkUSimStore::CSimPhBkUSimStore(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 CSimPhBkUSimStore::ConstructL(const TDesC8& aStore, const TDesC8& aName, TInt aMaxNumSlots, TInt aMaxNumLen, TInt aMaxTextLen, TInt aAdditional, TInt aMaxEmail, TInt aMaxAdditionalTelNumLen, TInt aMaxAdditionalTextLen) +/** + * 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. + * @param aMaxNumLen The maximum length of the telephone number (<100). + * @param aMaxTextLen The maximum length of the alpha text strings (<100). + * @param aAdditional The maximum number of additional numbers associated with an entry. + * @param aMaxEmail The maximum number of email addresses associated with an entry. + * @param aMaxAdditionalTelNumLen The maximum length of the an additional telephone number. + * @param aMaxAdditionalTextLen The maximum length of the alpha tag in an additional telephone number. + */ + { + LOGPHBK1("Starting to parse Phonebook store additional config parameters..."); + __ASSERT_ALWAYS(aMaxNumLen<=KPhBkMaxTelNumSize,SimPanic(EPhonebookNameOrNumberTooLarge)); + __ASSERT_ALWAYS(aMaxTextLen<=KPhBkMaxAlphaTagSize,SimPanic(EPhonebookNameOrNumberTooLarge)); + + iPhBkMaxNumSlots=aMaxNumSlots; + iPhBkMaxTelNumLen=aMaxNumLen; + iPhBkMaxTextLen=aMaxTextLen; + iPhBkStoreName.Copy(aName); + iPhBkStore.Copy(aStore); + iPhBkAdditional=aAdditional; + iPhBkMaxEmail=aMaxEmail; + iPhBkMaxAdditionalTelNumLen = aMaxAdditionalTelNumLen; + iPhBkMaxAdditionalTextLen = aMaxAdditionalTextLen; + + iPhBkAid.Zero(); + iPhBkAidUSim1.Zero(); + iPhBkAidUSim2.Zero(); + + if(iPhBkStore.Compare(KUSimPhoneBook)==KErrNone) + { + iPhBkUSim1StoreEntries=new(ELeave) TPhBkUSimStoreEntry[aMaxNumSlots+1]; //slot 0 is unused + iPhBkUSim2StoreEntries=new(ELeave) TPhBkUSimStoreEntry[aMaxNumSlots+1]; //slot 0 is unused + } + else + { + iPhBkUSim1StoreEntries=new(ELeave) TPhBkUSimStoreEntry[aMaxNumSlots+1]; //slot 0 is unused + iPhBkUSimStoreEntries=iPhBkUSim1StoreEntries; + } + + 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; + TInt count=CfgFile()->ItemCount(KPhBkPhoneUSimStoreCaps); + + if(count==0) + iPhBkStoreCaps=KDefaultPhBkPhoneStoreCaps; + else + { + TBool capsFound=EFalse; + for(TInt i=0;(iItem(KPhBkPhoneUSimStoreCaps,i); + + if (item0) + { + TPtrC8 value0,phonebookStore, phonebookName; + TInt ret0; + + ret0=CTestConfig::GetElement(item0->Value(),KStdDelimiter,0,phonebookStore); + if(ret0!=KErrNone) + { + iPhBkStoreCaps=KDefaultPhBkPhoneStoreCaps; + LOGPARSERR("Caps:PhonebookStore",ret,0,&KPhBkPhoneUSimStoreCaps); + } + + if(phonebookStore.MatchF(iPhBkStore)!=0)// Not this PhBkStore type + continue; + + ret0=CTestConfig::GetElement(item0->Value(),KStdDelimiter,1,phonebookName); + if(ret0!=KErrNone) + { + iPhBkStoreCaps=KDefaultPhBkPhoneStoreCaps; + LOGPARSERR("phonebookName",ret,1,&KPhBkPhoneUSimStoreCaps); + } + + if(phonebookName.MatchF(iPhBkStoreName)!=0)// Not this PhBkStoreName type + continue; + + ret0=CTestConfig::GetElement(item0->Value(),KStdDelimiter,2,value0); + if(ret0!=KErrNone) + { + iPhBkStoreCaps=KDefaultPhBkPhoneStoreCaps; + LOGPARSERR("caps",ret,2,&KPhBkPhoneUSimStoreCaps); + } + else + { + TUint32 intValue; + TInt ret = AsciiToNum(value0, intValue); + if(ret!=KErrNone) + iPhBkStoreCaps=KDefaultPhBkPhoneStoreCaps; + else + { + iPhBkStoreCaps = intValue; + capsFound=ETrue; + } + } + + } + } + } + LOGPHBK1("...Finished parsing Phonebook store additional config parameters..."); + } + +void CSimPhBkUSimStore::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. +//alex + * + * 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); + + const CTestConfigItem* item=NULL; + TInt ret=KErrNone; + + TInt i; + + // Get Phonebook entries + TInt count=CfgFile()->ItemCount(KPhBkUSimStoreEntry); + for(i=0;iItem(KPhBkUSimStoreEntry,i); + if(!item) + break; + + TPtrC8 phonebookStore,aid, phonebookName,alphaTag,telNum,alphaTag2,emails, groups, additional; + TInt index; + TUint8 npiTon; + ret=GetPhBkUSimEntry(item,parseIndex,phonebookStore,phonebookName,aid,index,telNum,alphaTag,npiTon,alphaTag2); + if(ret!=KErrNone) + { + LOGPARSERR("Phonebook Entry",ret,index,&KPhBkUSimStoreEntry); + continue; + } + + if(phonebookStore.MatchF(iPhBkStore)!=0)// Not this PhBkStore type + continue; + else if(phonebookName.MatchF(iPhBkStoreName)!=0)// Not this phonebook + continue; + + if(phonebookStore.MatchF(KUSimPhoneBook)==0 && + iPhBkAid.Length()==0) //starting up + { + iPhBkAid.Copy(aid); + iPhBkAidUSim1.Copy(aid); + iPhBkUSimStoreEntries=iPhBkUSim1StoreEntries; + } + + else if(phonebookStore.MatchF(KUSimPhoneBook)==0 && + iPhBkAid.Length()!=0 && iPhBkAid.Compare(aid)!=KErrNone) + { + if(iPhBkAidUSim2.Length()==0) + { + iPhBkAid.Copy(aid); + iPhBkAidUSim2.Copy(aid); + iPhBkUSimStoreEntries=iPhBkUSim2StoreEntries; + } + else if(iPhBkAidUSim2.Compare(aid)==KErrNone) + { + iPhBkAid.Copy(aid); + iPhBkUSimStoreEntries=iPhBkUSim2StoreEntries; + } + else if(iPhBkAidUSim2.Compare(aid)!=KErrNone) + //Currently there is support for only 2 USim phonebooks + {continue;} //...so, a possible third one will be ignored!!! + } + + iPhBkUSimStoreEntries[index].iAlphaTag.Copy(alphaTag); + iPhBkUSimStoreEntries[index].iTelNum.Copy(telNum); + iPhBkUSimStoreEntries[index].iTonNpi=npiTon; + iPhBkUSimStoreEntries[index].iAlphaTag2.Copy(alphaTag2); + + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,parseIndex++,additional); + if(ret!=KErrNone) + { + LOGPARSERR("additional",ret,parseIndex,&KPhBkUSimStoreEntry); + } + else + { + TPtrC8 myName,myNum; + TUint8 myTon; + TInt myindex=0,pIndex=0; + iPhBkUSimStoreEntries[index].iAdditional=new(ELeave) CArrayFixFlat(iPhBkAdditional+1); + + while((GetPhBkAdditionalEntry(additional,pIndex,myNum,myName,myTon)==KErrNone) + && (myindex < iPhBkAdditional)) + { + TPhBkStoreEntry entry; + + entry.iAlphaTag.Copy(myName); + entry.iTelNum.Copy(myNum); + entry.iTonNpi=myTon; + TRAP_IGNORE(iPhBkUSimStoreEntries[index].iAdditional->AppendL(entry)); + + myindex++; + } + + } + + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,parseIndex++,emails); + if(ret!=KErrNone) + { + LOGPARSERR("emails",ret,parseIndex,&KPhBkUSimStoreEntry); + } + else + { + TPtrC8 myemail; + TInt myindex=0; + iPhBkUSimStoreEntries[index].iEmails=new(ELeave) CArrayFixFlat(iPhBkMaxEmail+1); + + while((CTestConfig::GetElement(emails,';',myindex,myemail)==KErrNone) && + (myindex < iPhBkMaxEmail)) + { + TPhBkUSimEmail entry; + entry.Copy(myemail); + TRAP_IGNORE(iPhBkUSimStoreEntries[index].iEmails->AppendL(entry)); + myindex++; + } + } + + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,parseIndex++,groups); + if(ret!=KErrNone) + { + LOGPARSERR("groups",ret,parseIndex,&KPhBkUSimStoreEntry); + } + else + { + + TPtrC8 mygroup; + TInt myindex=0; + iPhBkUSimStoreEntries[index].iGroups=new(ELeave) CArrayFixFlat(KMaxGroups+1); + + + while((CTestConfig::GetElement(groups,';',myindex,mygroup)==KErrNone) && + (myindex < KMaxGroups)) + { + TPhBkUSimGroup entry; + entry.Copy(mygroup); + TRAP_IGNORE(iPhBkUSimStoreEntries[index].iGroups->AppendL(entry)); + myindex++; + } + } + + TBool hidden; + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,parseIndex++,hidden); + if(ret!=KErrNone) + { + LOGPARSERR("emails",ret,parseIndex,&KPhBkUSimStoreEntry); + } + else + iPhBkUSimStoreEntries[index].iHiddenEntry=hidden; + + } + + 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); + //global phonebook error + continue; + } + + if(phonebookName.MatchF(iPhBkStoreName)!=0)// Not this phonebook + continue; + else if(phonebookStore.MatchF(iPhBkStore)!=0)// Not this phonebook + continue; + + TPhBkError entry; + entry.iCount=count; + entry.iError=error; + TRAP_IGNORE(iPhBkError->AppendL(entry)); + } + PopulateOOBWrite(); + PopulateOOBDelete(); + LOGPHBK1("...Finished reading Phonebook store entries..."); + + if(iPhBkOOBWriteDuration!=-1) + iOOBWriteTimer->Start(iPhBkOOBWriteDuration,this,ETimerIdPhBkUSimStorOOBWrite); + if(iPhBkOOBDeleteDuration!=-1) + iOOBDeleteTimer->Start(iPhBkOOBDeleteDuration,this,ETimerIdPhBkUSimStorOOBDelete); + } + +void CSimPhBkUSimStore::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= , , , , " + */ + { + TInt parseIndex=0; + iPhBkOOBWriteDuration=KErrNotFound; + const CTestConfigItem* item=CfgFile()->Item(KOOBPhBkUSimWrite); + if(!item) + return; + + TInt count; + TInt ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,parseIndex++,count); + if(ret!=KErrNone) + { + LOGPARSERR("count",ret,parseIndex,&KOOBPhBkUSimWrite); + return; + } + + TPtrC8 phonebookStore,aid, phonebookName,alphaTag,telNum,alphaTag2,emails, groups, additional; + TInt index; + TUint8 npiTon; + ret=GetPhBkUSimEntry(item,parseIndex,phonebookStore,phonebookName,aid,index,telNum,alphaTag,npiTon,alphaTag2); + if(ret!=KErrNone) + { + LOGPARSERR("Phonebook Entry",ret,parseIndex,&KOOBPhBkUSimWrite); + return; + } + + if(phonebookStore.MatchF(iPhBkStore)!=0)// Not this PhBkStore type + return; + else if(phonebookName.MatchF(iPhBkStoreName)!=0)// Not this phonebook + return; + + iPhBkOOBWriteDuration=count; + iPhBkOOBWriteIndex=index; + iPhBkOOBWrite.iAlphaTag.Copy(alphaTag); + iPhBkOOBWrite.iTelNum.Copy(telNum); + iPhBkOOBWrite.iTonNpi=npiTon; + iPhBkOOBWrite.iAlphaTag2.Copy(alphaTag2); + + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,parseIndex++,additional); + if(ret!=KErrNone) + { + LOGPARSERR("additional",ret,parseIndex,&KOOBPhBkUSimWrite); + } + else + { + TPtrC8 myName,myNum; + TUint8 myTon; + TInt myindex=0,pIndex=0; + + TRAPD(err,iPhBkOOBWrite.iAdditional=new(ELeave) CArrayFixFlat(iPhBkAdditional+1)); + if (err!=KErrNone) + return; + while((GetPhBkAdditionalEntry(additional,pIndex,myNum,myName,myTon)==KErrNone) + && (myindex < iPhBkAdditional)) + { + TPhBkStoreEntry entry; + + entry.iAlphaTag.Copy(myName); + entry.iTelNum.Copy(myNum); + entry.iTonNpi=myTon; + TRAP_IGNORE(iPhBkOOBWrite.iAdditional->AppendL(entry)); + myindex++; + } + } + + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,parseIndex++,groups); + if(ret!=KErrNone) + { + LOGPARSERR("groups",ret,parseIndex,&KOOBPhBkUSimWrite); + } + else + { + TPtrC8 mygroup; + TInt myindex=0; + + TRAPD(err,iPhBkOOBWrite.iGroups=new(ELeave) CArrayFixFlat(KMaxGroups+1)); + if (err!=KErrNone) + return; + while((CTestConfig::GetElement(groups,';',myindex,mygroup)==KErrNone) && + (myindex < KMaxGroups)) + { + TPhBkUSimGroup entry; + entry.Copy(mygroup); + TRAP_IGNORE(iPhBkOOBWrite.iGroups->AppendL(entry)); + myindex++; + } + } + + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,parseIndex++,emails); + if(ret!=KErrNone) + { + LOGPARSERR("emails",ret,parseIndex,&KOOBPhBkUSimWrite); + } + else + { + TPtrC8 myemail; + TInt myindex=0; + + TRAPD(err,iPhBkOOBWrite.iEmails=new(ELeave) CArrayFixFlat(iPhBkMaxEmail+1)); + if (err!=KErrNone) + return; + + while((CTestConfig::GetElement(emails,';',myindex,myemail)==KErrNone) && + (myindex < iPhBkMaxEmail)) + { + TPhBkUSimEmail entry; + entry.Copy(myemail); + TRAP_IGNORE(iPhBkOOBWrite.iEmails->AppendL(entry)); + myindex++; + } + } + + } + +void CSimPhBkUSimStore::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(KOOBPhBkUSimDelete); + if(!item) + return; + + TInt count; + TInt ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,count); + if(ret!=KErrNone) + { + LOGPARSERR("count",ret,0,&KOOBPhBkUSimDelete); + return; + } + + TPtrC8 phonebookName, phonebookStore; + + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,phonebookStore); + if(ret!=KErrNone) + { + LOGPARSERR("phonebookStore",ret,1,&KOOBPhBkUSimDelete); + return; + } + + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,phonebookName); + if(ret!=KErrNone) + { + LOGPARSERR("phonebookName",ret,2,&KOOBPhBkUSimDelete); + return; + } + + if(phonebookStore.MatchF(iPhBkStore)!=0) + return; // Not this store + else if(phonebookName.MatchF(iPhBkStoreName)!=0)// Not this phonebook + return; + + TInt index; + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,index); + if(ret!=KErrNone) + { + LOGPARSERR("index",ret,3,&KOOBPhBkUSimDelete); + return; + } + + iPhBkOOBDeleteDuration=count; + iPhBkOOBDeleteIndex=index; + } + + +TInt CSimPhBkUSimStore::GetPhBkUSimEntry(const CTestConfigItem* aItem, TInt& aItemIndex, + TPtrC8& aPhonebookStore, + TPtrC8& aPhonebookName, + TPtrC8& aAid,TInt& aIndex, + TPtrC8& aTelNum, TPtrC8& aAlphaTag, TUint8& aNpiTon, + TPtrC8& aAlphaTag2) +/** + * 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++,aPhonebookStore); + if(ret!=KErrNone) + return ret; + + ret=CTestConfig::GetElement(aItem->Value(),KStdDelimiter,aItemIndex++,aPhonebookName); + if(ret!=KErrNone) + return ret; + + ret=CTestConfig::GetElement(aItem->Value(),KStdDelimiter,aItemIndex++,aAid); + 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 EXTENDEDERROR(KErrArgument, KErrPhonebookNumberOverflow); + + ret=CTestConfig::GetElement(aItem->Value(),KStdDelimiter,aItemIndex++,aAlphaTag); + if(ret!=KErrNone) + return ret; + if(aAlphaTag.Length()>iPhBkMaxTextLen) + return EXTENDEDERROR(KErrArgument, KErrPhonebookTextOverflow); + + if((aTelNum.Length()>0) && (aTelNum[0]=='+')) + { + aTelNum.Set(aTelNum.Mid(1)); + aNpiTon=KNpiTonInternational; + } + else + aNpiTon=KNpiTonNational; + + ret=CTestConfig::GetElement(aItem->Value(),KStdDelimiter,aItemIndex++,aAlphaTag2); + if(ret!=KErrNone) + return ret; + if(aAlphaTag.Length()>iPhBkMaxTextLen) + return EXTENDEDERROR(KErrArgument, KErrPhonebookTextOverflow); + + return ret; + } + +TInt CSimPhBkUSimStore::GetPhBkAdditionalEntry(TPtrC8& aEntry, TInt& aItemIndex, + 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 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(aEntry,';',aItemIndex++,aAlphaTag); + if(ret!=KErrNone) + return ret; + + if(aAlphaTag.Length()>iPhBkMaxAdditionalTextLen) + return EXTENDEDERROR(KErrArgument, KErrPhonebookAdditionalNumberAlphaTextOverflow); + + ret=CTestConfig::GetElement(aEntry,';',aItemIndex++,aTelNum); + if(ret!=KErrNone) + return ret; + if(aTelNum.Length()>iPhBkMaxAdditionalTelNumLen) + return EXTENDEDERROR(KErrArgument, KErrPhonebookAdditionalNumberNumberOverflow); + + + if((aTelNum.Length()>0) && (aTelNum[0]=='+')) + { + aTelNum.Set(aTelNum.Mid(1)); + aNpiTon=KNpiTonInternational; + } + else + { + aNpiTon=KNpiTonNational; + } + + return ret; + } + +CSimPhBkUSimStore::~CSimPhBkUSimStore() +/** + * Standard destructor. Any objects created by the ::ConstructL() function + * will be destroyed here. + */ + { + + for(TInt i=1;i<=iPhBkMaxNumSlots;i++) + { + if(iPhBkUSim1StoreEntries[i].iTelNum.Length()>0 || + iPhBkUSim1StoreEntries[i].iAlphaTag.Length()>0) + { + iPhBkUSim1StoreEntries[i].iTelNum.Zero(); + if((iPhBkUSim1StoreEntries[i].iAdditional!=NULL) + && ((TUint)iPhBkUSim1StoreEntries[i].iAdditional!=DELETED)) + { + if(iPhBkUSim1StoreEntries[i].iAdditional->Count()>=0) + { + iPhBkUSim1StoreEntries[i].iAdditional->Delete(0,iPhBkUSim1StoreEntries[i].iAdditional->Count()); + delete iPhBkUSim1StoreEntries[i].iAdditional; + } + } + if((iPhBkUSim1StoreEntries[i].iGroups!=NULL) + && ((TUint)iPhBkUSim1StoreEntries[i].iGroups!=DELETED)) + { + if(iPhBkUSim1StoreEntries[i].iGroups->Count()>=0) + { + iPhBkUSim1StoreEntries[i].iGroups->Delete(0,iPhBkUSim1StoreEntries[i].iGroups->Count()); + delete iPhBkUSim1StoreEntries[i].iGroups; + } + } + if((iPhBkUSim1StoreEntries[i].iEmails!=NULL) + && ((TUint)iPhBkUSim1StoreEntries[i].iEmails!=DELETED)) + { + if(iPhBkUSim1StoreEntries[i].iEmails->Count()>=0) + { + iPhBkUSim1StoreEntries[i].iEmails->Delete(0,iPhBkUSim1StoreEntries[i].iEmails->Count()); + delete iPhBkUSim1StoreEntries[i].iEmails; + } + } + } + if(iPhBkUSim2StoreEntries!=NULL && + (iPhBkUSim2StoreEntries[i].iTelNum.Length()>0 || + iPhBkUSim2StoreEntries[i].iAlphaTag.Length()>0)) + { + iPhBkUSim2StoreEntries[i].iTelNum.Zero(); + if((iPhBkUSim2StoreEntries[i].iAdditional!=NULL) + && ((TUint)iPhBkUSim2StoreEntries[i].iAdditional!=DELETED)) + { + if(iPhBkUSim2StoreEntries[i].iAdditional->Count()>=0) + { + iPhBkUSim2StoreEntries[i].iAdditional->Delete(0,iPhBkUSim2StoreEntries[i].iAdditional->Count()); + delete iPhBkUSim2StoreEntries[i].iAdditional; + } + } + if((iPhBkUSim2StoreEntries[i].iGroups!=NULL) + && ((TUint)iPhBkUSim2StoreEntries[i].iGroups!=DELETED)) + { + if(iPhBkUSim2StoreEntries[i].iGroups->Count()>=0) + { + iPhBkUSim2StoreEntries[i].iGroups->Delete(0,iPhBkUSim2StoreEntries[i].iGroups->Count()); + delete iPhBkUSim2StoreEntries[i].iGroups; + } + } + if((iPhBkUSim2StoreEntries[i].iEmails!=NULL) + && ((TUint)iPhBkUSim2StoreEntries[i].iEmails!=DELETED)) + { + if(iPhBkUSim2StoreEntries[i].iEmails->Count()>=0) + { + iPhBkUSim2StoreEntries[i].iEmails->Delete(0,iPhBkUSim2StoreEntries[i].iEmails->Count()); + delete iPhBkUSim2StoreEntries[i].iEmails; + } + } + } + } + + if((iPhBkOOBWrite.iAdditional!=NULL) + && ((TUint)iPhBkOOBWrite.iAdditional!=DELETED)) + { + iPhBkOOBWrite.iAdditional->Delete(0,iPhBkOOBWrite.iAdditional->Count()); + delete iPhBkOOBWrite.iAdditional; + } + if((iPhBkOOBWrite.iGroups!=NULL) + && ((TUint)iPhBkOOBWrite.iGroups!=DELETED)) + { + iPhBkOOBWrite.iGroups->Delete(0,iPhBkOOBWrite.iGroups->Count()); + delete iPhBkOOBWrite.iGroups; + } + if((iPhBkOOBWrite.iEmails!=NULL) + && ((TUint)iPhBkOOBWrite.iEmails!=DELETED)) + { + iPhBkOOBWrite.iEmails->Delete(0,iPhBkOOBWrite.iEmails->Count()); + delete iPhBkOOBWrite.iEmails; + } + delete[] iPhBkUSim1StoreEntries; + delete[] iPhBkUSim2StoreEntries; + delete iPhBkError; + delete iPhBkRwBuffer; + delete iOOBWriteTimer; + delete iOOBDeleteTimer; + delete iReqTimer; + + } + +TInt CSimPhBkUSimStore::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* CSimPhBkUSimStore::OpenNewObjectByNameL(const TDesC& /*aName*/) +/** + * The API does not support any objects that could be opened from this one. + */ + { + User::Leave(KErrNotSupported); + return NULL; + } + +CTelObject* CSimPhBkUSimStore::OpenNewObjectL(TDes&) +/** + * The API does not support any objects that could be opened from this one. + */ + { + User::Leave(KErrNotSupported); + return NULL; + } + +CTelObject::TReqMode CSimPhBkUSimStore::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 CSimPhBkUSimStore::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 CSimPhBkUSimStore::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 CSimPhBkUSimStore::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 CSimPhBkUSimStore::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 CSimPhBkUSimStore::Init() +/** + * This function can be used to perform any necessary synchronous initialisation. + */ + { + } + +TInt CSimPhBkUSimStore::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; + } + + if(CheckAndSwitchUSimApps()!=KErrNone) + { + ReqCompleted(aReqHandle, KErrNotFound); + return KErrNone; + } + + RMobilePhoneBookStore::TMobilePhoneBookInfoV1Pckg* getInfoPckg=(RMobilePhoneBookStore::TMobilePhoneBookInfoV1Pckg*)aPckg; + RMobilePhoneBookStore::TMobilePhoneBookInfoV1& getInfo=(*getInfoPckg)(); + + PopulatePhBkStoreInfo(&getInfo); + + if(&getInfo!=NULL) // NULL will have been assigned by PopulatePhBkStoreInfo if the version checking failed. + { + ReqCompleted(aReqHandle,KErrNone); + } + else + { + ReqCompleted(aReqHandle,KErrNotSupported); + } + + return KErrNone; + } + +void CSimPhBkUSimStore::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.Zero(); + + getExtraInfo->iPhBkMode.Copy(PhBkStore()); + + if(PhBkStore().Compare(KUSimPhoneBook)!=KErrNone) + { + getExtraInfo->iIdentity.Copy(iPhone->GetImsi()); + } + else + { + TPtrC8 USimId(iPhone->GetActiveUSim().Right(1)); + getExtraInfo->iIdentity.Copy(USimId); + getExtraInfo->iIdentity.Append(iPhone->GetImsi()); + } + } + 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.Zero(); + + getExtraInfo->iPhBkMode.Copy(PhBkStore()); + + getExtraInfo->iMaxSecondNames = KMaxSecondNames; + getExtraInfo->iMaxTextLengthSecondName = iPhBkMaxTextLen; + getExtraInfo->iMaxAdditionalNumbers = iPhBkAdditional; + getExtraInfo->iMaxTextLengthAdditionalNumber = iPhBkMaxAdditionalTextLen; + getExtraInfo->iMaxNumLengthAdditionalNumber = iPhBkMaxAdditionalTelNumLen; + getExtraInfo->iMaxGroupNames = KMaxGroups; + getExtraInfo->iMaxTextLengthGroupName = iPhBkMaxTextLen; + getExtraInfo->iMaxEmailAddr = iPhBkMaxEmail; + getExtraInfo->iMaxTextLengthEmailAddr = iPhBkMaxTextLen; + + if(PhBkStore().Compare(KUSimPhoneBook)!=KErrNone) + { + getExtraInfo->iIdentity.Copy(iPhone->GetImsi()); + } + else + { + TPtrC8 USimId(iPhone->GetActiveUSim().Right(1)); + getExtraInfo->iIdentity.Copy(USimId); + getExtraInfo->iIdentity.Append(iPhone->GetImsi()); + } + } + } + +TInt CSimPhBkUSimStore::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(CheckAndSwitchUSimApps()!=KErrNone) + { + ReqCompleted(aReqHandle, KErrNotFound); + return KErrNone; + } + + 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; + TBool onlyHidden=EFalse; + + for(TInt i=indexNum.iIndex;i<=iPhBkMaxNumSlots;i++) + { + if((iPhBkUSimStoreEntries[i].iTelNum.Length()!=0)||(iPhBkUSimStoreEntries[i].iAlphaTag.Length()!=0)) + { + ret=iPhBkRwBuffer->AddNewEntryTag(); + if(ret!=KErrNone) + break; + + if((iPhone->IsHiddenEnabled()!=EFalse) && + iPhBkUSimStoreEntries[i].iHiddenEntry==1) + { + //This is a hidden entry, the key is required and is currently locked + //Therefore, the client should be notified that the slot has been occupied by a hidden entry + + partial=ETrue; + ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBAdnIndex,(TUint16)i); + if(ret!=KErrNone) + break; + ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBHiddenInfo,(TUint8) iPhBkUSimStoreEntries[i].iHiddenEntry); + if(ret!=KErrNone) + break; + partial=EFalse; + onlyHidden=ETrue; + break; + } + + partial=ETrue; + ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBAdnIndex,(TUint16)i); + if(ret!=KErrNone) + break; + ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBText,iPhBkUSimStoreEntries[i].iAlphaTag); + if(ret!=KErrNone) + break; + ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBTonNpi,iPhBkUSimStoreEntries[i].iTonNpi); + if(ret!=KErrNone) + break; + ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBNumber,iPhBkUSimStoreEntries[i].iTelNum); + if(ret!=KErrNone) + break; + + ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBSecondName,iPhBkUSimStoreEntries[i].iAlphaTag2); + if(ret!=KErrNone) + break; + + TInt EmailCount = iPhBkUSimStoreEntries[i].iEmails->Count(); + TInt GroupCount = iPhBkUSimStoreEntries[i].iGroups->Count(); + TInt AnrCount = iPhBkUSimStoreEntries[i].iAdditional->Count(); + TInt j; + + TBool corrupt=EFalse; + + for(j=0; jAt(j); + + corrupt=ETrue; + + ret=iPhBkRwBuffer->AddNewNumberTag(); + if(ret!=KErrNone) + break; + + ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBText,entry.iAlphaTag); + if(ret!=KErrNone) + break; + + ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBNumber,entry.iTelNum); + if(ret!=KErrNone) + break; + + ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBTonNpi,entry.iTonNpi); + if(ret!=KErrNone) + break; + + corrupt=EFalse; + } + if(corrupt) + break; + + for(j=0; jAt(j); + + corrupt=ETrue; + ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBEmailAddress,entry); + if(ret!=KErrNone) + break; + corrupt=EFalse; + } + if(corrupt) + break; + + for(j=0; jAt(j); + + corrupt=ETrue; + ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBGroupName,entry); + if(ret!=KErrNone) + break; + corrupt=EFalse; + } + if(corrupt) + break; + + ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBHiddenInfo,(TUint8) iPhBkUSimStoreEntries[i].iHiddenEntry); + if(ret!=KErrNone) + break; + + partial=EFalse; + onlyHidden=ETrue; + 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)&&(!onlyHidden)) + ReqCompleted(aReqHandle,KErrNotFound); // No entries found. + else if((cnt==0)&&(!partial)&&(onlyHidden)) + ReqCompleted(aReqHandle,KErrAccessDenied); + else + ReqCompleted(aReqHandle,KErrNone); + + return KErrNone; + } + +TInt CSimPhBkUSimStore::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(CheckAndSwitchUSimApps()!=KErrNone) + { + ReqCompleted(aReqHandle, KErrNotFound); + return KErrNone; + } + + 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((iPhBkUSimStoreEntries[i].iTelNum.Length()==0)&&(iPhBkUSimStoreEntries[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(iPhBkUSimStoreEntries[index].iTelNum.Length()!=0) + { + if((iPhone->IsHiddenEnabled()!=EFalse) && + iPhBkUSimStoreEntries[index].iHiddenEntry==1) + { + ReqCompleted(aReqHandle, KErrAccessDenied); + return KErrNone; + } + + isSlotAlreadyUsed=ETrue; + TInt idx,count; + + count=iPhBkUSimStoreEntries[index].iAdditional->Count(); + for(idx=0;idxAt(idx); + entry.iTelNum.Zero(); + entry.iAlphaTag.Zero(); + entry.iTonNpi=0; + } + iPhBkUSimStoreEntries[index].iAdditional->Delete(0,count); + delete iPhBkUSimStoreEntries[index].iAdditional; + count=iPhBkUSimStoreEntries[index].iGroups->Count(); + iPhBkUSimStoreEntries[index].iGroups->Delete(0,count); + delete iPhBkUSimStoreEntries[index].iGroups; + count=iPhBkUSimStoreEntries[index].iEmails->Count(); + iPhBkUSimStoreEntries[index].iEmails->Delete(0,count); + delete iPhBkUSimStoreEntries[index].iEmails; + + TRAPD(err,iPhBkUSimStoreEntries[index].iAdditional= + new(ELeave) CArrayFixFlat(iPhBkAdditional+1)); + if (err!=KErrNone) + return (err); + + TRAP(err,iPhBkUSimStoreEntries[index].iGroups= + new(ELeave) CArrayFixFlat(KMaxGroups)); + if (err!=KErrNone) + return (err); + + TRAP(err,iPhBkUSimStoreEntries[index].iEmails= + new(ELeave) CArrayFixFlat(iPhBkMaxEmail+1)); + if (err!=KErrNone) + return (err); + } + else + { + TRAPD(err,iPhBkUSimStoreEntries[index].iAdditional= + new(ELeave) CArrayFixFlat(iPhBkAdditional+1)); + if (err!=KErrNone) + return (err); + + TRAP(err,iPhBkUSimStoreEntries[index].iGroups= + new(ELeave) CArrayFixFlat(KMaxGroups)); + if (err!=KErrNone) + return (err); + + TRAP(err,iPhBkUSimStoreEntries[index].iEmails= + new(ELeave) CArrayFixFlat(iPhBkMaxEmail+1)); + if (err!=KErrNone) + return (err); + } +// Unpick the phonebook entry. + iPhBkRwBuffer->Set(aPckg1); + iPhBkRwBuffer->StartRead(); + + TUint8 tagVal; + TUint8 npiTon=0; + TUint8 hidden; + TPtrC alphaTag,alphaTag2; + TPtrC telNum; + TPtrC bufPtr; + TBool additional=EFalse; + TInt additionalCount=0; + + CPhoneBookBuffer::TPhBkTagType tagType; + TInt ret=KErrNone; + + TPhBkStoreEntry additionalEntry; + + while(ret==KErrNone) + { + ret=iPhBkRwBuffer->GetTagAndType(tagVal,tagType); + if(ret==KErrNotFound) + { + ret=KErrNone; + break; + } + else if(ret!=KErrNone) + break; + switch(tagVal) + { + case RMobilePhoneBookStore::ETagPBNewEntry: + break; + + case RMobilePhoneBookStore::ETagPBText: + ret=iPhBkRwBuffer->GetValue(alphaTag); + + LOGPHBK2("alphaTag (ETagPBText) Length = (%d)",alphaTag.Length()); + LOGPHBK2("Phonebook Max Text Length = (%d)",iPhBkMaxTextLen); + + if(!additional && ret==KErrNone && (alphaTag.Length()<=iPhBkMaxTextLen)) + iPhBkUSimStoreEntries[index].iAlphaTag.Copy(alphaTag); + else if(additional && ret==KErrNone && (alphaTag.Length()<=iPhBkMaxAdditionalTextLen) + && (additionalCountGetValue(alphaTag2); + + LOGPHBK2("alphaTag2 (ETagPBSecondName) Length = (%d)",alphaTag2.Length()); + LOGPHBK2("Phonebook Max Text Length = (%d)",iPhBkMaxTextLen); + + if(ret==KErrNone && (alphaTag2.Length()<=iPhBkMaxTextLen)) + iPhBkUSimStoreEntries[index].iAlphaTag2.Copy(alphaTag2); + else + ret=EXTENDEDERROR(KErrOverflow, KErrPhonebookSecondNameTextOverflow); + break; + + case RMobilePhoneBookStore::ETagPBNumber: + ret=iPhBkRwBuffer->GetValue(telNum); + + LOGPHBK2("telNum (ETagPBNumber) Length = (%d)",telNum.Length()); + LOGPHBK2("Phonebook Max Text Length = (%d)",iPhBkMaxTelNumLen); + + if(!additional && ret==KErrNone && (telNum.Length()<=iPhBkMaxTelNumLen)) + iPhBkUSimStoreEntries[index].iTelNum.Copy(telNum); + else if(additional && ret==KErrNone && (telNum.Length()<=iPhBkMaxAdditionalTelNumLen) + && (additionalCountGetValue(npiTon); + if(!additional && ret==KErrNone) + iPhBkUSimStoreEntries[index].iTonNpi=npiTon; + else if (additional && ret==KErrNone) + { + additionalEntry.iTonNpi=npiTon; + TRAP_IGNORE(iPhBkUSimStoreEntries[index].iAdditional->AppendL(additionalEntry)); + additional=EFalse; + additionalCount++; + additionalEntry.iAlphaTag.Zero(); + additionalEntry.iTelNum.Zero(); + additionalEntry.iTonNpi=0; + } + break; + + case RMobilePhoneBookStore::ETagPBAnrStart: + if(!additional) + additional=ETrue; + else + ret=KErrArgument; + break; + + case RMobilePhoneBookStore::ETagPBGroupName: + ret=iPhBkRwBuffer->GetValue(bufPtr); + + LOGPHBK2("bufPtr (ETagPBGroupName) Length = (%d)",bufPtr.Length()); + LOGPHBK2("Phonebook Max Text Length = (%d)",iPhBkMaxTextLen); + + if(ret==KErrNone && (bufPtr.Length()<=iPhBkMaxTextLen) + && (iPhBkUSimStoreEntries[index].iGroups->Count() < KMaxGroups)) + { + TRAP_IGNORE(iPhBkUSimStoreEntries[index].iGroups->AppendL(bufPtr)); + } + else + ret=EXTENDEDERROR(KErrOverflow, KErrPhonebookGroupAlphaTextOverflow); + break; + + case RMobilePhoneBookStore::ETagPBEmailAddress: + ret=iPhBkRwBuffer->GetValue(bufPtr); + + LOGPHBK2("bufPtr (ETagPBEmailAddress) Length = (%d)",bufPtr.Length()); + LOGPHBK2("Phonebook Max Text Length = (%d)",iPhBkMaxTextLen); + + if(ret==KErrNone && (bufPtr.Length()<=iPhBkMaxTextLen) + && (iPhBkUSimStoreEntries[index].iEmails->Count() < iPhBkMaxEmail)) + { + TRAP_IGNORE(iPhBkUSimStoreEntries[index].iEmails->AppendL(bufPtr)); + } + else + ret=EXTENDEDERROR(KErrOverflow, KErrPhonebookEmailTextOverflow); + break; + + case RMobilePhoneBookStore::ETagPBHiddenInfo: + ret=iPhBkRwBuffer->GetValue(hidden); + if(ret==KErrNone) + iPhBkUSimStoreEntries[index].iHiddenEntry=hidden; + break; + + default: + ret=KErrNotSupported; + } + } + + if(ret!=KErrNone) + { + //Cleanup! + iPhBkUSimStoreEntries[index].iTelNum.Zero(); + iPhBkUSimStoreEntries[index].iAlphaTag.Zero(); + iPhBkUSimStoreEntries[index].iAlphaTag2.Zero(); + iPhBkUSimStoreEntries[index].iHiddenEntry=0; + iPhBkUSimStoreEntries[index].iTonNpi=npiTon; + + if(iPhBkUSimStoreEntries[index].iGroups!=NULL) + { + iPhBkUSimStoreEntries[index].iGroups->Delete(0,iPhBkUSimStoreEntries[index].iGroups->Count()); + delete iPhBkUSimStoreEntries[index].iGroups; + } + if(iPhBkUSimStoreEntries[index].iEmails!=NULL) + { + iPhBkUSimStoreEntries[index].iEmails->Delete(0,iPhBkUSimStoreEntries[index].iEmails->Count()); + delete iPhBkUSimStoreEntries[index].iEmails; + } + if(iPhBkUSimStoreEntries[index].iAdditional!=NULL) + { + iPhBkUSimStoreEntries[index].iAdditional->Delete(0,iPhBkUSimStoreEntries[index].iAdditional->Count()); + delete iPhBkUSimStoreEntries[index].iAdditional; + } + ReqCompleted(aReqHandle,ret); + return KErrNone; + } + +// if(alphaTag.Length()>iPhBkMaxTextLen) +// { +// ReqCompleted(aReqHandle, EXTENDEDERROR(KErrOverflow, KErrPhonebookTextOverflow)); +// return KErrNone; +// } +// else if(telNum.Length()>iPhBkMaxTelNumLen) +// { +// ReqCompleted(aReqHandle, EXTENDEDERROR(KErrOverflow, KErrPhonebookNumberOverflow)); +// return KErrNone; +// } + + if(isSlotAlreadyUsed) + DelayCompletion(iPhBkIndividualPause,aReqHandle,EStoreEventChanged,index); + else + DelayCompletion(iPhBkIndividualPause,aReqHandle,EStoreEventAdded,index); + return KErrNone; + } + +TInt CSimPhBkUSimStore::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(CheckAndSwitchUSimApps()!=KErrNone) + { + ReqCompleted(aReqHandle, KErrNotFound); + return KErrNone; + } + + 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; + } + + if((iPhone->IsHiddenEnabled()!=EFalse) && + iPhBkUSimStoreEntries[index].iHiddenEntry==1) + { + ReqCompleted(aReqHandle, KErrAccessDenied); + return KErrNone; + } + + iPhBkUSimStoreEntries[index].iTelNum.Zero(); + iPhBkUSimStoreEntries[index].iAlphaTag.Zero(); + iPhBkUSimStoreEntries[index].iAlphaTag2.Zero(); + + if((iPhBkUSimStoreEntries[index].iGroups!=NULL) && + ((TUint)iPhBkUSimStoreEntries[index].iGroups!=DELETED)) + { + iPhBkUSimStoreEntries[index].iGroups->Delete(0, + iPhBkUSimStoreEntries[index].iGroups->Count()); + delete iPhBkUSimStoreEntries[index].iGroups; + } + if((iPhBkUSimStoreEntries[index].iEmails!=NULL) && + ((TUint)iPhBkUSimStoreEntries[index].iEmails!=DELETED)) + { + iPhBkUSimStoreEntries[index].iEmails->Delete(0, + iPhBkUSimStoreEntries[index].iEmails->Count()); + delete iPhBkUSimStoreEntries[index].iEmails; + } + + if((iPhBkUSimStoreEntries[index].iAdditional!=NULL) && + ((TUint)iPhBkUSimStoreEntries[index].iAdditional!=DELETED)) + { + TInt count = iPhBkUSimStoreEntries[index].iAdditional->Count(); + for(TInt i=0;iAt(i); + entry.iTelNum.Zero(); + entry.iAlphaTag.Zero(); + entry.iTonNpi=0; + } + + iPhBkUSimStoreEntries[index].iAdditional->Delete(0,count); + delete iPhBkUSimStoreEntries[index].iAdditional; + } + + DelayCompletion(iPhBkIndividualPause,aReqHandle,EStoreEventDeleted,index); + return KErrNone; + } + +TInt CSimPhBkUSimStore::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(CheckAndSwitchUSimApps()!=KErrNone) + { + ReqCompleted(aReqHandle, KErrNotFound); + return KErrNone; + } + + 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++) + { + TBool entryUsed =EFalse; + + if((iPhone->IsHiddenEnabled()!=EFalse) && + iPhBkUSimStoreEntries[i].iHiddenEntry==1) + { + //Skip me because I am a hidden entry! + //The hidden key has to be verified to delete me! + continue; + } + if(iPhBkUSimStoreEntries[i].iTelNum.Length()>0) + entryUsed = ETrue; + + iPhBkUSimStoreEntries[i].iTelNum.Zero(); + iPhBkUSimStoreEntries[i].iAlphaTag.Zero(); + iPhBkUSimStoreEntries[i].iAlphaTag2.Zero(); + + if(entryUsed) + { + if((iPhBkUSimStoreEntries[i].iGroups!=NULL) && + ((TUint)iPhBkUSimStoreEntries[i].iGroups!=DELETED)) + { + iPhBkUSimStoreEntries[i].iGroups->Delete(0, + iPhBkUSimStoreEntries[i].iGroups->Count()); + delete iPhBkUSimStoreEntries[i].iGroups; + } + if((iPhBkUSimStoreEntries[i].iEmails!=NULL) && + ((TUint)iPhBkUSimStoreEntries[i].iEmails!=DELETED)) + { + iPhBkUSimStoreEntries[i].iEmails->Delete(0, + iPhBkUSimStoreEntries[i].iEmails->Count()); + delete iPhBkUSimStoreEntries[i].iEmails; + } + if((iPhBkUSimStoreEntries[i].iAdditional!=NULL) && + ((TUint)iPhBkUSimStoreEntries[i].iAdditional!=DELETED)) + { + TInt count = iPhBkUSimStoreEntries[i].iAdditional->Count(); + for(TInt index=0;indexAt(index); + entry.iTelNum.Zero(); + entry.iAlphaTag.Zero(); + entry.iTonNpi=0; + } + + iPhBkUSimStoreEntries[i].iAdditional->Delete(0,count); + delete iPhBkUSimStoreEntries[i].iAdditional; + } + } + } + DelayCompletion(iPhBkBatchPause,aReqHandle,EStoreEventDeleted,-1); + return KErrNone; + } + +TInt CSimPhBkUSimStore::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 CSimPhBkUSimStore::NotifyStoreEventCancel() +/** + * Cancel an outstanding notify store request. + */ + { + if(iEvOutstandingReq) + { + iEvOutstandingReq=EFalse; + ReqCompleted(iEvReqHandle,KErrCancel); + } + } + +TPtrC8 CSimPhBkUSimStore::Name() +/** + * Accessor function fot the Phonebook Store name. + * + * @return TPtrC8 The name of this Phonebook Store. + */ + { + return iPhBkStoreName; + } + +TPtrC8 CSimPhBkUSimStore::PhBkStore() +/** + * Accessor function fot the Phonebook Store name. + * + * @return TPtrC8 The name of this Phonebook Store. + */ + { + return iPhBkStore; + } + +TPtrC8 CSimPhBkUSimStore::AID() +/** + * Accessor function fot the Phonebook Store name. + * + * @return TPtrC8 The name of this Phonebook Store. + */ + { + return iPhBkAid; + } + +TInt CSimPhBkUSimStore::UsedEntries() +/** + * Count the number of used entries in the Phonebook Store. + * @return TInt The number of used entries in the store. + */ + { + TInt cnt=0; + if(CheckAndSwitchUSimApps()!=KErrNone) + return KErrNotFound; + for(TInt i=1;i<=iPhBkMaxNumSlots;i++) + { + if((iPhBkUSimStoreEntries[i].iTelNum.Length()!=0)||(iPhBkUSimStoreEntries[i].iAlphaTag.Length()!=0)) + cnt++; + } + return cnt; + } + +TInt CSimPhBkUSimStore::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 CSimPhBkUSimStore::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 CSimPhBkUSimStore::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,ETimerIdPhBkUSimStorReq); + } + +void CSimPhBkUSimStore::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. + */ + { + TInt idx=0,count; + TBool isSlotAlreadyUsed=EFalse; + + switch(aId) + { + case ETimerIdPhBkUSimStorReq: + StoreEvent(iPendingEvent,iPendingIndex); + ReqCompleted(iPendingReqCompletion,KErrNone); + break; + + case ETimerIdPhBkUSimStorOOBWrite: + + if(CheckAndSwitchUSimApps()!=KErrNone) + if(iEvOutstandingReq) + { + ReqCompleted(iEvReqHandle,KErrNotFound); + return; + } + else + { + return; + } + + if(iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iTelNum.Length()!=0) + isSlotAlreadyUsed=ETrue; + + iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iAlphaTag.Copy(iPhBkOOBWrite.iAlphaTag); + iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iTelNum.Copy(iPhBkOOBWrite.iTelNum); + iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iTonNpi=iPhBkOOBWrite.iTonNpi; + iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iAlphaTag2.Copy(iPhBkOOBWrite.iAlphaTag2); + + if(isSlotAlreadyUsed) + { + if((count=iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iAdditional->Count())>0) + { + for(idx=0;idxAt(idx); + entry.iTelNum.Zero(); + entry.iAlphaTag.Zero(); + entry.iTonNpi=0; + } + iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iAdditional->Delete(0,count); + delete iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iAdditional; + } + + if((count = iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iGroups->Count())>0) + { + iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iGroups->Delete(0,count); + delete iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iGroups; + } + if((count = iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iEmails->Count())>0) + { + iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iEmails->Delete(0,count); + delete iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iEmails; + } + } + + count = iPhBkOOBWrite.iAdditional->Count(); + + //sometimes because of a kernel bug on wins, iAdditional pointer gets filled up with + //bad address 0xdededede (investigating) + + TRAPD(err,iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iAdditional=new(ELeave) CArrayFixFlat(iPhBkAdditional+1)); + if (err!=KErrNone) + { + LOGPHBK1("CSimPhBkUSimStore::TimerCallBack - Memory Allocation Failure"); + return; + } + + for(idx=0;idxAt(idx); + TRAP_IGNORE(iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iAdditional->AppendL(entry)); + } + + + TRAP(err,iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iGroups=new(ELeave) CArrayFixFlat(KMaxGroups)); + if (err!=KErrNone) + { + LOGPHBK1("CSimPhBkUSimStore::TimerCallBack - Memory Allocation Failure"); + return; + } + + for(idx=0;idxAppendL(entry)); + } + + count = iPhBkOOBWrite.iEmails->Count(); + TRAP(err,iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iEmails=new(ELeave) CArrayFixFlat(iPhBkMaxEmail+1)); + if (err!=KErrNone) + { + LOGPHBK1("CSimPhBkUSimStore::TimerCallBack - Memory Allocation Failure"); + return; + } + + for(idx=0;idxAppendL(entry)); + } + + iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iHiddenEntry=iPhBkOOBWrite.iHiddenEntry; + + StoreEvent(EStoreEventAdded,iPhBkOOBWriteIndex); + break; + + case ETimerIdPhBkUSimStorOOBDelete: + + if(CheckAndSwitchUSimApps()!=KErrNone) + if(iEvOutstandingReq) + { + ReqCompleted(iEvReqHandle,KErrNotFound); + return; + } + else + { + return; + } + + iPhBkUSimStoreEntries[iPhBkOOBDeleteIndex].iAlphaTag.Zero(); + iPhBkUSimStoreEntries[iPhBkOOBDeleteIndex].iTelNum.Zero(); + iPhBkUSimStoreEntries[iPhBkOOBDeleteIndex].iTonNpi=0; + iPhBkUSimStoreEntries[iPhBkOOBDeleteIndex].iAlphaTag2.Zero(); + + iPhBkUSimStoreEntries[iPhBkOOBDeleteIndex].iGroups->Delete(0, + iPhBkUSimStoreEntries[iPhBkOOBDeleteIndex].iGroups->Count()); + delete iPhBkUSimStoreEntries[iPhBkOOBDeleteIndex].iGroups; + + iPhBkUSimStoreEntries[iPhBkOOBDeleteIndex].iEmails->Delete(0, + iPhBkUSimStoreEntries[iPhBkOOBDeleteIndex].iEmails->Count()); + delete iPhBkUSimStoreEntries[iPhBkOOBDeleteIndex].iEmails; + + count = iPhBkUSimStoreEntries[iPhBkOOBDeleteIndex].iAdditional->Count(); + for(idx=0;idxAt(idx); + entry.iTelNum.Zero(); + entry.iAlphaTag.Zero(); + entry.iTonNpi=0; + } + + iPhBkUSimStoreEntries[iPhBkOOBDeleteIndex].iAdditional->Delete(0,count); + delete iPhBkUSimStoreEntries[iPhBkOOBDeleteIndex].iAdditional; + iPhBkUSimStoreEntries[iPhBkOOBDeleteIndex].iHiddenEntry=0; + + StoreEvent(EStoreEventDeleted,iPhBkOOBDeleteIndex); + break; + + default: + break; + } + } + +void CSimPhBkUSimStore::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 CSimPhBkUSimStore::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++) + { + if(iPhBkError->At(i).iCount==iIpcCnt) + { + aError=iPhBkError->At(i).iError; + return ETrue; + } + } + return EFalse; + } + + +/** + * Check that the USIM App phonebook in use is the same as the current + * USIM App, and if not then swap the phonebook over. + */ +TInt CSimPhBkUSimStore::CheckAndSwitchUSimApps() + { + TInt ret=KErrNone; + + if(iPhBkStore.Compare(KUSimPhoneBook)==KErrNone) + { + if(iPhone->GetActiveUSim().Compare(iPhBkAid)==KErrNone) + { + // + // The active USIM App is the same as last time, but ensure that + // we are using the right phonebook anyway. + // + if(iPhBkAid.Compare(iPhBkAidUSim2)==KErrNone) + { + iPhBkUSimStoreEntries=iPhBkUSim2StoreEntries; + } + else if(iPhBkAid.Compare(iPhBkAidUSim1)==KErrNone) + { + iPhBkUSimStoreEntries=iPhBkUSim1StoreEntries; + } + else + { + //messed up + return KErrUnknown; + } + } + else if((iPhone->GetActiveUSim().Compare(iPhBkAid)!=KErrNone) && + (iPhone->GetActiveUSim().Compare(iPhBkAidUSim2)==KErrNone)) + { + // + // The active USIM App is not the same as last time and it appears + // to be USIM App 2, so use USIM phonebook number 2. + // + iPhBkAid.Copy(iPhBkAidUSim2); + iPhBkUSimStoreEntries=iPhBkUSim2StoreEntries; + } + else if((iPhone->GetActiveUSim().Compare(iPhBkAid)!=KErrNone) && + (iPhone->GetActiveUSim().Compare(iPhBkAidUSim1)==KErrNone)) + { + // + // The active USIM App is not the same as last time and it appears + // to be USIM App 1, so use USIM phonebook number 1. + // + iPhBkAid.Copy(iPhBkAidUSim1); + iPhBkUSimStoreEntries=iPhBkUSim1StoreEntries; + } + else + { + //Unknown active application!! + ret=KErrNotFound; + } + } + return ret; +} + +const CTestConfigSection* CSimPhBkUSimStore::CfgFile() +/** +* Returns a pointer to the config file section +* +* @return CTestConfigSection a pointer to the configuration file data section +*/ + { + LOGPHBK1(">>CSimPhBkUSimStore::CfgFile"); + return iPhone->CfgFile(); + }