// 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 <testconfigfileparser.h>
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<TPhBkError>(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;(i<count || !capsFound);i++)
{
item0=CfgFile()->Item(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 = <store name>, <slot number>, <telephone number>, <alphatag>"
*/
{
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;i<count;i++)
{
TInt parseIndex=0;
item=CfgFile()->Item(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<TPhBkStoreEntry>(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<TPhBkUSimEmail>(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<TPhBkUSimGroup>(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;i<count;i++)
{
item=CfgFile()->Item(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= <duration>, <phonebook name>, <index>, <telephone number>, <alpha tag>"
*/
{
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<TPhBkStoreEntry>(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<TPhBkUSimGroup>(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<TPhBkUSimEmail>(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= <duration>, <phonebook name>, <index>
*/
{
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<RMobilePhoneBookStore::TPBIndexAndNumEntries>* indexNumPckg=(TPckg<RMobilePhoneBookStore::TPBIndexAndNumEntries>*)aPckg1;
RMobilePhoneBookStore::TPBIndexAndNumEntries& indexNum=(*indexNumPckg)();
if(indexNum.iNumSlots==iPhBkMaxNumSlots)
{
if (!(iPhBkStoreCaps & static_cast<TUint32>(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; j<AnrCount; j++)
{
TPhBkStoreEntry entry = iPhBkUSimStoreEntries[i].iAdditional->At(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; j<EmailCount; j++)
{
TPhBkUSimEmail entry = iPhBkUSimStoreEntries[i].iEmails->At(j);
corrupt=ETrue;
ret=iPhBkRwBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBEmailAddress,entry);
if(ret!=KErrNone)
break;
corrupt=EFalse;
}
if(corrupt)
break;
for(j=0; j<GroupCount; j++)
{
TPhBkUSimGroup entry = iPhBkUSimStoreEntries[i].iGroups->At(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<TInt>* indexPckg=(TPckg<TInt>*)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;idx<count;idx++)
{
TPhBkStoreEntry entry=
iPhBkUSimStoreEntries[index].iAdditional->At(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<TPhBkStoreEntry>(iPhBkAdditional+1));
if (err!=KErrNone)
return (err);
TRAP(err,iPhBkUSimStoreEntries[index].iGroups=
new(ELeave) CArrayFixFlat<TPhBkUSimGroup>(KMaxGroups));
if (err!=KErrNone)
return (err);
TRAP(err,iPhBkUSimStoreEntries[index].iEmails=
new(ELeave) CArrayFixFlat<TPhBkUSimEmail>(iPhBkMaxEmail+1));
if (err!=KErrNone)
return (err);
}
else
{
TRAPD(err,iPhBkUSimStoreEntries[index].iAdditional=
new(ELeave) CArrayFixFlat<TPhBkStoreEntry>(iPhBkAdditional+1));
if (err!=KErrNone)
return (err);
TRAP(err,iPhBkUSimStoreEntries[index].iGroups=
new(ELeave) CArrayFixFlat<TPhBkUSimGroup>(KMaxGroups));
if (err!=KErrNone)
return (err);
TRAP(err,iPhBkUSimStoreEntries[index].iEmails=
new(ELeave) CArrayFixFlat<TPhBkUSimEmail>(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)
&& (additionalCount<iPhBkAdditional))
additionalEntry.iAlphaTag.Copy(alphaTag);
else if(additional)
ret=EXTENDEDERROR(KErrArgument, KErrPhonebookAdditionalNumberAlphaTextOverflow);
else
ret=EXTENDEDERROR(KErrOverflow, KErrPhonebookTextOverflow);
break;
case RMobilePhoneBookStore::ETagPBSecondName:
ret=iPhBkRwBuffer->GetValue(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)
&& (additionalCount<iPhBkAdditional))
additionalEntry.iTelNum.Copy(telNum);
else if(additional)
ret=EXTENDEDERROR(KErrArgument, KErrPhonebookAdditionalNumberNumberOverflow);
else
ret=EXTENDEDERROR(KErrOverflow, KErrPhonebookNumberOverflow);
break;
case RMobilePhoneBookStore::ETagPBTonNpi:
ret=iPhBkRwBuffer->GetValue(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<TInt>* intPckg=(TPckg<TInt>*)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;i<count;i++)
{
TPhBkStoreEntry entry=iPhBkUSimStoreEntries[index].iAdditional->At(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<TUint32>(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;index<count;index++)
{
TPhBkStoreEntry entry=iPhBkUSimStoreEntries[i].iAdditional->At(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<TUint32>* eventPckg=(TPckg<TUint32>*)aPckg1;
TUint32& event=(*eventPckg)();
TPckg<TInt>* indexPckg=(TPckg<TInt>*)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;idx<count;idx++)
{
TPhBkStoreEntry entry=
iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iAdditional->At(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<TPhBkStoreEntry>(iPhBkAdditional+1));
if (err!=KErrNone)
{
LOGPHBK1("CSimPhBkUSimStore::TimerCallBack - Memory Allocation Failure");
return;
}
for(idx=0;idx<count;idx++)
{
TPhBkStoreEntry entry=iPhBkOOBWrite.iAdditional->At(idx);
TRAP_IGNORE(iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iAdditional->AppendL(entry));
}
TRAP(err,iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iGroups=new(ELeave) CArrayFixFlat<TPhBkUSimGroup>(KMaxGroups));
if (err!=KErrNone)
{
LOGPHBK1("CSimPhBkUSimStore::TimerCallBack - Memory Allocation Failure");
return;
}
for(idx=0;idx<count;idx++)
{
TPhBkUSimGroup entry;
TRAP_IGNORE(iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iGroups->AppendL(entry));
}
count = iPhBkOOBWrite.iEmails->Count();
TRAP(err,iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iEmails=new(ELeave) CArrayFixFlat<TPhBkUSimEmail>(iPhBkMaxEmail+1));
if (err!=KErrNone)
{
LOGPHBK1("CSimPhBkUSimStore::TimerCallBack - Memory Allocation Failure");
return;
}
for(idx=0;idx<count;idx++)
{
TPhBkUSimEmail entry;
TRAP_IGNORE(iPhBkUSimStoreEntries[iPhBkOOBWriteIndex].iEmails->AppendL(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;idx<count;idx++)
{
TPhBkStoreEntry entry=iPhBkUSimStoreEntries[iPhBkOOBDeleteIndex].iAdditional->At(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;i<iPhBkError->Count();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();
}