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