diff -r 6b1d113cdff3 -r 6638e7f4bd8f telephonyserverplugins/simtsy/src/CSimSmsStore.cpp --- a/telephonyserverplugins/simtsy/src/CSimSmsStore.cpp Mon May 03 13:37:20 2010 +0300 +++ b/telephonyserverplugins/simtsy/src/CSimSmsStore.cpp Thu May 06 15:10:38 2010 +0100 @@ -1,1183 +1,1183 @@ -// Copyright (c) 2003-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 SMS Store manipulation code. -// -// - -/** - @file -*/ - -#include -#include -#include -#include "CSimSmsStore.h" -#include "csimsmsmess.h" -#include "Simlog.h" -#include "CSimTsyMode.h" - -const TInt KSmsStoreGranularity=2; -const TInt KCorruptPDU=9999; -_LIT(KNullTelephoneNumber,"0"); - - -CListReadAllAttempt* CListReadAllAttempt::NewL(RMobilePhone::TClientId& aId, TTsyReqHandle aReqHandle) -/** - * Standard two phase constructor. - * @param aId The client ID (session and sub-session handles) that uniquely identifies a client performing a two phase read. - * @param aReqHandle The TSY request handle of the client request associated with a two phase read. - * @return CListReadAllAttempt* The newly created object. - */ - { - CListReadAllAttempt* read=new(ELeave) CListReadAllAttempt(aId, aReqHandle); - CleanupStack::PushL(read); - read->ConstructL(); - CleanupStack::Pop(); - return read; - } - -CListReadAllAttempt::CListReadAllAttempt(RMobilePhone::TClientId& aId, TTsyReqHandle aReqHandle) - : iListBuf(NULL),iReqHandle(aReqHandle) -/** - * Trivial first phase constructor. - * @param aId The client ID (session and sub-session handles) that uniquely identifies a client performing a two phase read. - * @param aReqHandle The TSY request handle of the client request associated with a two phase read. - */ - { - iClient.iSessionHandle=aId.iSessionHandle; - iClient.iSubSessionHandle=aId.iSubSessionHandle; - iReqHandle=aReqHandle; - iListBuf = NULL; - } - -void CListReadAllAttempt::ConstructL() -/** - * Trivial second phase constructor. - */ - { - } - -CListReadAllAttempt::~CListReadAllAttempt() -/** - * Trivial destructor. - */ - { - delete iListBuf; - } - -// -// CSimSmsStore -// -void CSimSmsStore::ClosePhone(TAny* aObj) -/** - * A utility function for cleaning up the stack. - */ - { - ((CObject*)aObj)->Close(); - } - -CSimSmsStore* CSimSmsStore::NewL(CSimSmsMessaging* aSimSmsMess, const TDesC8& aName, TInt aMaxNumSlots, CSimPhone* aPhone) -/** - * Standard two phase constructor. - * @param aSimSmsMess The SMS Messaging object from which this SMS Store was opened. - * @param aName The name of the created SMS Store. - * @param aMaxNumSlots The maximum number of slots in the SMS Store. - * @return CSimSmsStore* The newly created object. - */ - { - CSimSmsStore* store=new(ELeave) CSimSmsStore(aSimSmsMess, aPhone); - TCleanupItem newObjClose(ClosePhone,store); - CleanupStack::PushL(newObjClose); - store->ConstructL(aName,aMaxNumSlots); - CleanupStack::Pop(); - return store; - } - -CSimSmsStore::CSimSmsStore(CSimSmsMessaging* aSmsMess, CSimPhone* aPhone) - : iSmsMessaging(aSmsMess), iEvOutstandingReq(EFalse), iPhone(aPhone) -/** - * Trivial first phase constructor. - * @param aSimSmsMess The SMS Messaging object from which this SMS Store was opened. - */ - {} - -void CSimSmsStore::ConstructL(const TDesC8& aName, TInt aMaxNumSlots) -/** - * Second phase constructor that allocates memory for the SMS store, 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 SMS Store. - * @param aMaxNumSlots The maximum number of slots in the SMS Store. - */ - { - iGsmSmsStoreEntries=new(ELeave) RMobileSmsStore::TMobileGsmSmsEntryV1[aMaxNumSlots+1];//index 0 is not used - iSmsMaxNumSlots=aMaxNumSlots; - iSmsStoreName.Copy(aName); - iSmsReadAll=new(ELeave) CArrayPtrFlat(KSmsStoreGranularity); - LOGSMS1("Starting to parse SMS Store config parameters..."); - iSmsIndividualPause=CfgFileSection()->ItemValue(KSmsStoreIndividualReqPause,KDefaultSmsStoreIndividualReqPause); - iSmsBatchPause=CfgFileSection()->ItemValue(KSmsStoreBatchReqPause,KDefaultSmsStoreBatchReqPause); - - const CTestConfigItem* item0=NULL; - item0=CfgFileSection()->Item(KSmsPhoneStoreCaps,0); - if (item0) - { - TPtrC8 value0; - TInt ret0=CTestConfig::GetElement(item0->Value(),KStdDelimiter,0,value0); - if(ret0!=KErrNone) - { - LOGPARSERR("value0",ret0,0,&KSmsPhoneStoreCaps); - iSmsStoreCaps=KDefaultSmsPhoneStoreCaps+KDefaultSmsOnlySmsCaps; - } - else - { - TUint32 intValue; - TInt ret = AsciiToNum(value0, intValue); - if(ret!=KErrNone) - iSmsStoreCaps=KDefaultSmsPhoneStoreCaps+KDefaultSmsOnlySmsCaps; - else - iSmsStoreCaps = intValue+KDefaultSmsOnlySmsCaps; - } - } - else - iSmsStoreCaps=KDefaultSmsPhoneStoreCaps+KDefaultSmsOnlySmsCaps; - - - LOGSMS1("...Finished parsing SMS Store config parameters"); - iTimer=CSimTimer::NewL(iSmsMessaging->iPhone); - iIncomingTimer=CSimTimer::NewL(iSmsMessaging->iPhone); - } - -void CSimSmsStore::PopulateStoreFromConfigFile() -/** - * Populate the SMS Store from information in the configuration file. This is performed - * after the standard SMS Store construction in order to prevent reseting the configuation - * file accessor class' pointers while possibly multiple SMS Stores are created. - * - * The store entries comply to the following format: - * "SmsStoreEntry = , , , " - */ - { - LOGSMS1("Starting reading SMS Store entries..."); - TInt count=CfgFileSection()->ItemCount(KSmsStoreEntry); - const CTestConfigItem* item=NULL; - TInt ret=KErrNone; - - for(TInt i=0;iItem(KSmsStoreEntry,i); - if(!item) - break; - - TPtrC8 storeName; - ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,storeName); - if(ret!=KErrNone) - { - LOGPARSERR("storeName",ret,0,&KSmsStoreEntry); - continue; - } - if(storeName.MatchF(iSmsStoreName)!=0) - continue; // Not this store - - TInt index,stat; - TPtrC8 pdu; - ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,index); - if((ret!=KErrNone)||(index>=iSmsMaxNumSlots)) - { - LOGPARSERR("index",ret,1,&KSmsStoreEntry); - continue; - } - - ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,stat); - if(ret!=KErrNone) - { - LOGPARSERR("stat",ret,2,&KSmsStoreEntry); - continue; - } - - ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,pdu); - if(ret!=KErrNone) - { - LOGPARSERR("pdu",ret,3,&KSmsStoreEntry); - continue; - } - - TPtrC8 sca; - ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,4,sca); - if(ret!=KErrNone) - { - LOGPARSERR("sca",ret,4,&KSmsStoreEntry); - continue; - } - iGsmSmsStoreEntries[index].iIndex=index; - iGsmSmsStoreEntries[index].iMsgStatus=(RMobileSmsStore::TMobileSmsStoreStatus)stat; - ConvertAsciiSms(pdu,iGsmSmsStoreEntries[index].iMsgData); - RecordSca(sca, index); - } - - LOGSMS1("...Finished reading SMS Store entries"); - } - - - -void CSimSmsStore::RecordSca(const TDesC8& aAsciiAddr, TInt aIndex) -/** - * Used to set the sca number - * - * - * @param aAsciiSca Ascii representation of a telephone number such as the one found in the configuration file - * @param aType specifies whether aAsciiAddres should be used to fill in the sca or destination field of the smsp entry - * @param aIndex specifies at which index in the smsp list the number should be filled in - */ - { - if(aAsciiAddr.Length()>0)//only support for international numbers - { - iGsmSmsStoreEntries[aIndex].iServiceCentre.iNumberPlan=RMobilePhone::EIsdnNumberPlan; - iGsmSmsStoreEntries[aIndex].iServiceCentre.iTypeOfNumber=RMobilePhone::EInternationalNumber; - iGsmSmsStoreEntries[aIndex].iServiceCentre.iTelNumber.Copy(aAsciiAddr); - } - } - -CSimSmsStore::~CSimSmsStore() -/** - * Standard destructor. Any objects created by the ::ConstructL() function - * will be destroyed here. - */ - { - delete[] iGsmSmsStoreEntries; - - if (iSmsReadAll) - { - iSmsReadAll->ResetAndDestroy(); - delete iSmsReadAll; - } - - delete iTimer; - delete iIncomingTimer; - } - -#ifdef _DEBUG -void CSimSmsStore::LogRequest(TBool aEntering, TInt aIpc, TInt aError) -#else -void CSimSmsStore::LogRequest(TBool aEntering, TInt aIpc, TInt /*aError*/) -#endif -/** - * This method logs client requests to the t_reg.txt - * @param aEntering Tells if the request is entering into simtsy tsy or completing - * @param aIpc IPC number of request - * @param aError Error code that the request has - */ - { - TBuf8<64> ipcBuf; - - switch (aIpc) - { - case EMobilePhoneStoreGetInfo: - ipcBuf = _L8("GetInfo"); - break; - - case EMobilePhoneStoreNotifyStoreEvent: - ipcBuf = _L8("NotifyStoreEvent"); - break; - - case EMobilePhoneStoreRead: - ipcBuf = _L8("Read"); - break; - - case EMobilePhoneStoreWrite: - ipcBuf = _L8("Write"); - break; - - case EMobilePhoneStoreDelete: - ipcBuf = _L8("Delete"); - break; - - case EMobilePhoneStoreReadAllPhase1: - ipcBuf = _L8("ReadAllPhase1"); - break; - - - case EMobilePhoneStoreReadAllPhase2: - ipcBuf = _L8("ReadAllPhase2"); - break; - - case EMobilePhoneStoreDeleteAll: - ipcBuf = _L8("DeleteAll"); - break; - - default: - ipcBuf = _L8("OTHER"); - break; - } - - if (aEntering!=EFalse) - { - LOGSMS3(">>%d,CSimSmsStore::%S",aIpc, &ipcBuf ); - } - else - { - LOGSMS4("<<%d,CSimSmsStore::%S with error %d",aIpc, &ipcBuf, aError); - } - } - - - - -TInt CSimSmsStore::ExtFunc(const TTsyReqHandle aReqHandle,const TInt aIpc, const TDataPackage& aPckg) -/** - * Dispatch function for all SMS 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. - */ - { -// The following requests can be completed even if the completion of another request is pending. - TInt ret=KErrNone;//error is only used with LogRequest when at the end of ExtFunc - LogRequest(ETrue, aIpc, ret); - switch(aIpc) - { - case EMobilePhoneStoreGetInfo: - ret = GetInfo(aReqHandle,aPckg.Des1n()); - LogRequest(EFalse, aIpc, ret); - return ret; - - case EMobilePhoneStoreNotifyStoreEvent: - ret = NotifyStoreEvent(aReqHandle,aPckg.Des1n(),aPckg.Des2n()); - LogRequest(EFalse, aIpc, ret); - return ret; - - 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(iTimer->IsActive()) - { - ReqCompleted(aReqHandle,KErrInUse); - return KErrNone; - } - - switch(aIpc) - { - case EMobilePhoneStoreRead: - ret = Read(aReqHandle,aPckg.Des1n()); - break; - - case EMobilePhoneStoreWrite: - ret = Write(aReqHandle,aPckg.Des1n()); - break; - - case EMobilePhoneStoreDelete: - ret = Delete(aReqHandle,aPckg.Des1n()); - break; - - case EMobilePhoneStoreReadAllPhase1: - ret = ReadAllPhase1(aReqHandle,aPckg.Des1n(),aPckg.Des2n()); - break; - - case EMobilePhoneStoreReadAllPhase2: - ret = ReadAllPhase2(aReqHandle,aPckg.Des1n(),aPckg.Des2n()); - break; - - case EMobilePhoneStoreDeleteAll: - ret = DeleteAll(aReqHandle); - break; - - default: - return KErrNotSupported; - } - LogRequest(EFalse, aIpc, ret); - return ret; - - } - -CTelObject* CSimSmsStore::OpenNewObjectByNameL(const TDesC& /*aName*/) -/** - * The API does not support any objects that could be opened from this one. - */ - { - User::Leave(KErrNotSupported); - return NULL; - } - -CTelObject* CSimSmsStore::OpenNewObjectL(TDes&) -/** - * The API does not support any objects that could be opened from this one. - */ - { - User::Leave(KErrNotSupported); - return NULL; - } - -CTelObject::TReqMode CSimSmsStore::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 EMobilePhoneStoreRead: - case EMobilePhoneStoreWrite: - case EMobilePhoneStoreDelete: - case EMobilePhoneStoreReadAllPhase1: - case EMobilePhoneStoreReadAllPhase2: - case EMobilePhoneStoreDeleteAll: - break; - - case EMobilePhoneStoreNotifyStoreEvent: - ret=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately; - break; - - default: - User::Leave(KErrNotSupported); - break; - } - - return ret; - } - -TInt CSimSmsStore::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 CSimSmsStore::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 CSimSmsStore::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 CSimSmsStore::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 EMobilePhoneStoreRead: - case EMobilePhoneStoreWrite: - case EMobilePhoneStoreDelete: - if(iTimer->Running()) - { - iTimer->Cancel(); - ReqCompleted(iPendingReqCompletion,KErrCancel); - } - break; - case EMobilePhoneStoreReadAllPhase1: - ReadAllCancel(); - break; - case EMobilePhoneStoreDeleteAll: - DeleteAllCancel(); - break; - case EMobilePhoneStoreNotifyStoreEvent: - NotifyStoreEventCancel(); - break; - default: - break; - } - return KErrNone; - } - -void CSimSmsStore::Init() -/** - * This function can be used to perform any necessary synchronous initialisation. - */ - { - } - -TInt CSimSmsStore::GetInfo(TTsyReqHandle aReqHandle, TDes8* aPckg) -/** - * Retrieve SMS 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. - */ - { - RMobilePhoneStore::TMobilePhoneStoreInfoV1Pckg* getInfoPckg=(RMobilePhoneStore::TMobilePhoneStoreInfoV1Pckg*)aPckg; - RMobilePhoneStore::TMobilePhoneStoreInfoV1& getInfo=(*getInfoPckg)(); - - // Check that the data structure is supported by the simulated TSY version - TInt err = iPhone->CheckSimTsyVersion(getInfo); - if(err != KErrNone) - { - ReqCompleted(aReqHandle, err); - return KErrNone; - } - - getInfo.iType=RMobilePhoneStore::EShortMessageStore; - getInfo.iTotalEntries=MaxSlots(); - getInfo.iCaps=iSmsStoreCaps; - getInfo.iName.Copy(iSmsStoreName); - getInfo.iUsedEntries=UsedEntries(); - - ReqCompleted(aReqHandle,KErrNone); - return KErrNone; - } - -TInt CSimSmsStore::Read(TTsyReqHandle aReqHandle, TDes8* aPckg) -/** - * Read a single SMS store entry. 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 aPckg The parameter package associated with this request. - */ - { - if (!(iSmsStoreCaps & RMobilePhoneStore::KCapsIndividualEntry && iSmsStoreCaps & RMobilePhoneStore::KCapsReadAccess)) - { - ReqCompleted(aReqHandle, KErrAccessDenied); - return KErrNone; - } - - RMobileSmsStore::TMobileSmsEntryV1Pckg* smsPckg=(RMobileSmsStore::TMobileSmsEntryV1Pckg*)aPckg; - RMobileSmsStore::TMobileSmsEntryV1& sms=(*smsPckg)(); - - // Check that the data structure is supported by the simulated TSY version - TInt err = iPhone->CheckSimTsyVersion(sms); - if(err != KErrNone) - { - ReqCompleted(aReqHandle, err); - return KErrNone; - } - - switch (sms.ExtensionId()) - { - case RMobileSmsStore::KETelMobileGsmSmsEntryV1: - { - RMobileSmsStore::TMobileGsmSmsEntryV1Pckg* gsmSmsPckg=(RMobileSmsStore::TMobileGsmSmsEntryV1Pckg*)aPckg; - RMobileSmsStore::TMobileGsmSmsEntryV1& gsmSms=(*gsmSmsPckg)(); - - // Check that the data structure is supported by the simulated TSY version - TInt err = iPhone->CheckSimTsyVersion(gsmSms); - if(err != KErrNone) - { - ReqCompleted(aReqHandle, err); - return KErrNone; - } - - TInt& index=gsmSms.iIndex; - if((index<1)||(index>iSmsMaxNumSlots)) - { - ReqCompleted(aReqHandle,KErrArgument); - return KErrNone; - } - - if (iGsmSmsStoreEntries[index].iMsgStatus == KCorruptPDU) - { - ReqCompleted(aReqHandle,KErrCorrupt); - return KErrNone; - } - - if(iGsmSmsStoreEntries[index].iMsgData.Length()==0) - { - ReqCompleted(aReqHandle, KErrNotFound); - return KErrNone; - } - - gsmSms.iMsgData.Copy(iGsmSmsStoreEntries[index].iMsgData); - gsmSms.iMsgStatus=iGsmSmsStoreEntries[index].iMsgStatus; - gsmSms.iServiceCentre=iGsmSmsStoreEntries[index].iServiceCentre; - break; - } - case RMobileSmsStore::KETelMobileCdmaSmsEntryV1: - ReqCompleted(aReqHandle,KErrNotSupported); - return KErrNone; - - default: - ReqCompleted(aReqHandle,KErrArgument); - return KErrNone; - } - - DelayCompletion(iSmsIndividualPause,aReqHandle); - return KErrNone; - } - -TInt CSimSmsStore::Write(TTsyReqHandle aReqHandle,TDes8* aPckg) -/** - * Write a single SMS 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. - */ - { - if (!(iSmsStoreCaps & RMobilePhoneStore::KCapsIndividualEntry && iSmsStoreCaps & RMobilePhoneStore::KCapsWriteAccess)) - { - ReqCompleted(aReqHandle, KErrAccessDenied); - return KErrNone; - } - - TStoreEvent event=EStoreEventNoEvent; - TInt index; - - RMobileSmsStore::TMobileSmsEntryV1Pckg* smsPckg=(RMobileSmsStore::TMobileSmsEntryV1Pckg*)aPckg; - RMobileSmsStore::TMobileSmsEntryV1& sms=(*smsPckg)(); - - // Check that the data structure is supported by the simulated TSY version - TInt err = iPhone->CheckSimTsyVersion(sms); - if(err != KErrNone) - { - ReqCompleted(aReqHandle, err); - return KErrNone; - } - - switch (sms.ExtensionId()) - { - case RMobileSmsStore::KETelMobileGsmSmsEntryV1: - { - RMobileSmsStore::TMobileGsmSmsEntryV1Pckg* gsmSmsPckg=(RMobileSmsStore::TMobileGsmSmsEntryV1Pckg*)aPckg; - RMobileSmsStore::TMobileGsmSmsEntryV1& gsmSms=(*gsmSmsPckg)(); - - // Check that the data structure is supported by the simulated TSY version - TInt err = iPhone->CheckSimTsyVersion(gsmSms); - if(err != KErrNone) - { - ReqCompleted(aReqHandle, err); - return KErrNone; - } - - index=gsmSms.iIndex; - if(index==-1)//check the 1st free slot - { - for(TInt i=1;i<=iSmsMaxNumSlots;i++) - { - if(iGsmSmsStoreEntries[i].iMsgData.Length()==0) - { - index=i; - //ret = KErrNone; - break; - } - } - } - //else ret = KErrNone;//if index is specified entry will be overwitten, not possible to exceed memory - if((index<1)||(index>iSmsMaxNumSlots)) - { - ReqCompleted(aReqHandle,KErrArgument); - return KErrNone; - } - - // - // This can never happen because either ret is KErrNone or - // index is still -1 and we have returned. - // - //if (ret==KErrNoMemory) - //ReqCompleted(aReqHandle,ret); - - if(iGsmSmsStoreEntries[index].iMsgData.Length()==0) - event=EStoreEventAdded; - else - event=EStoreEventChanged; - - gsmSms.iIndex = index; // Update index data member for the client - iGsmSmsStoreEntries[index].iIndex=index; - iGsmSmsStoreEntries[index].iMsgData.Copy(gsmSms.iMsgData); - iGsmSmsStoreEntries[index].iMsgStatus=gsmSms.iMsgStatus; - iGsmSmsStoreEntries[index].iServiceCentre=gsmSms.iServiceCentre; - break; - } - case RMobileSmsStore::KETelMobileCdmaSmsEntryV1: - ReqCompleted(aReqHandle,KErrNotSupported); - return KErrNone; - - default: - ReqCompleted(aReqHandle,KErrArgument); - return KErrNone; - } - - DelayCompletion(iSmsIndividualPause,aReqHandle,event,index); - return KErrNone; - } - -TInt CSimSmsStore::StoreIncomingMessage(RMobileSmsStore::TMobileGsmSmsEntryV1* aSms) -/** - * This method is used to store Incoming sms messages with the status EMtMessageStored - * It is accessed by CSimSmsMessaging::AttemptSmsRxCompleteL. - * Note: this will not call ReqComplete as no client request has been posted on this class - * Note: the smsStack will delete the message from the store after ReceiveMessage has completed - **/ - { - - TInt& index=aSms->iIndex; - TInt ret=KErrNoMemory; - TStoreEvent event=EStoreEventNoEvent; - for(TInt i=1;i<=iSmsMaxNumSlots;i++) - { - if(iGsmSmsStoreEntries[i].iMsgData.Length()==0) - { - index=i; - event=EStoreEventAdded; - ret = KErrNone; - break; - } - - } - - aSms->iIndex=index;//set here to be used by CSimSmsMessaging - - if (ret==KErrNone) - { - iGsmSmsStoreEntries[index].iIndex=index; - iGsmSmsStoreEntries[index].iMsgData.Copy(aSms->iMsgData); - iGsmSmsStoreEntries[index].iMsgStatus=aSms->iMsgStatus; - iGsmSmsStoreEntries[index].iServiceCentre=aSms->iServiceCentre; - - iPendingEvent=event; - iPendingIndex=index; - iIncomingTimer->Start(iSmsIndividualPause,this, 1);//delay the notification - } - - return ret; - } - - -TInt CSimSmsStore::Delete(TTsyReqHandle aReqHandle,TDes8* aPckg) -/** - * Delete a single SMS 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 (!(iSmsStoreCaps & RMobilePhoneStore::KCapsIndividualEntry && iSmsStoreCaps & RMobilePhoneStore::KCapsWriteAccess)) - { - ReqCompleted(aReqHandle, KErrAccessDenied); - return KErrNone; - } - - TPckg* intPckg=(TPckg*)aPckg; - TInt& index=(*intPckg)(); - - if((index<1)||(index>iSmsMaxNumSlots)) - { - ReqCompleted(aReqHandle,KErrArgument); - return KErrNone; - } - - iGsmSmsStoreEntries[index].iMsgData.Zero(); - iGsmSmsStoreEntries[index].iMsgStatus=RMobileSmsStore::EStoredMessageUnknownStatus; - iGsmSmsStoreEntries[index].iServiceCentre.iTelNumber=KNullTelephoneNumber; - - DelayCompletion(iSmsIndividualPause,aReqHandle,EStoreEventDeleted,index); - return KErrNone; - } - -TInt CSimSmsStore::ReadAllPhase1(TTsyReqHandle aReqHandle,TDes8* aPckg1,TDes8* aPckg2) -/** - * First phase of a batch SMS Store read. The completion of this request is delayed in - * order to simulate a real TSY that would have to get the information from a SIM card. - * If the GetSmspListPhase1L should leave this method takes care of that and - * makes a premature ReqCompleted to the client. - * - * @param aReqHandle The TSY request handle associated with this request. - * @param aPckg1 The first parameter package associated with this request. - * It contains the client ID information required to uniquely identify this request. - * It also contains the batch read information (first slot, number of slots). - * @param aPckg2 The parameter package associated with this request. - * The size of the information to be passed back to the client is returned in this package. - * @return Standard return value. - */ { - if (!(iSmsStoreCaps & static_cast(RMobilePhoneStore::KCapsWholeStore) && iSmsStoreCaps & RMobilePhoneStore::KCapsReadAccess)) - { - ReqCompleted(aReqHandle, KErrAccessDenied); - return KErrNone; - } - - - TPckg* clientIdPckg=(TPckg*) aPckg1; - CRetrieveMobilePhoneSmsList::TBatchRequestData& clientId=(*clientIdPckg)(); - TPckg* sizePckg=(TPckg*)aPckg2; - TInt& size=(*sizePckg)(); - - TRAPD(leaveCode,ReadAllPhase1L(aReqHandle,clientId,size)); - - return leaveCode; - } - - - - -void CSimSmsStore::ReadAllPhase1L(TTsyReqHandle aReqHandle,CRetrieveMobilePhoneSmsList::TBatchRequestData& aClientId, - TInt& aBufSize) -/** - * Implementation of ReadAllPhase1. - * - */ - - { - TInt cnt=0; - CMobilePhoneListBase* listBase = NULL; - - if ((CSimTsyMode::GetMode() != CSimTsyMode::ECdmaV1) && - (aClientId.iEntryType == RMobileSmsStore::KETelMobileGsmSmsEntryV1)) - { - listBase = CMobilePhoneGsmSmsList::NewL(); - } - else - { - // Nothing to read. - ReqCompleted(aReqHandle, KErrNone); - return; - } - - CleanupStack::PushL(listBase); - - if(!aClientId.iBatchRequest) - { - aClientId.iStartIndex=1; - aClientId.iBatchSize=iSmsMaxNumSlots; - } - - for(TInt i = aClientId.iStartIndex; cnt < aClientId.iBatchSize; i++) - { - if (i > iSmsMaxNumSlots) - break; - - if (aClientId.iEntryType == RMobileSmsStore::KETelMobileGsmSmsEntryV1) - { - if (iGsmSmsStoreEntries[i].iMsgData.Length() != 0) - { - ((CMobilePhoneGsmSmsList*)listBase)->AddEntryL(iGsmSmsStoreEntries[i]); - cnt++; - } - } - - } - - // Store the streamed list and the client ID - CListReadAllAttempt* read=CListReadAllAttempt::NewL(aClientId.iClient, aReqHandle); - CleanupStack::PushL(read); - - read->iListBuf = listBase->StoreLC(); - CleanupStack::Pop(); // pop the CBufFlat allocated by StoreLC - - iSmsReadAll->AppendL(read); - CleanupStack::Pop(); // pop the CListReadAllAttempt - - // return the CBufFlat’s size to client - aBufSize=(read->iListBuf)->Size(); - - CleanupStack::PopAndDestroy(); // pop&destroy list - // Complete first phase of list retrieval - - DelayCompletion(iSmsBatchPause,aReqHandle); -// return KErrNone; - } - -TInt CSimSmsStore::ReadAllPhase2(TTsyReqHandle aReqHandle,TDes8* aPckg1,TDes8* aBuffer) -/** - * Second phase of a batch SMS Store read. The completion of this request is not delayed - * as it is assumed that the TSY has already cached the required information (during the - * first phase of the read). - * - * @param aReqHandle The TSY request handle associated with this request. - * @param aPckg1 The first parameter package associated with this request. - * It contains the client ID information required to uniquely identify this request. - * @param aBuffer The parameter package associated with this request. - * It contains the read buffer in which the required information is returned. - * @return Standard return value. - */ - { - TPckg* clientIdPckg=(TPckg*) aPckg1; - RMobilePhone::TClientId& clientId=(*clientIdPckg)(); - - for (TInt i=0; iCount(); ++i) - { - CListReadAllAttempt* read = iSmsReadAll->At(i); - if ((read->iClient.iSessionHandle==clientId.iSessionHandle) && - (read->iClient.iSubSessionHandle==clientId.iSubSessionHandle)) - { - TPtr8 bufPtr((read->iListBuf)->Ptr(0)); - // Copy the streamed list to the client - aBuffer->Copy(bufPtr); - delete read; - iSmsReadAll->Delete(i); - ReqCompleted(aReqHandle,KErrNone); - return KErrNone; - } - } - -// Don't delay completion of this request, as we assume the TSY will have the results in -// memory from the first request. - ReqCompleted(aReqHandle,KErrNotFound); - return KErrNone; - } - -TInt CSimSmsStore::DeleteAll(TTsyReqHandle aReqHandle) -/** - * Delete all entries in the SIM 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 SMS Store notification. - * - * @param aReqHandle The TSY request handle associated with this request. - * @return Standard return value. - */ - { - if (!(iSmsStoreCaps & static_cast(RMobilePhoneStore::KCapsWholeStore) && iSmsStoreCaps & RMobilePhoneStore::KCapsWriteAccess)) - { - ReqCompleted(aReqHandle, KErrAccessDenied); - return KErrNone; - } - - for(TInt i=1;i<=iSmsMaxNumSlots;i++) - { - - iGsmSmsStoreEntries[i].iIndex=i; - iGsmSmsStoreEntries[i].iMsgStatus=RMobileSmsStore::EStoredMessageUnknownStatus; - iGsmSmsStoreEntries[i].iMsgData.Zero(); - iGsmSmsStoreEntries[i].iServiceCentre.iTelNumber=KNullTelephoneNumber; - - } - - DelayCompletion(iSmsBatchPause,aReqHandle,EStoreEventDeleted,-1); - return KErrNone; - } - -TInt CSimSmsStore::NotifyStoreEvent(TTsyReqHandle aReqHandle,TDes8* aPckg1,TDes8* aPckg2) -/** - * Register a client's interest in SMS 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. - */ - { - if (!(iSmsStoreCaps & RMobilePhoneStore::KCapsNotifyEvent)) - { - ReqCompleted(aReqHandle, KErrNotSupported); - return KErrNone; - } - - __ASSERT_ALWAYS(iEvOutstandingReq==EFalse,SimPanic(ENotificationAlreadyPending)); - - TPckg* eventPckg=(TPckg*)aPckg1; - TUint32& event=(*eventPckg)(); - TPckg* indexPckg=(TPckg*)aPckg2; - TInt& index=(*indexPckg)(); - - iEvOutstandingReq=ETrue; - iEvReqHandle=aReqHandle; - iEvEvent=&event; - iEvIndex=&index; - return KErrNone; - } - -void CSimSmsStore::NotifyStoreEventCancel() -/** - * Cancel an outstanding notify store request. - */ - { - if(iEvOutstandingReq) - { - iEvOutstandingReq=EFalse; - ReqCompleted(iEvReqHandle,KErrCancel); - } - } - -//coverity[bad_override] -TPtrC8 CSimSmsStore::Name() -/** - * Accessor function fot the SMS Store name. - * - * @return TPtrC8 The name of this SMS Store. - */ - { - return iSmsStoreName; - } - -TInt CSimSmsStore::UsedEntries() -/** - * Count the number of used entries in the SMS Store. - * @return TInt The number of used entries in the store. - */ - { - TInt cnt=0; - for(TInt i=1;i<=iSmsMaxNumSlots;i++) - { - if(iGsmSmsStoreEntries[i].iMsgData.Length()!=0) - cnt++; - } - return cnt; - } - -TInt CSimSmsStore::MaxSlots() -/** - * Retrieve the maximum number of slots in this SMS Store. - * @return TInt The maximum number of slots in this SMS Store. - */ - { - return iSmsMaxNumSlots; - } - -void CSimSmsStore::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); - } - -TUint CSimSmsStore::StoreCaps() - { - return iSmsStoreCaps; - } - -void CSimSmsStore::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; - iTimer->Start(aDelayDuration,this); - } - - -void CSimSmsStore::ReadAllCancel() -/* - * Cancel an outstanding read/write smsp. - */ - { - iTimer->Cancel(); - ReqCompleted(iPendingReqCompletion,KErrCancel); - } - -void CSimSmsStore::DeleteAllCancel() -/* - * Cancel an outstanding read/write smsp. - */ - { - iTimer->Cancel(); - ReqCompleted(iPendingReqCompletion,KErrNone);//The timer is cancelled but data has already been deleted - } - -void CSimSmsStore::TimerCallBack(TInt aId) -/** - * Process a timer call back event. The timer is used to kick requests which have had their - * completions delayed. - */ - { - StoreEvent(iPendingEvent,iPendingIndex); - if (aId!=1)//aId is 1 if reuest is StoreIncomingMessage(coming from CSimSmsMessaging) - ReqCompleted(iPendingReqCompletion,KErrNone); - } - -void CSimSmsStore::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; - } - - if(UsedEntries()==0) - event|=RMobilePhoneStore::KStoreEmpty; - - if(UsedEntries()==iSmsMaxNumSlots) - event|=RMobilePhoneStore::KStoreFull; - else - event|=RMobilePhoneStore::KStoreHasSpace; - - *iEvEvent=event; - *iEvIndex=aIndex; - iEvOutstandingReq=EFalse; - ReqCompleted(iEvReqHandle,KErrNone); - } - } - -const CTestConfigSection* CSimSmsStore::CfgFileSection() -/** -* Returns a pointer to the config file section -* -* @return CTestConfigSection a pointer to the configuration file data section -*/ - { - LOGSMS1(">>CSimSmsStore::CfgFileSection"); - return iSmsMessaging->CfgFileSection(); - } - +// Copyright (c) 2003-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 SMS Store manipulation code. +// +// + +/** + @file +*/ + +#include +#include +#include +#include "CSimSmsStore.h" +#include "csimsmsmess.h" +#include "Simlog.h" +#include "CSimTsyMode.h" + +const TInt KSmsStoreGranularity=2; +const TInt KCorruptPDU=9999; +_LIT(KNullTelephoneNumber,"0"); + + +CListReadAllAttempt* CListReadAllAttempt::NewL(RMobilePhone::TClientId& aId, TTsyReqHandle aReqHandle) +/** + * Standard two phase constructor. + * @param aId The client ID (session and sub-session handles) that uniquely identifies a client performing a two phase read. + * @param aReqHandle The TSY request handle of the client request associated with a two phase read. + * @return CListReadAllAttempt* The newly created object. + */ + { + CListReadAllAttempt* read=new(ELeave) CListReadAllAttempt(aId, aReqHandle); + CleanupStack::PushL(read); + read->ConstructL(); + CleanupStack::Pop(); + return read; + } + +CListReadAllAttempt::CListReadAllAttempt(RMobilePhone::TClientId& aId, TTsyReqHandle aReqHandle) + : iListBuf(NULL),iReqHandle(aReqHandle) +/** + * Trivial first phase constructor. + * @param aId The client ID (session and sub-session handles) that uniquely identifies a client performing a two phase read. + * @param aReqHandle The TSY request handle of the client request associated with a two phase read. + */ + { + iClient.iSessionHandle=aId.iSessionHandle; + iClient.iSubSessionHandle=aId.iSubSessionHandle; + iReqHandle=aReqHandle; + iListBuf = NULL; + } + +void CListReadAllAttempt::ConstructL() +/** + * Trivial second phase constructor. + */ + { + } + +CListReadAllAttempt::~CListReadAllAttempt() +/** + * Trivial destructor. + */ + { + delete iListBuf; + } + +// +// CSimSmsStore +// +void CSimSmsStore::ClosePhone(TAny* aObj) +/** + * A utility function for cleaning up the stack. + */ + { + ((CObject*)aObj)->Close(); + } + +CSimSmsStore* CSimSmsStore::NewL(CSimSmsMessaging* aSimSmsMess, const TDesC8& aName, TInt aMaxNumSlots, CSimPhone* aPhone) +/** + * Standard two phase constructor. + * @param aSimSmsMess The SMS Messaging object from which this SMS Store was opened. + * @param aName The name of the created SMS Store. + * @param aMaxNumSlots The maximum number of slots in the SMS Store. + * @return CSimSmsStore* The newly created object. + */ + { + CSimSmsStore* store=new(ELeave) CSimSmsStore(aSimSmsMess, aPhone); + TCleanupItem newObjClose(ClosePhone,store); + CleanupStack::PushL(newObjClose); + store->ConstructL(aName,aMaxNumSlots); + CleanupStack::Pop(); + return store; + } + +CSimSmsStore::CSimSmsStore(CSimSmsMessaging* aSmsMess, CSimPhone* aPhone) + : iSmsMessaging(aSmsMess), iEvOutstandingReq(EFalse), iPhone(aPhone) +/** + * Trivial first phase constructor. + * @param aSimSmsMess The SMS Messaging object from which this SMS Store was opened. + */ + {} + +void CSimSmsStore::ConstructL(const TDesC8& aName, TInt aMaxNumSlots) +/** + * Second phase constructor that allocates memory for the SMS store, 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 SMS Store. + * @param aMaxNumSlots The maximum number of slots in the SMS Store. + */ + { + iGsmSmsStoreEntries=new(ELeave) RMobileSmsStore::TMobileGsmSmsEntryV1[aMaxNumSlots+1];//index 0 is not used + iSmsMaxNumSlots=aMaxNumSlots; + iSmsStoreName.Copy(aName); + iSmsReadAll=new(ELeave) CArrayPtrFlat(KSmsStoreGranularity); + LOGSMS1("Starting to parse SMS Store config parameters..."); + iSmsIndividualPause=CfgFileSection()->ItemValue(KSmsStoreIndividualReqPause,KDefaultSmsStoreIndividualReqPause); + iSmsBatchPause=CfgFileSection()->ItemValue(KSmsStoreBatchReqPause,KDefaultSmsStoreBatchReqPause); + + const CTestConfigItem* item0=NULL; + item0=CfgFileSection()->Item(KSmsPhoneStoreCaps,0); + if (item0) + { + TPtrC8 value0; + TInt ret0=CTestConfig::GetElement(item0->Value(),KStdDelimiter,0,value0); + if(ret0!=KErrNone) + { + LOGPARSERR("value0",ret0,0,&KSmsPhoneStoreCaps); + iSmsStoreCaps=KDefaultSmsPhoneStoreCaps+KDefaultSmsOnlySmsCaps; + } + else + { + TUint32 intValue; + TInt ret = AsciiToNum(value0, intValue); + if(ret!=KErrNone) + iSmsStoreCaps=KDefaultSmsPhoneStoreCaps+KDefaultSmsOnlySmsCaps; + else + iSmsStoreCaps = intValue+KDefaultSmsOnlySmsCaps; + } + } + else + iSmsStoreCaps=KDefaultSmsPhoneStoreCaps+KDefaultSmsOnlySmsCaps; + + + LOGSMS1("...Finished parsing SMS Store config parameters"); + iTimer=CSimTimer::NewL(iSmsMessaging->iPhone); + iIncomingTimer=CSimTimer::NewL(iSmsMessaging->iPhone); + } + +void CSimSmsStore::PopulateStoreFromConfigFile() +/** + * Populate the SMS Store from information in the configuration file. This is performed + * after the standard SMS Store construction in order to prevent reseting the configuation + * file accessor class' pointers while possibly multiple SMS Stores are created. + * + * The store entries comply to the following format: + * "SmsStoreEntry = , , , " + */ + { + LOGSMS1("Starting reading SMS Store entries..."); + TInt count=CfgFileSection()->ItemCount(KSmsStoreEntry); + const CTestConfigItem* item=NULL; + TInt ret=KErrNone; + + for(TInt i=0;iItem(KSmsStoreEntry,i); + if(!item) + break; + + TPtrC8 storeName; + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,storeName); + if(ret!=KErrNone) + { + LOGPARSERR("storeName",ret,0,&KSmsStoreEntry); + continue; + } + if(storeName.MatchF(iSmsStoreName)!=0) + continue; // Not this store + + TInt index,stat; + TPtrC8 pdu; + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,index); + if((ret!=KErrNone)||(index>=iSmsMaxNumSlots)) + { + LOGPARSERR("index",ret,1,&KSmsStoreEntry); + continue; + } + + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,stat); + if(ret!=KErrNone) + { + LOGPARSERR("stat",ret,2,&KSmsStoreEntry); + continue; + } + + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,pdu); + if(ret!=KErrNone) + { + LOGPARSERR("pdu",ret,3,&KSmsStoreEntry); + continue; + } + + TPtrC8 sca; + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,4,sca); + if(ret!=KErrNone) + { + LOGPARSERR("sca",ret,4,&KSmsStoreEntry); + continue; + } + iGsmSmsStoreEntries[index].iIndex=index; + iGsmSmsStoreEntries[index].iMsgStatus=(RMobileSmsStore::TMobileSmsStoreStatus)stat; + ConvertAsciiSms(pdu,iGsmSmsStoreEntries[index].iMsgData); + RecordSca(sca, index); + } + + LOGSMS1("...Finished reading SMS Store entries"); + } + + + +void CSimSmsStore::RecordSca(const TDesC8& aAsciiAddr, TInt aIndex) +/** + * Used to set the sca number + * + * + * @param aAsciiSca Ascii representation of a telephone number such as the one found in the configuration file + * @param aType specifies whether aAsciiAddres should be used to fill in the sca or destination field of the smsp entry + * @param aIndex specifies at which index in the smsp list the number should be filled in + */ + { + if(aAsciiAddr.Length()>0)//only support for international numbers + { + iGsmSmsStoreEntries[aIndex].iServiceCentre.iNumberPlan=RMobilePhone::EIsdnNumberPlan; + iGsmSmsStoreEntries[aIndex].iServiceCentre.iTypeOfNumber=RMobilePhone::EInternationalNumber; + iGsmSmsStoreEntries[aIndex].iServiceCentre.iTelNumber.Copy(aAsciiAddr); + } + } + +CSimSmsStore::~CSimSmsStore() +/** + * Standard destructor. Any objects created by the ::ConstructL() function + * will be destroyed here. + */ + { + delete[] iGsmSmsStoreEntries; + + if (iSmsReadAll) + { + iSmsReadAll->ResetAndDestroy(); + delete iSmsReadAll; + } + + delete iTimer; + delete iIncomingTimer; + } + +#ifdef _DEBUG +void CSimSmsStore::LogRequest(TBool aEntering, TInt aIpc, TInt aError) +#else +void CSimSmsStore::LogRequest(TBool aEntering, TInt aIpc, TInt /*aError*/) +#endif +/** + * This method logs client requests to the t_reg.txt + * @param aEntering Tells if the request is entering into simtsy tsy or completing + * @param aIpc IPC number of request + * @param aError Error code that the request has + */ + { + TBuf8<64> ipcBuf; + + switch (aIpc) + { + case EMobilePhoneStoreGetInfo: + ipcBuf = _L8("GetInfo"); + break; + + case EMobilePhoneStoreNotifyStoreEvent: + ipcBuf = _L8("NotifyStoreEvent"); + break; + + case EMobilePhoneStoreRead: + ipcBuf = _L8("Read"); + break; + + case EMobilePhoneStoreWrite: + ipcBuf = _L8("Write"); + break; + + case EMobilePhoneStoreDelete: + ipcBuf = _L8("Delete"); + break; + + case EMobilePhoneStoreReadAllPhase1: + ipcBuf = _L8("ReadAllPhase1"); + break; + + + case EMobilePhoneStoreReadAllPhase2: + ipcBuf = _L8("ReadAllPhase2"); + break; + + case EMobilePhoneStoreDeleteAll: + ipcBuf = _L8("DeleteAll"); + break; + + default: + ipcBuf = _L8("OTHER"); + break; + } + + if (aEntering!=EFalse) + { + LOGSMS3(">>%d,CSimSmsStore::%S",aIpc, &ipcBuf ); + } + else + { + LOGSMS4("<<%d,CSimSmsStore::%S with error %d",aIpc, &ipcBuf, aError); + } + } + + + + +TInt CSimSmsStore::ExtFunc(const TTsyReqHandle aReqHandle,const TInt aIpc, const TDataPackage& aPckg) +/** + * Dispatch function for all SMS 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. + */ + { +// The following requests can be completed even if the completion of another request is pending. + TInt ret=KErrNone;//error is only used with LogRequest when at the end of ExtFunc + LogRequest(ETrue, aIpc, ret); + switch(aIpc) + { + case EMobilePhoneStoreGetInfo: + ret = GetInfo(aReqHandle,aPckg.Des1n()); + LogRequest(EFalse, aIpc, ret); + return ret; + + case EMobilePhoneStoreNotifyStoreEvent: + ret = NotifyStoreEvent(aReqHandle,aPckg.Des1n(),aPckg.Des2n()); + LogRequest(EFalse, aIpc, ret); + return ret; + + 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(iTimer->IsActive()) + { + ReqCompleted(aReqHandle,KErrInUse); + return KErrNone; + } + + switch(aIpc) + { + case EMobilePhoneStoreRead: + ret = Read(aReqHandle,aPckg.Des1n()); + break; + + case EMobilePhoneStoreWrite: + ret = Write(aReqHandle,aPckg.Des1n()); + break; + + case EMobilePhoneStoreDelete: + ret = Delete(aReqHandle,aPckg.Des1n()); + break; + + case EMobilePhoneStoreReadAllPhase1: + ret = ReadAllPhase1(aReqHandle,aPckg.Des1n(),aPckg.Des2n()); + break; + + case EMobilePhoneStoreReadAllPhase2: + ret = ReadAllPhase2(aReqHandle,aPckg.Des1n(),aPckg.Des2n()); + break; + + case EMobilePhoneStoreDeleteAll: + ret = DeleteAll(aReqHandle); + break; + + default: + return KErrNotSupported; + } + LogRequest(EFalse, aIpc, ret); + return ret; + + } + +CTelObject* CSimSmsStore::OpenNewObjectByNameL(const TDesC& /*aName*/) +/** + * The API does not support any objects that could be opened from this one. + */ + { + User::Leave(KErrNotSupported); + return NULL; + } + +CTelObject* CSimSmsStore::OpenNewObjectL(TDes&) +/** + * The API does not support any objects that could be opened from this one. + */ + { + User::Leave(KErrNotSupported); + return NULL; + } + +CTelObject::TReqMode CSimSmsStore::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 EMobilePhoneStoreRead: + case EMobilePhoneStoreWrite: + case EMobilePhoneStoreDelete: + case EMobilePhoneStoreReadAllPhase1: + case EMobilePhoneStoreReadAllPhase2: + case EMobilePhoneStoreDeleteAll: + break; + + case EMobilePhoneStoreNotifyStoreEvent: + ret=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately; + break; + + default: + User::Leave(KErrNotSupported); + break; + } + + return ret; + } + +TInt CSimSmsStore::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 CSimSmsStore::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 CSimSmsStore::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 CSimSmsStore::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 EMobilePhoneStoreRead: + case EMobilePhoneStoreWrite: + case EMobilePhoneStoreDelete: + if(iTimer->Running()) + { + iTimer->Cancel(); + ReqCompleted(iPendingReqCompletion,KErrCancel); + } + break; + case EMobilePhoneStoreReadAllPhase1: + ReadAllCancel(); + break; + case EMobilePhoneStoreDeleteAll: + DeleteAllCancel(); + break; + case EMobilePhoneStoreNotifyStoreEvent: + NotifyStoreEventCancel(); + break; + default: + break; + } + return KErrNone; + } + +void CSimSmsStore::Init() +/** + * This function can be used to perform any necessary synchronous initialisation. + */ + { + } + +TInt CSimSmsStore::GetInfo(TTsyReqHandle aReqHandle, TDes8* aPckg) +/** + * Retrieve SMS 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. + */ + { + RMobilePhoneStore::TMobilePhoneStoreInfoV1Pckg* getInfoPckg=(RMobilePhoneStore::TMobilePhoneStoreInfoV1Pckg*)aPckg; + RMobilePhoneStore::TMobilePhoneStoreInfoV1& getInfo=(*getInfoPckg)(); + + // Check that the data structure is supported by the simulated TSY version + TInt err = iPhone->CheckSimTsyVersion(getInfo); + if(err != KErrNone) + { + ReqCompleted(aReqHandle, err); + return KErrNone; + } + + getInfo.iType=RMobilePhoneStore::EShortMessageStore; + getInfo.iTotalEntries=MaxSlots(); + getInfo.iCaps=iSmsStoreCaps; + getInfo.iName.Copy(iSmsStoreName); + getInfo.iUsedEntries=UsedEntries(); + + ReqCompleted(aReqHandle,KErrNone); + return KErrNone; + } + +TInt CSimSmsStore::Read(TTsyReqHandle aReqHandle, TDes8* aPckg) +/** + * Read a single SMS store entry. 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 aPckg The parameter package associated with this request. + */ + { + if (!(iSmsStoreCaps & RMobilePhoneStore::KCapsIndividualEntry && iSmsStoreCaps & RMobilePhoneStore::KCapsReadAccess)) + { + ReqCompleted(aReqHandle, KErrAccessDenied); + return KErrNone; + } + + RMobileSmsStore::TMobileSmsEntryV1Pckg* smsPckg=(RMobileSmsStore::TMobileSmsEntryV1Pckg*)aPckg; + RMobileSmsStore::TMobileSmsEntryV1& sms=(*smsPckg)(); + + // Check that the data structure is supported by the simulated TSY version + TInt err = iPhone->CheckSimTsyVersion(sms); + if(err != KErrNone) + { + ReqCompleted(aReqHandle, err); + return KErrNone; + } + + switch (sms.ExtensionId()) + { + case RMobileSmsStore::KETelMobileGsmSmsEntryV1: + { + RMobileSmsStore::TMobileGsmSmsEntryV1Pckg* gsmSmsPckg=(RMobileSmsStore::TMobileGsmSmsEntryV1Pckg*)aPckg; + RMobileSmsStore::TMobileGsmSmsEntryV1& gsmSms=(*gsmSmsPckg)(); + + // Check that the data structure is supported by the simulated TSY version + TInt err = iPhone->CheckSimTsyVersion(gsmSms); + if(err != KErrNone) + { + ReqCompleted(aReqHandle, err); + return KErrNone; + } + + TInt& index=gsmSms.iIndex; + if((index<1)||(index>iSmsMaxNumSlots)) + { + ReqCompleted(aReqHandle,KErrArgument); + return KErrNone; + } + + if (iGsmSmsStoreEntries[index].iMsgStatus == KCorruptPDU) + { + ReqCompleted(aReqHandle,KErrCorrupt); + return KErrNone; + } + + if(iGsmSmsStoreEntries[index].iMsgData.Length()==0) + { + ReqCompleted(aReqHandle, KErrNotFound); + return KErrNone; + } + + gsmSms.iMsgData.Copy(iGsmSmsStoreEntries[index].iMsgData); + gsmSms.iMsgStatus=iGsmSmsStoreEntries[index].iMsgStatus; + gsmSms.iServiceCentre=iGsmSmsStoreEntries[index].iServiceCentre; + break; + } + case RMobileSmsStore::KETelMobileCdmaSmsEntryV1: + ReqCompleted(aReqHandle,KErrNotSupported); + return KErrNone; + + default: + ReqCompleted(aReqHandle,KErrArgument); + return KErrNone; + } + + DelayCompletion(iSmsIndividualPause,aReqHandle); + return KErrNone; + } + +TInt CSimSmsStore::Write(TTsyReqHandle aReqHandle,TDes8* aPckg) +/** + * Write a single SMS 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. + */ + { + if (!(iSmsStoreCaps & RMobilePhoneStore::KCapsIndividualEntry && iSmsStoreCaps & RMobilePhoneStore::KCapsWriteAccess)) + { + ReqCompleted(aReqHandle, KErrAccessDenied); + return KErrNone; + } + + TStoreEvent event=EStoreEventNoEvent; + TInt index; + + RMobileSmsStore::TMobileSmsEntryV1Pckg* smsPckg=(RMobileSmsStore::TMobileSmsEntryV1Pckg*)aPckg; + RMobileSmsStore::TMobileSmsEntryV1& sms=(*smsPckg)(); + + // Check that the data structure is supported by the simulated TSY version + TInt err = iPhone->CheckSimTsyVersion(sms); + if(err != KErrNone) + { + ReqCompleted(aReqHandle, err); + return KErrNone; + } + + switch (sms.ExtensionId()) + { + case RMobileSmsStore::KETelMobileGsmSmsEntryV1: + { + RMobileSmsStore::TMobileGsmSmsEntryV1Pckg* gsmSmsPckg=(RMobileSmsStore::TMobileGsmSmsEntryV1Pckg*)aPckg; + RMobileSmsStore::TMobileGsmSmsEntryV1& gsmSms=(*gsmSmsPckg)(); + + // Check that the data structure is supported by the simulated TSY version + TInt err = iPhone->CheckSimTsyVersion(gsmSms); + if(err != KErrNone) + { + ReqCompleted(aReqHandle, err); + return KErrNone; + } + + index=gsmSms.iIndex; + if(index==-1)//check the 1st free slot + { + for(TInt i=1;i<=iSmsMaxNumSlots;i++) + { + if(iGsmSmsStoreEntries[i].iMsgData.Length()==0) + { + index=i; + //ret = KErrNone; + break; + } + } + } + //else ret = KErrNone;//if index is specified entry will be overwitten, not possible to exceed memory + if((index<1)||(index>iSmsMaxNumSlots)) + { + ReqCompleted(aReqHandle,KErrArgument); + return KErrNone; + } + + // + // This can never happen because either ret is KErrNone or + // index is still -1 and we have returned. + // + //if (ret==KErrNoMemory) + //ReqCompleted(aReqHandle,ret); + + if(iGsmSmsStoreEntries[index].iMsgData.Length()==0) + event=EStoreEventAdded; + else + event=EStoreEventChanged; + + gsmSms.iIndex = index; // Update index data member for the client + iGsmSmsStoreEntries[index].iIndex=index; + iGsmSmsStoreEntries[index].iMsgData.Copy(gsmSms.iMsgData); + iGsmSmsStoreEntries[index].iMsgStatus=gsmSms.iMsgStatus; + iGsmSmsStoreEntries[index].iServiceCentre=gsmSms.iServiceCentre; + break; + } + case RMobileSmsStore::KETelMobileCdmaSmsEntryV1: + ReqCompleted(aReqHandle,KErrNotSupported); + return KErrNone; + + default: + ReqCompleted(aReqHandle,KErrArgument); + return KErrNone; + } + + DelayCompletion(iSmsIndividualPause,aReqHandle,event,index); + return KErrNone; + } + +TInt CSimSmsStore::StoreIncomingMessage(RMobileSmsStore::TMobileGsmSmsEntryV1* aSms) +/** + * This method is used to store Incoming sms messages with the status EMtMessageStored + * It is accessed by CSimSmsMessaging::AttemptSmsRxCompleteL. + * Note: this will not call ReqComplete as no client request has been posted on this class + * Note: the smsStack will delete the message from the store after ReceiveMessage has completed + **/ + { + + TInt& index=aSms->iIndex; + TInt ret=KErrNoMemory; + TStoreEvent event=EStoreEventNoEvent; + for(TInt i=1;i<=iSmsMaxNumSlots;i++) + { + if(iGsmSmsStoreEntries[i].iMsgData.Length()==0) + { + index=i; + event=EStoreEventAdded; + ret = KErrNone; + break; + } + + } + + aSms->iIndex=index;//set here to be used by CSimSmsMessaging + + if (ret==KErrNone) + { + iGsmSmsStoreEntries[index].iIndex=index; + iGsmSmsStoreEntries[index].iMsgData.Copy(aSms->iMsgData); + iGsmSmsStoreEntries[index].iMsgStatus=aSms->iMsgStatus; + iGsmSmsStoreEntries[index].iServiceCentre=aSms->iServiceCentre; + + iPendingEvent=event; + iPendingIndex=index; + iIncomingTimer->Start(iSmsIndividualPause,this, 1);//delay the notification + } + + return ret; + } + + +TInt CSimSmsStore::Delete(TTsyReqHandle aReqHandle,TDes8* aPckg) +/** + * Delete a single SMS 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 (!(iSmsStoreCaps & RMobilePhoneStore::KCapsIndividualEntry && iSmsStoreCaps & RMobilePhoneStore::KCapsWriteAccess)) + { + ReqCompleted(aReqHandle, KErrAccessDenied); + return KErrNone; + } + + TPckg* intPckg=(TPckg*)aPckg; + TInt& index=(*intPckg)(); + + if((index<1)||(index>iSmsMaxNumSlots)) + { + ReqCompleted(aReqHandle,KErrArgument); + return KErrNone; + } + + iGsmSmsStoreEntries[index].iMsgData.Zero(); + iGsmSmsStoreEntries[index].iMsgStatus=RMobileSmsStore::EStoredMessageUnknownStatus; + iGsmSmsStoreEntries[index].iServiceCentre.iTelNumber=KNullTelephoneNumber; + + DelayCompletion(iSmsIndividualPause,aReqHandle,EStoreEventDeleted,index); + return KErrNone; + } + +TInt CSimSmsStore::ReadAllPhase1(TTsyReqHandle aReqHandle,TDes8* aPckg1,TDes8* aPckg2) +/** + * First phase of a batch SMS Store read. The completion of this request is delayed in + * order to simulate a real TSY that would have to get the information from a SIM card. + * If the GetSmspListPhase1L should leave this method takes care of that and + * makes a premature ReqCompleted to the client. + * + * @param aReqHandle The TSY request handle associated with this request. + * @param aPckg1 The first parameter package associated with this request. + * It contains the client ID information required to uniquely identify this request. + * It also contains the batch read information (first slot, number of slots). + * @param aPckg2 The parameter package associated with this request. + * The size of the information to be passed back to the client is returned in this package. + * @return Standard return value. + */ { + if (!(iSmsStoreCaps & static_cast(RMobilePhoneStore::KCapsWholeStore) && iSmsStoreCaps & RMobilePhoneStore::KCapsReadAccess)) + { + ReqCompleted(aReqHandle, KErrAccessDenied); + return KErrNone; + } + + + TPckg* clientIdPckg=(TPckg*) aPckg1; + CRetrieveMobilePhoneSmsList::TBatchRequestData& clientId=(*clientIdPckg)(); + TPckg* sizePckg=(TPckg*)aPckg2; + TInt& size=(*sizePckg)(); + + TRAPD(leaveCode,ReadAllPhase1L(aReqHandle,clientId,size)); + + return leaveCode; + } + + + + +void CSimSmsStore::ReadAllPhase1L(TTsyReqHandle aReqHandle,CRetrieveMobilePhoneSmsList::TBatchRequestData& aClientId, + TInt& aBufSize) +/** + * Implementation of ReadAllPhase1. + * + */ + + { + TInt cnt=0; + CMobilePhoneListBase* listBase = NULL; + + if ((CSimTsyMode::GetMode() != CSimTsyMode::ECdmaV1) && + (aClientId.iEntryType == RMobileSmsStore::KETelMobileGsmSmsEntryV1)) + { + listBase = CMobilePhoneGsmSmsList::NewL(); + } + else + { + // Nothing to read. + ReqCompleted(aReqHandle, KErrNone); + return; + } + + CleanupStack::PushL(listBase); + + if(!aClientId.iBatchRequest) + { + aClientId.iStartIndex=1; + aClientId.iBatchSize=iSmsMaxNumSlots; + } + + for(TInt i = aClientId.iStartIndex; cnt < aClientId.iBatchSize; i++) + { + if (i > iSmsMaxNumSlots) + break; + + if (aClientId.iEntryType == RMobileSmsStore::KETelMobileGsmSmsEntryV1) + { + if (iGsmSmsStoreEntries[i].iMsgData.Length() != 0) + { + ((CMobilePhoneGsmSmsList*)listBase)->AddEntryL(iGsmSmsStoreEntries[i]); + cnt++; + } + } + + } + + // Store the streamed list and the client ID + CListReadAllAttempt* read=CListReadAllAttempt::NewL(aClientId.iClient, aReqHandle); + CleanupStack::PushL(read); + + read->iListBuf = listBase->StoreLC(); + CleanupStack::Pop(); // pop the CBufFlat allocated by StoreLC + + iSmsReadAll->AppendL(read); + CleanupStack::Pop(); // pop the CListReadAllAttempt + + // return the CBufFlat’s size to client + aBufSize=(read->iListBuf)->Size(); + + CleanupStack::PopAndDestroy(); // pop&destroy list + // Complete first phase of list retrieval + + DelayCompletion(iSmsBatchPause,aReqHandle); +// return KErrNone; + } + +TInt CSimSmsStore::ReadAllPhase2(TTsyReqHandle aReqHandle,TDes8* aPckg1,TDes8* aBuffer) +/** + * Second phase of a batch SMS Store read. The completion of this request is not delayed + * as it is assumed that the TSY has already cached the required information (during the + * first phase of the read). + * + * @param aReqHandle The TSY request handle associated with this request. + * @param aPckg1 The first parameter package associated with this request. + * It contains the client ID information required to uniquely identify this request. + * @param aBuffer The parameter package associated with this request. + * It contains the read buffer in which the required information is returned. + * @return Standard return value. + */ + { + TPckg* clientIdPckg=(TPckg*) aPckg1; + RMobilePhone::TClientId& clientId=(*clientIdPckg)(); + + for (TInt i=0; iCount(); ++i) + { + CListReadAllAttempt* read = iSmsReadAll->At(i); + if ((read->iClient.iSessionHandle==clientId.iSessionHandle) && + (read->iClient.iSubSessionHandle==clientId.iSubSessionHandle)) + { + TPtr8 bufPtr((read->iListBuf)->Ptr(0)); + // Copy the streamed list to the client + aBuffer->Copy(bufPtr); + delete read; + iSmsReadAll->Delete(i); + ReqCompleted(aReqHandle,KErrNone); + return KErrNone; + } + } + +// Don't delay completion of this request, as we assume the TSY will have the results in +// memory from the first request. + ReqCompleted(aReqHandle,KErrNotFound); + return KErrNone; + } + +TInt CSimSmsStore::DeleteAll(TTsyReqHandle aReqHandle) +/** + * Delete all entries in the SIM 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 SMS Store notification. + * + * @param aReqHandle The TSY request handle associated with this request. + * @return Standard return value. + */ + { + if (!(iSmsStoreCaps & static_cast(RMobilePhoneStore::KCapsWholeStore) && iSmsStoreCaps & RMobilePhoneStore::KCapsWriteAccess)) + { + ReqCompleted(aReqHandle, KErrAccessDenied); + return KErrNone; + } + + for(TInt i=1;i<=iSmsMaxNumSlots;i++) + { + + iGsmSmsStoreEntries[i].iIndex=i; + iGsmSmsStoreEntries[i].iMsgStatus=RMobileSmsStore::EStoredMessageUnknownStatus; + iGsmSmsStoreEntries[i].iMsgData.Zero(); + iGsmSmsStoreEntries[i].iServiceCentre.iTelNumber=KNullTelephoneNumber; + + } + + DelayCompletion(iSmsBatchPause,aReqHandle,EStoreEventDeleted,-1); + return KErrNone; + } + +TInt CSimSmsStore::NotifyStoreEvent(TTsyReqHandle aReqHandle,TDes8* aPckg1,TDes8* aPckg2) +/** + * Register a client's interest in SMS 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. + */ + { + if (!(iSmsStoreCaps & RMobilePhoneStore::KCapsNotifyEvent)) + { + ReqCompleted(aReqHandle, KErrNotSupported); + return KErrNone; + } + + __ASSERT_ALWAYS(iEvOutstandingReq==EFalse,SimPanic(ENotificationAlreadyPending)); + + TPckg* eventPckg=(TPckg*)aPckg1; + TUint32& event=(*eventPckg)(); + TPckg* indexPckg=(TPckg*)aPckg2; + TInt& index=(*indexPckg)(); + + iEvOutstandingReq=ETrue; + iEvReqHandle=aReqHandle; + iEvEvent=&event; + iEvIndex=&index; + return KErrNone; + } + +void CSimSmsStore::NotifyStoreEventCancel() +/** + * Cancel an outstanding notify store request. + */ + { + if(iEvOutstandingReq) + { + iEvOutstandingReq=EFalse; + ReqCompleted(iEvReqHandle,KErrCancel); + } + } + +//coverity[bad_override] +TPtrC8 CSimSmsStore::Name() +/** + * Accessor function fot the SMS Store name. + * + * @return TPtrC8 The name of this SMS Store. + */ + { + return iSmsStoreName; + } + +TInt CSimSmsStore::UsedEntries() +/** + * Count the number of used entries in the SMS Store. + * @return TInt The number of used entries in the store. + */ + { + TInt cnt=0; + for(TInt i=1;i<=iSmsMaxNumSlots;i++) + { + if(iGsmSmsStoreEntries[i].iMsgData.Length()!=0) + cnt++; + } + return cnt; + } + +TInt CSimSmsStore::MaxSlots() +/** + * Retrieve the maximum number of slots in this SMS Store. + * @return TInt The maximum number of slots in this SMS Store. + */ + { + return iSmsMaxNumSlots; + } + +void CSimSmsStore::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); + } + +TUint CSimSmsStore::StoreCaps() + { + return iSmsStoreCaps; + } + +void CSimSmsStore::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; + iTimer->Start(aDelayDuration,this); + } + + +void CSimSmsStore::ReadAllCancel() +/* + * Cancel an outstanding read/write smsp. + */ + { + iTimer->Cancel(); + ReqCompleted(iPendingReqCompletion,KErrCancel); + } + +void CSimSmsStore::DeleteAllCancel() +/* + * Cancel an outstanding read/write smsp. + */ + { + iTimer->Cancel(); + ReqCompleted(iPendingReqCompletion,KErrNone);//The timer is cancelled but data has already been deleted + } + +void CSimSmsStore::TimerCallBack(TInt aId) +/** + * Process a timer call back event. The timer is used to kick requests which have had their + * completions delayed. + */ + { + StoreEvent(iPendingEvent,iPendingIndex); + if (aId!=1)//aId is 1 if reuest is StoreIncomingMessage(coming from CSimSmsMessaging) + ReqCompleted(iPendingReqCompletion,KErrNone); + } + +void CSimSmsStore::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; + } + + if(UsedEntries()==0) + event|=RMobilePhoneStore::KStoreEmpty; + + if(UsedEntries()==iSmsMaxNumSlots) + event|=RMobilePhoneStore::KStoreFull; + else + event|=RMobilePhoneStore::KStoreHasSpace; + + *iEvEvent=event; + *iEvIndex=aIndex; + iEvOutstandingReq=EFalse; + ReqCompleted(iEvReqHandle,KErrNone); + } + } + +const CTestConfigSection* CSimSmsStore::CfgFileSection() +/** +* Returns a pointer to the config file section +* +* @return CTestConfigSection a pointer to the configuration file data section +*/ + { + LOGSMS1(">>CSimSmsStore::CfgFileSection"); + return iSmsMessaging->CfgFileSection(); + } +