telephonyserverplugins/simtsy/src/csimsmsmess.cpp
changeset 0 3553901f7fa8
child 14 7ef16719d8cb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyserverplugins/simtsy/src/csimsmsmess.cpp	Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,2478 @@
+// 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:
+//
+
+/**
+ @file
+*/
+
+#include "csimsmsmess.h"
+#include <testconfigfileparser.h>
+#include "Simlog.h"
+#include <etelmm.h>
+#include "CSimTsyMode.h"
+
+//macro
+#define UNPACK_PCKG(target,source,datatype)  datatype& target=  (*(TPckg<datatype>*)(source))()
+
+const TInt KSmsSettingGranularity=5;	// < Granularity of SMS parameter list arrays.
+const TInt KSmsStoreGranularity=2;	// < Granularity of SMS store list array.
+const TInt KNoMessageReferenceInCofigurationFile=0;//the reference number returned to the client is 0 if
+													//no value is found in the configuration file
+			
+//
+// CSimSmsMessaging
+//
+
+void CSimSmsMessaging::CloseSmsObj(TAny* aObj)
+/**
+ *	A utility function for cleaning up the stack.
+ */
+	{
+	((CObject*)aObj)->Close();
+	}
+
+CSimSmsMessaging* CSimSmsMessaging::NewL(CSimPhone* aPhone)
+/**
+ *	Standard two phase constructor.
+ */
+	{
+	CSimSmsMessaging* smsMess=new(ELeave) CSimSmsMessaging(aPhone);
+	TCleanupItem newObjClose(CloseSmsObj,smsMess);
+	CleanupStack::PushL(newObjClose);
+	smsMess->ConstructL();
+	CleanupStack::Pop();
+	return smsMess;
+	}
+
+CSimSmsMessaging::CSimSmsMessaging(CSimPhone* aPhone)
+		: iPhone(aPhone), iSmspBusy(EFalse)
+	{}
+
+void CSimSmsMessaging::ConstructL()
+/**
+ * Retrieve the SMS-related tags from the configuration file.
+ *
+ * 
+ * If there are no constraints any SMS specified in the configuration file and the "incoming SMS event" timer will
+ * be started.
+ */
+	{
+	LOGSMS1("Starting to Load and Parse Sms Messaging Config ");
+	iRxTimer=CSimTimer::NewL(iPhone);
+	iTxTimer=CSimTimer::NewL(iPhone);
+	iSmspTimer=CSimTimer::NewL(iPhone);
+		
+	iSmsRxParameterListGsm=new(ELeave) CArrayFixFlat<TSmsRxParametersGsm>(KSmsSettingGranularity);	
+		
+		
+	FindAndCreateRxAttributesL();
+	
+	iSmsTxParametersListGsm=new(ELeave) CArrayFixFlat<TSmsTxParametersGsm>(KSmsSettingGranularity);		
+			
+	FindAndCreateTxAttributesL();
+	iSmsStores=new(ELeave) CArrayFixFlat<CSimSmsStore*>(KSmsStoreGranularity);
+	FindAndCreateSmsStoresL(iPhone);
+	FindAndCreateConstraints();
+	iSmspReadAll=new(ELeave) CArrayPtrFlat<CListReadAllAttempt>(KSmsStoreGranularity);
+	FindAndCreateSmsParamsL();
+
+	// NOTE - no need to start iRxTimer; this will be started once a EMobileSmsMessagingReceiveMessage
+	// request is received and/or Send Sms contrainst satisfied (see CompleteTxPendingReq)
+	
+	LOGSMS1("Finished parsing SMS Messaging config parameters");
+	}
+
+
+CSimSmsMessaging::~CSimSmsMessaging()
+/**
+ *	Standard destructor.  Any objects created by the ::ConstructL() function should be destroyed here.
+ */
+	{
+	if(iSmsRxParameterListGsm)
+		{
+		iSmsRxParameterListGsm->Delete(0,iSmsRxParameterListGsm->Count());
+		delete iSmsRxParameterListGsm;
+		}
+		
+	if(iSmsTxParametersListGsm)
+		{
+		iSmsTxParametersListGsm->Delete(0,iSmsTxParametersListGsm->Count());
+		delete iSmsTxParametersListGsm;
+		}
+			
+	delete iSmspEntries;
+
+	if (iSmsStores)
+		{
+		TInt storeCount=iSmsStores->Count();	
+		for(TInt i=0;i<storeCount;i++)
+			{
+			iSmsStores->At(i)->Close();
+			}
+		delete iSmsStores;
+		}
+
+	if (iSmspReadAll)
+		{
+		iSmspReadAll->ResetAndDestroy();
+		delete iSmspReadAll;
+		}
+	
+	iConstraints.Close();
+	if(iRxTimer)
+		delete iRxTimer;
+	if(iTxTimer)
+		delete iTxTimer;
+	if(iSmspTimer)
+		delete iSmspTimer;
+	}
+
+void CSimSmsMessaging::FindAndCreateRxAttributesL()
+/**
+ * Extract values from the tags
+ * SmsRx, SmsRxPeriod, SmsAckNackPause, SmsResumePause, SmsDeliveryReport
+ *
+ */	{
+	TInt ret=KErrNone;
+	TInt count=CfgFileSection()->ItemCount(KSmsRx);
+	const CTestConfigItem* item=NULL;
+	TInt i;
+	TSmsRxParametersGsm smsRxParameterGsm;
+	
+	LOGSMS2("CSimSmsMessaging::FindAndCreateRxAttributesL IN [count=%d]", count);
+
+	// Need to do this *before* entering the loop (so that we know 
+	// whether or not to read a delivery report pdu off the config file).
+	iSmsControlCaps=RMobileSmsMessaging::TMobileSmsControlCaps(CfgFileSection()->ItemValue(KSmsControlCaps,KDefaultSmsControlCaps));
+
+	for(i=0;i<count;i++)
+		{
+		item=CfgFileSection()->Item(KSmsRx,i);
+		if(!item)
+			break;
+
+		TPtrC8 smsPdu,sca;
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,smsPdu);
+		if(ret!=KErrNone)
+			{
+			LOGPARSERR("smsPdu",ret,0,&KSmsRx);
+			continue;
+			}
+		else
+			{
+			smsRxParameterGsm.iPdu.Zero();
+			ConvertAsciiSms(smsPdu,smsRxParameterGsm.iPdu);
+			}
+		
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,sca);
+		if(ret!=KErrNone)
+			{
+			LOGPARSERR("sca",ret,1,&KSmsRx);
+			continue;
+			}
+		else
+			{
+			smsRxParameterGsm.iSca=sca;
+			}
+			
+		//get delivery report pdu 
+		smsRxParameterGsm.iDeliveryReport.Zero(); 	
+		if (!(iSmsControlCaps & RMobileSmsMessaging::KCapsReceiveUnstoredClientAck))
+			{
+			TPtrC8 deliveryReportPdu;
+			ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,deliveryReportPdu);
+			if( (ret!=KErrNone) && (ret!=KErrGeneral) )
+				{
+				LOGPARSERR("deliveryReportPdu",ret,2,&KSmsRx);
+				}
+			else
+				{
+				if (CSimTsyMode::GetMode() != CSimTsyMode::ECdmaV1)			
+					{
+  					ConvertAsciiSms(deliveryReportPdu,smsRxParameterGsm.iDeliveryReport); 
+  					}
+
+				}
+			}
+
+		// add to list of params
+		iSmsRxParameterListGsm->AppendL(smsRxParameterGsm);	
+	
+		}// for
+	
+	iSmsRxPeriod=CfgFileSection()->ItemValue(KSmsRxPeriod,KDefaultSmsRxPeriod);
+	iAckNackCompletePause=CfgFileSection()->ItemValue(KSmsAckNackPause,KDefaultSmsAckNackPause);
+	iResumeCompletePause=CfgFileSection()->ItemValue(KSmsResumePause,KDefaultSmsResumePause);
+
+	if (iSmsControlCaps & RMobileSmsMessaging::KCapsReceiveUnstoredClientAck)
+		iSmsReceiveMode=RMobileSmsMessaging::EReceiveUnstoredClientAck;
+	else iSmsReceiveMode=RMobileSmsMessaging::EReceiveModeUnspecified;
+	LOGSMS5("iSmsRxPeriod =%d, iAckNackCompletePause=%d, iResumeCompletePause=%d, iSmsControlCaps=%d",iSmsRxPeriod, iAckNackCompletePause, iResumeCompletePause, iSmsControlCaps); 
+	LOGSMS4("iSmsModeCaps =%d, iSmsRxStartDelay = %d, iSmsReceiveMode = %d",iSmsModeCaps , iSmsRxStartDelay, iSmsReceiveMode);	
+	LOGSMS2("CSimSmsMessaging::FindAndCreateRxAttributesL OUT [count=%d]", iSmsRxParameterListGsm->Count());	
+	}
+
+void CSimSmsMessaging::FindAndCreateTxAttributesL()
+/**
+ * Extract values from the tags
+ * SmsTx, SmsTxPause
+ *
+ */
+	{
+	TInt ret=KErrNone;
+	TInt count=CfgFileSection()->ItemCount(KSmsTx);
+		
+	TSmsTxParametersGsm   smsTxParametersGsm;
+	
+	const CTestConfigItem* item=NULL;
+	for(TInt i=0;i<count;i++)
+		{
+		item=CfgFileSection()->Item(KSmsTx,i);//Tx
+		if(!item)
+			break;
+
+		//get pdu
+		TPtrC8 smsTx;
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,smsTx);
+		if(ret!=KErrNone)
+			{
+			LOGPARSERR("smsTx",ret,0,&KSmsTx);
+			continue;
+			}
+		else
+			{			
+			smsTxParametersGsm.iPdu.Zero();
+			ConvertAsciiSms(smsTx,smsTxParametersGsm.iPdu);
+			}
+
+		//get Sca
+		TPtrC8 sca;
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,sca);
+		if (ret!=KErrNone)
+			{
+			LOGPARSERR("sca",ret,1,&KSmsTx);
+			continue;
+			}
+		else
+			{			
+			smsTxParametersGsm.iSca.Copy(sca);				
+			}
+			
+		//get reference
+		TInt reference;
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,reference);
+		if(ret!=KErrNone)
+			{
+			LOGPARSERR("reference",ret,2,&KSmsTx);
+			smsTxParametersGsm.iRef=KNoMessageReferenceInCofigurationFile;	
+			}
+		else
+			{	
+			smsTxParametersGsm.iRef=reference;				
+			}
+	
+		//get submit report pdu
+		TPtrC8 submitReportPdu;
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,submitReportPdu);
+		if(ret!=KErrNone)
+			{
+			LOGPARSERR("submitReportPdu",ret,3,&KSmsTx);
+			continue;
+			}
+		else
+			{			
+			smsTxParametersGsm.iSubmitReport.Zero(); 	
+			ConvertAsciiSms(submitReportPdu,smsTxParametersGsm.iSubmitReport); 
+			}
+		
+		//get expected error code
+		TInt errorCode;
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,4,errorCode);
+		if(ret!=KErrNone)
+			{
+			LOGPARSERR("errorCode",ret,4,&KSmsTx);
+			continue;
+			}
+		else
+			{		
+			smsTxParametersGsm.iExpectedError=errorCode;					
+			}		
+		
+		iSmsTxParametersListGsm->AppendL(smsTxParametersGsm);			
+
+		} //end for SmsTx Tag
+	
+	iSmsTxPause=CfgFileSection()->ItemValue(KSmsTxPause,KDefaultSmsTxPause);
+	}
+
+void CSimSmsMessaging::FindAndCreateConstraints()
+/**
+ * Extract values from the tags
+ * SmsStartRxDelay
+ *
+ */
+	{
+	TInt ret=KErrNone;
+	TInt count=CfgFileSection()->ItemCount(KSmsStartRxDelay);
+	const CTestConfigItem* item=NULL;
+	TConstraintEntry constraint;
+	for(TInt i=0;i<count;i++)//Rx delay
+		{
+		item=CfgFileSection()->Item(KSmsStartRxDelay,i);
+		if(!item)
+			break;
+		
+		TInt ipc,noBefore,noAfter;
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,ipc);//only :SendMessage() is supported
+		if(ret!=KErrNone || ipc!=4207)
+			{
+			LOGPARSERR("ipc",ret,0,&KSmsStartRxDelay);
+			continue;
+			}
+
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,noBefore);
+		if(ret==KErrNone)
+			constraint.iIpcCnt=noBefore;
+		else
+			{
+			LOGPARSERR("noBefore",ret,1,&KSmsStartRxDelay);
+			continue;
+			}
+
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,noAfter);
+		if(ret==KErrNone)
+			constraint.iRxCnt=noAfter;
+		else
+			{
+			LOGPARSERR("noAfter",ret,2,&KSmsStartRxDelay);
+			continue;
+			}
+		
+		__ASSERT_ALWAYS(iConstraints.Append(constraint) == KErrNone,SimPanic(EGeneral));
+		}
+	}
+
+void CSimSmsMessaging::FindAndCreateSmsStoresL(CSimPhone* aPhone)
+/**
+ *	Creates sms stores as defined in the comfiguation files
+ *	Extract values from the tags
+ *	SmsStore, SmsStoreEntry, SmsStoreIndividualReqPause, SmsStoreBatchReqPause
+ */
+	{
+	TInt count=CfgFileSection()->ItemCount(KSmsStore);
+	const CTestConfigItem* item=NULL;
+	TInt ret=KErrNone;
+
+	for(TInt i=0;i<count;i++)
+		{
+		item=CfgFileSection()->Item(KSmsStore,i);
+		if(!item)
+			break;
+
+		TPtrC8 storeName;
+		TInt maxNumSlots;
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,storeName);
+		if(ret!=KErrNone)
+			{
+			LOGPARSERR("storeName",ret,0,&KSmsStore);
+			continue;
+			}
+
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,maxNumSlots);
+		if(ret!=KErrNone)
+			{
+			LOGPARSERR("maxNumSlots",ret,1,&KSmsStore);
+			continue;
+			}
+
+		CSimSmsStore* smsStore=CSimSmsStore::NewL(this,storeName,maxNumSlots,aPhone);
+		TCleanupItem newObjClose(CloseSmsObj,smsStore);
+		CleanupStack::PushL(newObjClose);
+		iSmsStores->AppendL(smsStore);
+		CleanupStack::Pop();
+		}
+
+	for(TInt j=0;j<iSmsStores->Count();j++)
+		{
+		iSmsStores->At(j)->PopulateStoreFromConfigFile();
+		}
+	}
+
+void CSimSmsMessaging::FindAndCreateSmsParamsL()
+/**
+ *Populates the sms parameter List as defined in the configuration file
+ *Extract values from the tags
+ *SmsParamEntry, SmsParamEntry, SmsParamBatchReqPause, SmsParamMaxNumSlots
+ */
+	{
+	iSmspEntries= CMobilePhoneSmspList::NewL();
+
+	const TInt maxSlots = CfgFileSection()->ItemValue(KSmspMaxNumSlots ,KDefaultSmspMaxNumSlots);
+	iSmspEntries->SetMaxNumberEntries(maxSlots);
+
+	iSmspBatchPause = CfgFileSection()->ItemValue(KSmspBatchReqPause,KDefaultSmspBatchReqPause);
+
+	const TInt numberOfSmspEntries = Min(CfgFileSection()->ItemCount(KSmsParamEntry), maxSlots);
+	const CTestConfigItem* item=NULL;
+	TInt ret=KErrNone;
+	
+	for(TInt i=0;i < numberOfSmspEntries;i++)
+		{
+		item=CfgFileSection()->Item(KSmsParamEntry,i);
+
+		if(!item)
+			break;
+
+		RMobileSmsMessaging::TMobileSmspEntryV1 entry = RMobileSmsMessaging::TMobileSmspEntryV1();
+
+		TInt index, pid, dcs, validityPeriod;
+		TPtrC8 destAddress, sca, smspName;
+
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,index);
+		if((ret==KErrNone)&&(index < maxSlots))
+			entry.iIndex=index;
+		else
+			{
+			LOGPARSERR("index",ret,0,&KSmsParamEntry);
+			continue;
+			}
+
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,smspName);
+		if(ret==KErrNone)
+			entry.iText.Copy(smspName);
+		else
+			{
+			LOGPARSERR("smspName",ret,1,&KSmsParamEntry);
+			continue;
+			}
+
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,pid);
+		if(ret==KErrNone)
+			{
+			entry.iProtocolId=TUint8(pid);
+			entry.iValidParams |= RMobileSmsMessaging::KProtocolIdIncluded;
+			}
+		else
+			{
+			LOGPARSERR("pid",ret,2,&KSmsParamEntry);
+			continue;
+			}
+
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,dcs);
+		if(ret==KErrNone)
+			{
+			entry.iDcs=TUint8(dcs);
+			entry.iValidParams |= RMobileSmsMessaging::KDcsIncluded;
+			}
+		else
+			{
+			LOGPARSERR("dcs",ret,3,&KSmsParamEntry);
+			continue;
+			}
+
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,4,validityPeriod);
+		if(ret==KErrNone)
+			{
+			entry.iValidityPeriod=TUint8(validityPeriod);
+			entry.iValidParams |= RMobileSmsMessaging::KValidityPeriodIncluded;
+			}
+		else
+			{
+			LOGPARSERR("validityPeriod",ret,4,&KSmsParamEntry);
+			continue;
+			}
+
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,5,destAddress);
+		if(ret==KErrNone)
+			{
+			RecordDestination(destAddress, entry);
+			}
+		else
+			{
+			LOGPARSERR("destAddress",ret,5,&KSmsParamEntry);
+			continue;
+			}
+
+		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,6,sca);
+		if(ret==KErrNone)
+			{
+			RecordSca(sca, entry);
+			}
+		else
+			{
+			LOGPARSERR("sca",ret,6,&KSmsParamEntry);
+			continue;
+			}
+
+		iSmspEntries->AddEntryL(entry);
+		}
+	}
+
+void CSimSmsMessaging::RecordSca(const TDesC8& aAsciiAddr, RMobileSmsMessaging::TMobileSmspEntryV1& aEntry)
+/**
+ * Used to set the sca number in the smsp
+ *
+ * @param aAsciiSca Ascii representation of a telephone number such as the one found in the configuration file
+ * @param aEntry reference to the actual smspentry in which the sca is going to be recorded
+ */
+	{
+	if(aAsciiAddr.Length()>0)//only support for international numbers
+		{
+		aEntry.iServiceCentre.iNumberPlan=RMobilePhone::EIsdnNumberPlan;
+		aEntry.iServiceCentre.iTypeOfNumber=RMobilePhone::EInternationalNumber;
+		aEntry.iServiceCentre.iTelNumber.Copy(aAsciiAddr);
+		aEntry.iValidParams |= RMobileSmsMessaging::KSCAIncluded;
+		}
+	}
+
+void CSimSmsMessaging::RecordDestination(const TDesC8& aAsciiAddr, RMobileSmsMessaging::TMobileSmspEntryV1& aEntry)
+/**
+ * Used to set the destination number in the smsp
+ *
+ * @param aAsciiAddr Ascii representation of a telephone number such as the one found in the configuration file
+ * @param aEntry reference to the actual smspentry in which the destination is going to be recorded
+ */
+	{
+	if(aAsciiAddr.Length()>0)//only support for international numbers
+		{
+		aEntry.iDestination.iNumberPlan=RMobilePhone::EIsdnNumberPlan;
+		aEntry.iDestination.iTypeOfNumber=RMobilePhone::EInternationalNumber;
+		aEntry.iDestination.iTelNumber.Copy(aAsciiAddr);
+		aEntry.iValidParams |= RMobileSmsMessaging::KDestinationIncluded;
+		}	
+	}
+
+#ifdef _DEBUG	// to stop the UREL build warnings
+void CSimSmsMessaging::LogRequest(const TBool aEntering, TInt aIpc, TInt aError)
+#else
+void CSimSmsMessaging::LogRequest(const TBool aEntering, TInt aIpc, TInt /*aError*/)
+#endif
+/**
+ * This method logs client requests to the t_reg.txt
+ * @param aDirection Tells if the request is coming 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 EEtelServerLoadPhoneModule:
+			ipcBuf = _L8("ServerLoadPhoneModule");
+			break;
+
+		case EEtelPhoneGetStatus:
+			ipcBuf = _L8("PhoneGetStatus");
+			break;
+
+		case EEtelPhoneNotifyModemDetected:
+			ipcBuf = _L8("PhoneNotifyModemDetected");
+			break;
+		case EEtelPhoneInitialise:
+			ipcBuf = _L8("PhoneInitialise");
+			break;
+		case EMobileSmsMessagingGetCaps:
+			ipcBuf = _L8("GetCaps");
+			break;
+		case EMobileSmsMessagingGetReceiveMode:
+			ipcBuf = _L8("GetReceiveMode");
+			break;
+		case EMobileSmsMessagingGetMoSmsBearer:
+			ipcBuf = _L8("GetMoSmsBearer");
+			break;
+		case EMobileSmsMessagingEnumerateMessageStores:
+			ipcBuf = _L8("EnumerateMessageStores");
+			break;
+		case EMobileSmsMessagingGetMessageStoreInfo:
+			ipcBuf = _L8("GetMessageStoreInfo");
+			break;
+		case EMobileSmsMessagingGetSmspListPhase2:
+			ipcBuf = _L8("GetSmspListPhase2");
+			break;
+		case EMobileSmsMessagingSetReceiveMode:
+			ipcBuf = _L8("SetReceiveMode");
+			break;
+		case EMobileSmsMessagingSetMoSmsBearer:
+			ipcBuf = _L8("SetMoSmsBearer");
+			break;
+		case EMobileSmsMessagingAckSmsStored:
+			ipcBuf = _L8("AckSmsStored");
+			break;
+		case EMobileSmsMessagingNackSmsStored:
+			ipcBuf = _L8("NackSmsStored");
+			break;
+		case EMobileSmsMessagingResumeSmsReception:
+			ipcBuf = _L8("ResumeSmsReception");
+			break;
+		case EMobileSmsMessagingSendMessage:
+			ipcBuf = _L8("SendMessage");
+			break;
+		case EMobileSmsMessagingGetSmspListPhase1:
+			ipcBuf = _L8("GetSmspListPhase1");
+			break;
+		case EMobileSmsMessagingStoreSmspList:
+			ipcBuf = _L8("StoreSmspList");
+			break;
+		case EMobileSmsMessagingReceiveMessage:
+			ipcBuf = _L8("ReceiveMessage");
+			break;
+		case EMobileSmsMessagingNotifyReceiveModeChange:
+			ipcBuf = _L8("NotifyReceiveModeChange");
+			break;
+		case EMobileSmsMessagingNotifyMoSmsBearerChange:
+			ipcBuf = _L8("NotifyMoSmsBearerChange");
+			break;
+		case EMobileSmsMessagingNotifySmspListChange:
+			ipcBuf = _L8("NotifySmspListChange");
+			break;
+		case EMobileSmsMessagingSetReceiveModeCancel:
+			ipcBuf = _L8("SetReceiveModeCancel");
+			break;
+		case EMobileSmsMessagingNotifyReceiveModeChangeCancel:
+			ipcBuf = _L8("NotifyReceiveModeChangeCancel");
+			break;
+		case EMobileSmsMessagingSetMoSmsBearerCancel:
+			ipcBuf = _L8("SetMoSmsBearerCancel");
+			break;
+		case EMobileSmsMessagingNotifyMoSmsBearerChangeCancel:
+			ipcBuf = _L8("NotifyMoSmsBearerChangeCancel");
+			break;
+		case EMobileSmsMessagingAckSmsStoredCancel:
+			ipcBuf = _L8("AckSmsStoredCancel");
+			break;
+		case EMobileSmsMessagingNackSmsStoredCancel:
+			ipcBuf = _L8("NackSmsStoredCancel");
+			break;
+		case EMobileSmsMessagingResumeSmsReceptionCancel:
+			ipcBuf = _L8("ResumeSmsReceptionCancel");
+			break;
+		case EMobileSmsMessagingSendMessageCancel:
+			ipcBuf = _L8("SendMessageCancel");
+			break;
+		case EMobileSmsMessagingReceiveMessageCancel:
+			ipcBuf = _L8("ReceiveMessageCancel");
+			break;
+		case EMobileSmsMessagingGetMessageStoreInfoCancel:
+			ipcBuf = _L8("GetMessageStoreInfoCancel");
+			break;
+		case EMobileSmsMessagingGetSmspListCancel:
+			ipcBuf = _L8("GetSmspListCancel");
+			break;
+		case EMobileSmsMessagingStoreSmspListCancel:
+			ipcBuf = _L8("StoreSmspListCancel");
+			break;
+		case EMobileSmsMessagingNotifySmspListChangeCancel:
+			ipcBuf = _L8("NotifySmspListChangeCancel");
+			break;
+		default:
+			ipcBuf = _L8("OTHER");
+			break;
+		}
+
+	if (aEntering!=EFalse)
+		{
+		LOGSMS3(">>%d,CSimSmsMessaging::%S",aIpc, &ipcBuf );
+		}
+	else
+		{
+		LOGSMS4("<<%d, CSimSmsMessaging::%S with error %d",aIpc, &ipcBuf, aError);
+		}
+	}
+
+
+TInt CSimSmsMessaging::ExtFunc(const TTsyReqHandle aReqHandle,const TInt aIpc, const TDataPackage& aPckg)
+/**
+ * Sms Read/Send Dispatch Function.
+ *
+ * If this method returns with an KErr code apart from KErrNone then Etel will 
+ * complete and destory the clients request for us. 
+ *
+ * @param aTsyReqHandle The handle of the request which started the IPC
+ * @param aIpc The IPC being requested
+ * @param aPackage Package of parameters associated with the IPC
+ * @return Standard KErr... codes
+ */	{
+	TInt ret=KErrNone;//error is only used with LogRequest when at the end of ExtFunc
+	LogRequest(ETrue, aIpc, ret);
+
+	switch(aIpc)
+		{
+	case EMobileSmsMessagingReceiveMessage://4211
+		{
+		TRAPD(leaveCode, ret = ReceiveMessageL(aReqHandle,aPckg.Des1n(),aPckg.Des2n()));
+		if (leaveCode != KErrNone)
+			{
+			ret = leaveCode;
+			}
+		}
+		break;
+		
+	case EMobileSmsMessagingGetCaps:
+		ret = GetCaps(aReqHandle,aPckg.Des1n());
+		break;
+
+	case EMobileSmsMessagingEnumerateMessageStores:
+		ret = EnumerateMessagingStores(aReqHandle,aPckg.Des1n());
+		break;
+
+	case EMobileSmsMessagingGetMessageStoreInfo:
+		ret = GetMessageStoreInfo(aReqHandle,aPckg.Des1n(),aPckg.Des2n());
+		break;
+
+	case EMobileSmsMessagingGetReceiveMode:
+		ret = GetReceiveMode(aReqHandle,aPckg.Des1n());
+		break;
+		
+	case EMobileSmsMessagingSetReceiveMode:
+		ret = SetReceiveMode(aReqHandle,aPckg.Des1n());//4202
+		break;
+
+	case EMobileSmsMessagingAckSmsStored:
+		ret = AckSmsStored(aReqHandle,aPckg.Des1n(),aPckg.Des2n());
+		break;
+
+	case EMobileSmsMessagingNackSmsStored:
+		ret = NackSmsStored(aReqHandle,aPckg.Des1n(),aPckg.Des2n());
+		break;
+
+	case EMobileSmsMessagingResumeSmsReception:
+		ret = ResumeSmsReception(aReqHandle);
+		break;
+
+	case EMobileSmsMessagingGetSmspListPhase1:
+		ret = GetSmspListPhase1(aReqHandle,aPckg.Des1n(), aPckg.Des2n());
+		break;
+
+	case EMobileSmsMessagingGetSmspListPhase2:
+		ret = GetSmspListPhase2(aReqHandle,aPckg.Des1n(), aPckg.Des2n());
+		break;
+
+	case EMobileSmsMessagingStoreSmspList:
+		ret = StoreSmspList(aReqHandle,aPckg.Des1n());
+		break;
+
+	case EMobileSmsMessagingSendMessage://4207
+		{
+		TRAPD(leaveCode, ret = SendMessageL(aReqHandle,aPckg.Des1n(),aPckg.Des2n()));
+		if (leaveCode != KErrNone)
+			{
+			ret = leaveCode;
+			}
+		}
+		break;
+	
+	//This is used to re-read the configuration without having to restart the TSY
+	//For testing purposes
+	case EMobileSmsMessagingGetMoSmsBearer:
+		//  FALLTHRU
+
+	default:
+		ret=KErrNotSupported;
+		break;
+		}
+	LogRequest(EFalse, aIpc, ret);
+	return ret;
+	}
+
+TBool CSimSmsMessaging::ConstraintEllapsed() const
+/**
+ * Check if the current contraint has ellapsed - i.e. check that that the number of received SMS
+ * messages has reached the expected number for the current constraint.
+ * @return ETrue if a constraint has ellapsed
+ */
+	{
+	TBool ellapsed = EFalse;
+	if( iConstraints.Count()>0 )
+		{
+		//check if the number of rx mess has been reached
+		ellapsed=(iConstraintRxCnt==iConstraints[iCurrentConstraint].iRxCnt);
+		}
+	return ellapsed;
+	}
+
+TBool CSimSmsMessaging::IpcMatch()
+/**
+ * Check if the number of Sms sent matches a constraint i.e. the number of messages sent reaches the number
+ * of sms to be sent to allow incoming messages to start being simulated.
+ * @return ETrue if a match is found
+ */
+	{
+	TInt i;
+	TBool constraintEllapsed=ConstraintEllapsed();
+	
+	// NOTE - call ConstraintEllapsed() before doing loop below as iCurrentConstraint
+	// is updated in the loop and so can result in ConstraintEllapsed() giving a 
+	// different result
+	
+	for(i=0;i<iConstraints.Count();i++)
+		{
+		if(iSmsTxCnt==(iConstraints[i].iIpcCnt))
+			{
+			iCurrentConstraint=i;
+			LOGSMS2("New Constraint : %d", iCurrentConstraint);
+			if(i!=0)
+				{
+				if( !constraintEllapsed )
+					{
+					LOGSMS1("Panic The constraints are overlapping...Compare test code and config file");
+					}
+				__ASSERT_ALWAYS(constraintEllapsed!=EFalse,SimPanic(EConstraintsOverlapping));
+				}
+			return ETrue;
+			}
+		}
+	return EFalse;
+	}
+
+CTelObject* CSimSmsMessaging::OpenNewObjectByNameL(const TDesC& aName)
+/**
+ *
+ */
+	{
+	LOGSMS1(">>CSimSmsMessaging::OpenNewObjectByNameL");
+	TBuf8<KMaxName> name;
+	name.Copy(aName);		// Do simple 16 bit to 8 bit conversion
+	for(TInt i=0;i<iSmsStores->Count();i++)
+		{
+		if(name.MatchF(iSmsStores->At(i)->Name())==0)
+			{
+			// Base class open
+			(void)iSmsStores->At(i)->Open();
+			return iSmsStores->At(i);
+			}
+		}
+	User::Leave(KErrNotFound);
+	return NULL;
+	}
+
+CTelObject* CSimSmsMessaging::OpenNewObjectL(TDes&)
+/**
+ *
+ */
+	{
+	User::Leave(KErrNotSupported);
+	return NULL;
+	}
+
+CTelObject::TReqMode CSimSmsMessaging::ReqModeL(const TInt aIpc)
+/**
+ *	This function returns the Request Mode for the request with the passed IPC value.
+ *	The ETel Server provides a function for returning the standard request modes for
+ *	the Core API requests.
+ */
+	{
+	CTelObject::TReqMode ret=0;	
+
+	switch(aIpc)
+		{
+	case EMobileSmsMessagingReceiveMessage:
+		ret=KReqModeRePostImmediately;
+		break;
+
+	case EMobileSmsMessagingGetCaps:
+	case EMobileSmsMessagingSetReceiveMode:
+	case EMobileSmsMessagingGetReceiveMode:
+	case EMobileSmsMessagingAckSmsStored:
+	case EMobileSmsMessagingNackSmsStored:
+	case EMobileSmsMessagingResumeSmsReception:
+	case EMobileSmsMessagingEnumerateMessageStores:
+	case EMobileSmsMessagingGetMessageStoreInfo:
+	case EMobileSmsMessagingSendMessage:
+	case EMobileSmsMessagingGetSmspListPhase1:
+	case EMobileSmsMessagingGetSmspListPhase2:
+	case EMobileSmsMessagingStoreSmspList:
+		ret=0;
+		break;
+	case EMobileSmsMessagingGetMoSmsBearer:
+		// FALLTHRU
+	default:
+		User::Leave(KErrNotSupported);
+		break;
+		}
+
+	return ret;
+	}
+
+TInt CSimSmsMessaging::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 CSimSmsMessaging::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 CSimSmsMessaging::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 CSimSmsMessaging::CancelService(const TInt aIpc,const TTsyReqHandle /*aTsyReqHandle*/)
+/**
+ * Cancel an outstanding request.
+ */
+	{
+	switch(aIpc)
+		{
+	case EMobileSmsMessagingReceiveMessage:
+		ReceiveMessageCancel();
+		break;
+	case EMobileSmsMessagingSendMessage:
+		SendMessageCancel();
+		break;
+	case EMobileSmsMessagingGetSmspListPhase1:
+		StoreSmspListCancel();
+		break;
+	case EMobileSmsMessagingStoreSmspList:
+		GetSmspListCancel();
+		break;
+	case EMobileSmsMessagingAckSmsStored:
+	case EMobileSmsMessagingNackSmsStored:
+		AckNackCancel();
+		break;
+	case EMobileSmsMessagingResumeSmsReception:
+		ResumeSmsReceptionCancel();
+		break;
+// These are actually implemented in a synchronous manner, so there's no cancel to perform.
+	case EMobileSmsMessagingSetReceiveMode:
+	case EMobileSmsMessagingGetReceiveMode:	
+		break;
+	default:
+		break;
+		}
+	return KErrNone;
+	}
+
+void CSimSmsMessaging::Init()
+/**
+	This function can be used to perform any necessary synchronous initialisation.
+*/
+	{
+	}
+
+TBool CSimSmsMessaging::CanStartRxEvent() const
+/** Check to see if the Rx event can be started. Conditions are that there are no constraints
+ * and Rx PDUs have been defined, OR SMS messages have been sent and current constraint has 
+ * not ellapsed
+ * @return ETrue if the Rx event can be started
+ */ 
+	{
+	TBool canStart = EFalse;
+	if( (iConstraints.Count()==0 && iSmsRxParameterListGsm->Count()>0) ||
+		(iConstraints.Count()>0 && (iSmsTxCnt == iConstraints[iCurrentConstraint].iIpcCnt) && !ConstraintEllapsed()) )
+		{
+		// No Constraints listed OR current constraint has not ellapsed
+		canStart = ETrue;
+		}
+	return canStart;	
+	}
+
+TInt CSimSmsMessaging::ActionRxEventUnstoredClientAck(TSmsRxEvent aRxEvent)
+/**
+ *	This function, triggered by sms receive events, manages the stated machine of 
+ *  receiving Unstored clientacked sms messages
+ *  
+ */
+	{
+	LOGSMS3(">>CSimSmsMessaging::ActionRxEventUnstoredClientAck [iRxState=%d aRxEvent=%d]", iRxState, aRxEvent);
+	switch(iRxState)
+		{
+	case ESmsRxStateIdle:
+		{
+		if(aRxEvent==ESmsEventPostedRxReq)
+			{
+			iRxState=ESmsRxStateWaitingForSmsRx;
+			if( CanStartRxEvent() )
+				{
+				// Start the Rx timer to simulate received SMS from network
+				StartSmsMtTimer();	
+				}
+			return KErrNone;
+			}
+		return KErrGeneral;
+		}
+	case ESmsRxStateWaitingForSmsRx:
+		{
+		if(aRxEvent==ESmsEventRxTimer )
+			{
+			iRxState=ESmsRxStateWaitingForAckNack;
+			TInt ret = AttemptSmsRxComplete();	//If successful Etel will repost the request and the state machine may be re-entered
+			return ret;
+			}
+		return KErrGeneral;
+		} 
+	case ESmsRxStateWaitingForAckNack:
+		{
+		__ASSERT_ALWAYS(aRxEvent!=ESmsEventRxTimer,SimPanic(EIllegalSmsRxEvent, __LINE__));
+		if(aRxEvent==ESmsEventRxAckNack)
+			{
+			iRxState=ESmsRxStateWaitingForNetworkAckNackResponse;
+			if (!iRxTimer->IsActive() && !iRxTimer->Running())
+				{
+				LOGSMS1(">>CSimSmsMessaging::ActionRxEventUnstoredClientAck Starting Rx Timer");
+				iRxTimer->Start(iAckNackCompletePause,this, ETimerIdSmsMessRx);
+				}
+
+			return KErrNone;
+			}
+		else if(aRxEvent==ESmsEventResume)
+			{
+			return KErrGeneral;
+			}
+		} break;
+	case ESmsRxStateWaitingForNetworkAckNackResponse:
+		if(aRxEvent==ESmsEventRxTimer)
+			{
+			if(iSmsStoreFull)
+				iRxState=ESmsRxStateSuspend;
+			else if(iSmsRxReqOutstanding)
+				{
+				iRxState=ESmsRxStateWaitingForSmsRx;
+				StartSmsMtTimer();
+				}
+			else
+				{
+				iRxState=ESmsRxStateIdle;
+				StartSmsMtTimer();
+				}
+			CompletePendingReq();
+			return KErrNone;
+			}
+		if(aRxEvent==ESmsEventPostedRxReq)
+			return KErrNone;
+		return KErrGeneral;
+	case ESmsRxStateSuspend:
+		{
+		__ASSERT_ALWAYS(aRxEvent!=ESmsEventRxTimer,SimPanic(EIllegalSmsRxEvent, __LINE__));
+		if(aRxEvent==ESmsEventResume)
+			{
+			iRxState=ESmsRxStateWaitingForNetworkResumeResponse;
+			iRxTimer->Start(iResumeCompletePause,this, ETimerIdSmsMessResumeReception);
+			return KErrNone;
+			}
+		return KErrGeneral;
+		}
+	case ESmsRxStateWaitingForNetworkResumeResponse:
+		{
+		if(aRxEvent==ESmsEventPostedRxReq)
+			return KErrNone;
+		return KErrGeneral;
+		}
+	default:
+		return KErrGeneral;
+		}
+	return KErrNone;
+	}
+
+TInt CSimSmsMessaging::ActionRxEventUnstoredPhoneAck(TSmsRxEvent aRxEvent)
+/**
+ *	This function, triggered by sms receive events, manages the stated machine of 
+ *  receiving Unstored Phone acked sms messages
+ *  
+ */
+	{
+	LOGSMS3(">> ActionRxEventUnstoredPhoneAck Enter function. Event=%d, State=%d",aRxEvent,iRxState);
+	
+	TInt ret = KErrGeneral;
+	
+	switch(iRxState)
+		{
+	case ESmsRxStateIdle:
+		{
+		if(aRxEvent==ESmsEventPostedRxReq)
+			{
+			iRxState=ESmsRxStateWaitingForSmsRx;
+			if( CanStartRxEvent() )
+				{
+				// Start the Rx timer to simulate received SMS from network
+				StartSmsMtTimer();	
+				}
+			ret = KErrNone;
+			}
+		} break;
+	case ESmsRxStateWaitingForSmsRx:
+		{
+		if(aRxEvent==ESmsEventRxTimer )
+			{
+			iRxState=ESmsRxStateIdle;
+			ret = AttemptSmsRxComplete();	//If successful Etel will repost the request and the state machine may be re-entered
+			}
+		} break; 
+	default: 
+		// Do nothing - return default value of KErrGeneral
+		break;
+		}
+	return ret;
+	}
+
+TInt CSimSmsMessaging::ActionRxEventStored(TSmsRxEvent aRxEvent)
+/**
+ *	This function, triggered by sms receive events, manages the stated machine of 
+ *  receiving stored Phone acked  sms messages
+ *  
+ */
+	{
+	LOGSMS3(">> ActionRxEventStored Enter function. Event=%d, State=%d",aRxEvent,iRxState);
+	TInt ret = KErrGeneral;
+	
+	switch(iRxState)
+		{
+	case ESmsRxStateIdle:
+		{
+		if(aRxEvent==ESmsEventPostedRxReq)
+			{
+			iRxState=ESmsRxStateWaitingForSmsRx;
+			if( CanStartRxEvent() )
+				{
+				// Start the Rx timer to simulate received SMS from network
+				StartSmsMtTimer();	
+				}
+			ret = KErrNone;
+			}
+		} break;
+	case ESmsRxStateWaitingForSmsRx:
+		{
+		if(aRxEvent==ESmsEventRxTimer )
+			{
+			iRxState=ESmsRxStateIdle;
+			ret = AttemptSmsRxComplete();	//If successful Etel will repost the request and the state machine may be re-entered
+			if( ret != KErrNone )
+				{
+				//the message wasn't stored ->ignore it and re-run the network event
+				iRxState=ESmsRxStateWaitingForSmsRx;
+				StartSmsMtTimer();
+				}
+			ret = KErrNone;	
+			}
+		} break; 
+	default: 
+		// Do nothing - return default value of KErrGeneral
+		break;
+		}
+	return ret;
+	}
+
+TInt CSimSmsMessaging::ReceiveMessageL(const TTsyReqHandle aReqHandle, TDes8* aSmsPdu, TDes8* aParam2)
+/**
+ * Process a Receive Message request.  This boils down to recording the parameters for later completion.
+ * The mode of operation where first an SMS receive request is made and then later an SMS
+ * receive event is simulated is supported.  If an SMS receive event is simulated and there is
+ * no receive request outstanding, the simulated incoming SMS will be discarded.  This assumption
+ * may need to be revisited later.
+ */
+	{
+	if (iSmsRxReqOutstanding!=EFalse)//Check if another client posts the request
+		{
+		ReqCompleted(aReqHandle, KErrInUse);
+		return KErrNone;
+		}
+	iSmsRxReqHandle=aReqHandle;
+	iSmsRxPdu=aSmsPdu;
+	RMobileSmsMessaging::TMobileSmsReceiveAttributesV1Pckg* aAttribPckg=(RMobileSmsMessaging::TMobileSmsReceiveAttributesV1Pckg*)aParam2;
+	RMobileSmsMessaging::TMobileSmsReceiveAttributesV1& attrib=(*aAttribPckg)();
+
+	// Check that the data structure is supported by the simulated TSY version
+	TInt err = iPhone->CheckSimTsyVersion(attrib);
+	if(err != KErrNone)
+		{
+		iPhone->ReqCompleted(aReqHandle, err);
+		return KErrNone;
+		}
+
+	iSmsRxAttrib=&attrib;
+	iSmsRxReqOutstanding=ETrue;
+	LOGSMS3(">>ReceiveMessageL. aSmsPdu&=%x, aParam2&=%x",aSmsPdu,iSmsRxAttrib);
+	
+	//  Print received PDU to simTSY log.
+	__ASSERT_ALWAYS(iSmsReceiveMode!=RMobileSmsMessaging::EReceiveModeUnspecified,SimPanic(EMobileSmsMessagingPhoneNotSetToAReceiveMode));
+	TInt ret=0;
+	switch (iSmsReceiveMode)//swich which state machine to enter
+		{
+	case RMobileSmsMessaging::EReceiveUnstoredClientAck:
+		ret=ActionRxEventUnstoredClientAck(ESmsEventPostedRxReq);
+		break;
+	case RMobileSmsMessaging::EReceiveUnstoredPhoneAck:
+		ret=ActionRxEventUnstoredPhoneAck(ESmsEventPostedRxReq);
+		break;
+	case RMobileSmsMessaging::EReceiveStored:
+		ret=ActionRxEventStored(ESmsEventPostedRxReq);
+		break;
+	default:
+		ret=KErrNotSupported;
+		}//end switch
+
+	if(ret==KErrNone)
+		{
+		
+		}
+	else
+		ReqCompleted(aReqHandle,ret);
+	return KErrNone;
+	}
+
+void CSimSmsMessaging::ReceiveMessageCancel()
+/*
+ * Cancel an outstanding Receive Message request.
+ */
+	{
+	if(iSmsRxReqOutstanding)
+		{
+		iSmsRxReqOutstanding=EFalse;
+		iRxState=ESmsRxStateIdle;
+		ReqCompleted(iSmsRxReqHandle,KErrCancel);
+		}
+	}
+
+TInt CSimSmsMessaging::AckSmsStored(const TTsyReqHandle aReqHandle,TDes8* aMsg,TDes8* aFullFlagPckg)
+/**
+ *	In response to an incoming sms message the sms stack Acks/Nacks the message
+ *  This function implements the Ack action.
+ *  The flag aFullFlagPckg if set informs the SC that the client has no space to store this message
+ *  and hence that it should retry once instructed by the ME
+ */
+	{
+	TPckg<TBool>* fullFlagPckg=(TPckg<TBool>*)aFullFlagPckg;
+	TBool& fullFlag=(*fullFlagPckg)();
+
+	//  SMS-DELIVER-REPORT TPDU check 
+	_LIT8(emptyDesc,"");
+	if(aMsg->Compare(emptyDesc) != KErrNone)
+		{
+		RMobileSmsMessaging::TMobileSmsGsmTpdu reportPdu;
+		reportPdu.Zero();
+		if (CSimTsyMode::GetMode() != CSimTsyMode::ECdmaV1)
+  			{
+ 			reportPdu = iSmsRxParameterListGsm->At(iSmsRxCnt-1).iDeliveryReport;
+  			}
+
+					
+		if (reportPdu.Length() > 0)	// check if SMS-DELIVER-REPORT TPDU in config file is present
+			{
+			if(aMsg->Match(reportPdu)!=0)//check if the transmitted pdu and the one in config file are not identical
+				{
+				ReqCompleted(aReqHandle,KErrCorrupt);
+				return KErrNone;
+				}
+			}
+		}
+
+	iSmsStoreFull=fullFlag;		// Record the "Store Full" status for future state transitions.
+	TInt ret=ActionRxEventUnstoredClientAck(ESmsEventRxAckNack);
+
+	// Handle any state transition errors now.  Simulated Ack/Nack failures are not supported yet...
+	if(ret!=KErrNone)
+		{
+		ReqCompleted(aReqHandle,ret);
+		return KErrNone;
+		}
+	iPendingReqHandle=aReqHandle;
+	return KErrNone;
+	}
+
+TInt CSimSmsMessaging::NackSmsStored(const TTsyReqHandle aReqHandle,TDes8* aMsg,TDes8* aRpCausePckg)
+/**
+ *	In response to an incoming sms message the sms stack Acks/Nacks the message
+ *  This function implements the NAck action.
+ *  aRpCausePckg must be filled in with the reason
+ */
+	{
+	TPckg<TInt>* rpCausePckg=(TPckg<TInt>*)aRpCausePckg;
+	TInt& rpCause=(*rpCausePckg)();
+
+	//  SMS-DELIVER-REPORT TPDU check 
+	_LIT8(emptyDesc,"");
+	if(aMsg->Compare(emptyDesc) != KErrNone)
+		{
+		RMobileSmsMessaging::TMobileSmsGsmTpdu reportPdu;
+		reportPdu.Zero();
+		if (CSimTsyMode::GetMode() != CSimTsyMode::ECdmaV1)
+  			{
+  			reportPdu = iSmsRxParameterListGsm->At(iSmsRxCnt-1).iDeliveryReport;
+  			}
+
+			
+		if (reportPdu.Length() > 0)	// check if SMS-DELIVER-REPORT TPDU in config file is present
+			{
+			if(aMsg->Match(reportPdu)!=0)//check if the transmitted pdu and the one in config file are not identical
+				{
+				ReqCompleted(aReqHandle,KErrCorrupt);
+				return KErrNone;
+				}
+			}
+		}
+
+	if(rpCause==KErrGsmSMSMemoryCapacityExceeded)
+		iSmsStoreFull=ETrue;
+	else
+		iSmsStoreFull=EFalse;
+
+	TInt ret=ActionRxEventUnstoredClientAck(ESmsEventRxAckNack);
+
+	// Handle any state transition errors now.  Simulated Ack/Nack failures are not supported yet...
+	if(ret!=KErrNone)
+		{
+		ReqCompleted(aReqHandle,ret);
+		return KErrNone;
+		}
+
+	iPendingReqHandle=aReqHandle;
+	return KErrNone;
+	}
+
+
+void CSimSmsMessaging::AckNackCancel()
+/*
+ * Cancel an outstanding Receive Message request.
+ */
+	{
+	//This method does nothing,, a complex implementation would have to be used to simulate a real tsy
+	}
+
+
+TInt CSimSmsMessaging::ResumeSmsReception(const TTsyReqHandle aReqHandle)
+/**
+ *  After the sms reception has been suspended(store full), if the client frees some space
+ *  the ME will inform the SC that reception can resume
+ *
+ */
+	{
+	TInt ret=ActionRxEventUnstoredClientAck(ESmsEventResume);
+// In case of state transition error, return the error code.
+// Resume failures cannot be simulated by the tsy yet...
+	if(ret!=KErrNone)
+		{
+		ReqCompleted(aReqHandle,ret);
+		return KErrNone;
+		}
+	iPendingReqHandle=aReqHandle;
+	return KErrNone;
+	}
+
+void CSimSmsMessaging::ResumeSmsReceptionCancel()
+	{
+	//Does nothing, a complex implementation would have to be used to simulate a real tsy
+	}
+
+//**********************************************
+//send
+//*********************************************
+
+
+TInt CSimSmsMessaging::ActionTxEvent(TSmsTxEvent aTxEvent)
+/**
+ *  This function actions the sms message sending state machine. It is triggered by sms sending events
+ *
+ */
+	{
+	LOGSMS1(">>ActionTxEvent ");
+	switch(iTxState)
+	{
+	case ESmsTxStateIdle:
+		__ASSERT_ALWAYS(aTxEvent!=ESmsEventSubmitReportReceived,SimPanic(EIllegalSmsTxEvent));
+		if(aTxEvent==ESmsEventSendReq)
+			{
+			iTxState=ESmsTxStateWaitingForSubmitReport;
+			iTxTimer->Start(iSmsTxPause,this, ETimerIdSmsMessTx);
+			}
+		break;
+	case ESmsTxStateWaitingForSubmitReport:
+		__ASSERT_ALWAYS(aTxEvent!=ESmsEventSendReq,SimPanic(EIllegalSmsTxEvent));	
+		if(aTxEvent==ESmsEventSubmitReportReceived)
+			{
+			iTxState=ESmsTxStateIdle;
+
+			PopulateSmsTxAttrib(iSmsTxAttrib);				
+			CompleteTxPendingReq(KErrNone);			
+			}
+		break;
+	}
+	return KErrNone;
+	}
+
+TInt CSimSmsMessaging::SendMessageL(const TTsyReqHandle aReqHandle,TDes8* aSmsPdu,TDes8* aParam2)
+/**
+ *	This function simulates the transmission of an sms from the ME to the SC.
+ *  It returns directly if 
+ *  -The Sms message description(SmsTx)tag in the config file specifies that this sms message should return with this error 
+ *  -The Pdu is corrupted
+ *  Otherwise it start the sms message sending state machine
+ * 
+ */
+
+	{
+    iSmsTxReqHandle=aReqHandle;
+    RMobileSmsMessaging::TMobileSmsSendAttributesV1Pckg* aAttribPckg=(RMobileSmsMessaging::TMobileSmsSendAttributesV1Pckg*)aParam2;
+	RMobileSmsMessaging::TMobileSmsSendAttributesV1& attrib=(*aAttribPckg)();
+		
+	// Check that the data structure is supported by the simulated TSY version
+	TInt err = iPhone->CheckSimTsyVersion(attrib);
+	if(err != KErrNone)
+		{
+		iPhone->ReqCompleted(aReqHandle, err);
+		return KErrNone;
+		}
+		
+	iSmsTxAttrib=&attrib;
+#ifdef _DEBUG
+		LogTMobileSmsAttributesV1(*iSmsTxAttrib);
+#endif // _DEBUG
+		
+
+	//check if messages defined in cfg file
+	TInt count = 0;	
+	count = iSmsTxParametersListGsm->Count();  
+	
+	if (count<=iSmsTxCnt)
+		return KErrTotalLossOfPrecision;
+
+	//check if expected error
+	//TInt err = KErrNone;
+	err = KErrNone;
+	err = iSmsTxParametersListGsm->At(iSmsTxCnt).iExpectedError;		
+	if (err!=KErrNone)
+		{
+		PopulateSmsTxAttrib(iSmsTxAttrib);			
+		CompleteTxPendingReq(err);
+		return KErrNone;
+		}
+
+		//check if a non null pdu is defined in the config file
+	RMobileSmsMessaging::TMobileSmsGsmTpdu octetPdu;
+	octetPdu = iSmsTxParametersListGsm->At(iSmsTxCnt).iPdu;
+
+	RMobileSmsMessaging::TMobileSmsGsmTpdu pduWith0;
+	TUint8 zero=0;
+	pduWith0.Append(&zero, 1);
+	if(octetPdu!=pduWith0)//if the pdu in config file is 00, skip the pdu check
+		{
+			if(aSmsPdu->Match(octetPdu)!=0)//check if the transmitted pdu and the one in config file are identical
+				{
+				CompleteTxPendingReq(KErrCorrupt);
+				return KErrNone;
+				}
+		}	
+
+	ActionTxEvent(ESmsEventSendReq);
+	return KErrNone;
+	}
+
+
+void CSimSmsMessaging::SendMessageCancel()
+/*
+ * Cancel an outstanding send Message request.
+ */
+	{
+	if(iTxState==ESmsTxStateWaitingForSubmitReport)
+		{
+		iTxTimer->Cancel();
+		iTxState=ESmsTxStateIdle;
+		CompleteTxPendingReq(KErrCancel);
+		}
+	}
+
+void CSimSmsMessaging::CompletePendingReq()
+	{
+	ReqCompleted(iPendingReqHandle,KErrNone);
+	}
+
+TInt CSimSmsMessaging::AttemptSmsRxComplete()
+/**
+ * Complete an outstanding SMS message receive request if one is outstanding.  If there is
+ * no request outstanding, the message will be discared.
+ * update the constraint count
+ */
+	{
+	LOGSMS1(">>AttemptSmsRxComplete ");
+
+	if (CSimTsyMode::GetMode() != CSimTsyMode::ECdmaV1)
+		{
+		iConstraintRxCnt++;
+		}
+
+	TInt ret=KErrNone;
+	if(iSmsRxReqOutstanding)
+		{
+		if (iSmsReceiveMode==RMobileSmsMessaging::EReceiveStored)
+			{
+			LOGSMS4(">>Populating SMS Structures. iSmsRxPdu&=%x, iSmsRxAttrib&=%x, iSmsRxCnt=%d.",iSmsRxPdu,iSmsRxAttrib,iSmsRxCnt);
+			RMobileSmsStore::TMobileGsmSmsEntryV1 sms;
+
+			*iSmsRxPdu=iSmsRxParameterListGsm->At(iSmsRxCnt).iPdu;
+			
+			sms.iMsgData=RMobileSmsMessaging::TMobileSmsGsmTpdu(*iSmsRxPdu);
+			sms.iServiceCentre.iTelNumber.Copy(iSmsRxParameterListGsm->At(iSmsRxCnt).iSca);
+		
+			sms.iServiceCentre.iTypeOfNumber=RMobilePhone::EInternationalNumber;//SmsMessaging only deals with international numbers
+			sms.iServiceCentre.iNumberPlan=RMobilePhone::EIsdnNumberPlan;
+			sms.iMsgStatus=RMobileSmsStore::EStoredMessageUnread;
+			ret = iSmsStores->At(0)->StoreIncomingMessage(&sms);//todo if several stores find the right one
+			if (ret==KErrNone)
+				{
+				iSmsRxAttrib->iStore.Copy(iSmsStores->At(0)->Name());
+				iSmsRxAttrib->iStoreIndex=sms.iIndex;
+				}
+			}
+		else
+			{			
+			*iSmsRxPdu = iSmsRxParameterListGsm->At(iSmsRxCnt).iPdu;				
+			}
+
+		if (ret==KErrNone)
+			{
+			iSmsRxReqOutstanding=EFalse;			
+			PopulateSmsRxAttrib(iSmsRxParameterListGsm->At(iSmsRxCnt).iSca,iSmsRxAttrib);	
+							
+			ReqCompleted(iSmsRxReqHandle,ret);
+			iSmsRxCnt++;
+			}
+		}
+	return ret;
+	}
+
+void CSimSmsMessaging::CompleteTxPendingReq(TInt aError)
+/**
+ * Complete a SmsTx request and increments the SmsTx counter
+ *
+ */
+	{
+	LOGSMS1(">>CompleteTxPendingReq ");
+	iSmsTxCnt++;
+	if(IpcMatch())
+		{
+		iConstraintRxCnt=0;
+		if( iSmsRxReqOutstanding )
+			{
+			// Client has a pending receive request - safe to start Rx timer
+			// to simulate received SMS from network.
+			StartSmsMtTimer();
+			}
+		else
+			{
+			// No pending client receive request - need to wait for it before
+			// simulating received SMS from network.
+			LOGSMS1(" - no pending receive req from client - do not start Rx timer");
+			}
+		}
+	ReqCompleted(iSmsTxReqHandle, aError);
+	}
+
+void CSimSmsMessaging::StartSmsMtTimer()
+	{
+	LOGSMS1(">>StartSmsMtTimer ");
+	TInt count = 0;
+	count = iSmsRxCnt<iSmsRxParameterListGsm->Count();
+			
+		if(count)		// Check that there are more messages defined in the config file.
+			{
+			if((iConstraints.Count()==0) ||	(iConstraintRxCnt<iConstraints[iCurrentConstraint].iRxCnt))	// If there are no constraints, or there are constraints and they're not exhausted.
+				{
+				LOGSMS1(">>StartSmsMtTimer Starting");
+				iRxTimer->Start(iSmsRxPeriod,this, ETimerIdSmsMessRx);
+				LOGSMS1(">>StartSmsMtTimer Started");
+				}
+			}
+	}
+
+
+void CSimSmsMessaging::PopulateSmsRxAttrib(const TDesC8& aAsciiScaAddr,RMobileSmsMessaging::TMobileSmsReceiveAttributesV1* aAttrib)
+/**
+ * Populate the SMS Rx Attributes from an ASCII respresentation, such as that stored in the configuration file.
+ * This involves checking the address for a leading '+' character and setting the TON and NPI
+ * accordingly.  The address can then be copied into the iTelNumber structure.
+ */
+	{
+	LOGSMS1(">>PopulateSmsRxAttrib, ");
+	aAttrib->iOriginator.iTelNumber.SetLength(0);
+	
+	switch (iSmsReceiveMode)
+		{
+	case RMobileSmsMessaging::EReceiveUnstoredClientAck:
+		aAttrib->iStatus=RMobileSmsMessaging::EMtMessageUnstoredClientAck;
+		aAttrib->iStore.SetLength(0);
+		aAttrib->iStoreIndex=-1;
+		break;
+	case RMobileSmsMessaging::EReceiveUnstoredPhoneAck:
+		aAttrib->iStatus=RMobileSmsMessaging::EMtMessageUnstoredPhoneAck;
+		aAttrib->iStore.SetLength(0);
+		aAttrib->iStoreIndex=-1;
+		break;
+	case RMobileSmsMessaging::EReceiveStored:
+		aAttrib->iStatus=RMobileSmsMessaging::EMtMessageStored;
+		break;
+	
+	default:
+		break;
+		}
+	aAttrib->iFlags=RMobileSmsMessaging::KGsmServiceCentre | RMobileSmsMessaging::KSmsDataFormat | RMobileSmsMessaging::KIncomingStatus;
+	aAttrib->iDataFormat=RMobileSmsMessaging::EFormatGsmTpdu;
+
+	if(aAsciiScaAddr.Length()>0)
+		{
+		aAttrib->iGsmServiceCentre.iNumberPlan=RMobilePhone::EIsdnNumberPlan;
+		aAttrib->iGsmServiceCentre.iTypeOfNumber=RMobilePhone::EInternationalNumber;
+		aAttrib->iGsmServiceCentre.iTelNumber.Copy(aAsciiScaAddr);
+		}
+	}
+
+
+void CSimSmsMessaging::PopulateSmsTxAttrib(RMobileSmsMessaging::TMobileSmsAttributesV1* aAttrib)
+/**
+ * Populate the SMS Tx Attributes for SMS from an ASCII respresentation, such as that stored in the configuration file.
+ * - Message Identifier
+ * - TL Ack
+ */
+	{
+	if (iSmsModeCaps == RMobileSmsMessaging::KCapsGsmSms)
+		{
+		RMobileSmsMessaging::TMobileSmsSendAttributesV1* attrib = static_cast<RMobileSmsMessaging::TMobileSmsSendAttributesV1*>(aAttrib);
+		attrib->iMsgRef = TUint16(iSmsTxParametersListGsm->At(iSmsTxCnt).iRef);	
+
+		attrib->iFlags = RMobileSmsMessaging::KMessageReference;
+		
+		if (iSmsControlCaps & RMobileSmsMessaging::KCapsSendWithAck)
+			{			
+			attrib->iSubmitReport=iSmsTxParametersListGsm->At(iSmsTxCnt).iSubmitReport;
+			attrib->iFlags |= RMobileSmsMessaging::KGsmSubmitReport;
+			}
+		}
+	}
+
+void CSimSmsMessaging::PopulateSmsTxAttrib(RMobileSmsMessaging::TMobileSmsSendAttributesV1* aAttrib)
+/**
+ * Populate the SMS Tx Attributes from an ASCII respresentation, such as that stored in the configuration file.
+ * -Message Reference
+ * -SUBMIT_REPORT_TPDU
+ */
+	{
+	 aAttrib->iMsgRef = TUint16(iSmsTxParametersListGsm->At(iSmsTxCnt).iRef);
+	 aAttrib->iFlags = RMobileSmsMessaging::KMessageReference;
+	
+	 if (iSmsControlCaps & RMobileSmsMessaging::KCapsSendWithAck)
+		{
+		aAttrib->iSubmitReport=iSmsTxParametersListGsm->At(iSmsTxCnt).iSubmitReport;
+		aAttrib->iFlags |= RMobileSmsMessaging::KGsmSubmitReport;
+		}
+	}
+
+TInt CSimSmsMessaging::GetCaps(const TTsyReqHandle aReqHandle,TDes8* aPckg)
+/**
+ * Process a request to retrieve the caps.  Currently, only the KCapsReceiveUnstoredClientAck
+ * mode is supported.
+ */
+	{
+	RMobileSmsMessaging::TMobileSmsCapsV1Pckg* capsPckg=(RMobileSmsMessaging::TMobileSmsCapsV1Pckg*)aPckg;
+	RMobileSmsMessaging::TMobileSmsCapsV1& caps=(*capsPckg)();
+
+	// Check that the data structure is supported by the simulated TSY version
+	TInt err = iPhone->CheckSimTsyVersion(caps);
+	if(err != KErrNone)
+		{
+		iPhone->ReqCompleted(aReqHandle, err);
+		return KErrNone;
+		}
+
+	 	caps.iSmsMode = RMobileSmsMessaging::KCapsGsmSms;
+		
+	caps.iSmsControl=iSmsControlCaps;
+	ReqCompleted(aReqHandle,KErrNone);
+	return KErrNone;
+	}
+
+TInt CSimSmsMessaging::GetReceiveMode(const TTsyReqHandle aReqHandle,TDes8* aPckg)
+/**
+ * Process a request to retrieve the current SMS receive mode.  Only the
+ * KCapsReceiveUnstoredClientAck mode is supported.
+ */
+	{
+	TPckg<RMobileSmsMessaging::TMobileSmsReceiveMode>* modePckg=(TPckg<RMobileSmsMessaging::TMobileSmsReceiveMode>*)aPckg;
+	RMobileSmsMessaging::TMobileSmsReceiveMode& mode=(*modePckg)();
+	mode=iSmsReceiveMode;
+	ReqCompleted(aReqHandle,KErrNone);
+	return KErrNone;
+	}
+
+TInt CSimSmsMessaging::SetReceiveMode(const TTsyReqHandle aReqHandle,TDes8* aPckg)
+/**
+ * Process a request to set the current SMS receive mode.  Only the
+ * KCapsReceiveUnstoredClientAck mode is supported.
+ */
+	{
+	TPckg<RMobileSmsMessaging::TMobileSmsReceiveMode>* modePckg=(TPckg<RMobileSmsMessaging::TMobileSmsReceiveMode>*)aPckg;
+	RMobileSmsMessaging:: TMobileSmsReceiveMode& mode=(*modePckg)();
+
+	TInt result(KErrNone);
+
+	switch (mode)
+		{
+		case RMobileSmsMessaging::EReceiveUnstoredClientAck:
+			{
+			if(iSmsControlCaps & RMobileSmsMessaging::KCapsReceiveUnstoredClientAck)
+				{
+				if ((iRxState==ESmsRxStateIdle) || (iRxState==ESmsRxStateWaitingForSmsRx))//can only change mode in these states
+					{
+					iSmsReceiveMode=RMobileSmsMessaging::EReceiveUnstoredClientAck;
+					ReqCompleted(aReqHandle,KErrNone);
+					}
+				else 
+					{
+					if(iSmsReceiveMode==RMobileSmsMessaging::EReceiveUnstoredClientAck)//already in this state
+						ReqCompleted(aReqHandle,KErrNone);
+					else
+						ReqCompleted(aReqHandle,KErrNotSupported);
+					}
+				}
+			else ReqCompleted(aReqHandle,KErrNotSupported); 
+			break;
+			}
+
+		case RMobileSmsMessaging::EReceiveUnstoredPhoneAck:
+			{
+			if(iSmsControlCaps & RMobileSmsMessaging:: KCapsReceiveUnstoredPhoneAck)
+				{
+				if ((iRxState==ESmsRxStateIdle) || (iRxState==ESmsRxStateWaitingForSmsRx))//can only change mode in these states
+					{
+					iSmsReceiveMode=RMobileSmsMessaging::EReceiveUnstoredPhoneAck;
+					ReqCompleted(aReqHandle,KErrNone);
+					}
+				else
+					{
+					if (iSmsReceiveMode==RMobileSmsMessaging::EReceiveUnstoredPhoneAck)//already in this state
+						ReqCompleted(aReqHandle,KErrNone);
+					else
+						ReqCompleted(aReqHandle,KErrNotSupported);
+					}
+				}
+			else
+				ReqCompleted(aReqHandle,KErrNotSupported); 	
+			break;
+			}
+
+		case RMobileSmsMessaging::EReceiveStored:
+			{
+			if(iSmsControlCaps & RMobileSmsMessaging:: KCapsReceiveStored)
+				{
+				if ((iRxState==ESmsRxStateIdle) || (iRxState==ESmsRxStateWaitingForSmsRx))//can only change mode in these states
+					{
+					iSmsReceiveMode=RMobileSmsMessaging::EReceiveStored;
+					ReqCompleted(aReqHandle,KErrNone);
+					}
+				else
+					{
+					if((iSmsReceiveMode==RMobileSmsMessaging::EReceiveStored))//already in this state
+						ReqCompleted(aReqHandle,KErrNone);
+					else
+						ReqCompleted(aReqHandle,KErrNotSupported);
+					}
+				}
+			else ReqCompleted(aReqHandle,KErrNotSupported); 
+			break;
+			}
+		default:
+			result = KErrNotSupported;
+		}
+	
+	return result;
+	}
+
+TInt CSimSmsMessaging::EnumerateMessagingStores(TTsyReqHandle aReqHandle,TDes8* aPckg)
+/**
+ * Process a request to retrieve the number of message stores supported.
+ * @param aReqHandle	The TSY request handle associated with this request.
+ * @param aPckg			The parameter package containing the count variable to be populated and
+ *						returned.
+ * @return TInt			Standard error value.
+ */
+	{
+	TPckg<TInt>* countPckg=(TPckg<TInt>*)aPckg;
+	TInt& count=(*countPckg)();
+	count=iSmsStores->Count();
+	ReqCompleted(aReqHandle,KErrNone);
+	return KErrNone;
+	}
+
+TInt CSimSmsMessaging::GetMessageStoreInfo(TTsyReqHandle aReqHandle,TDes8* aPckg1, TDes8* aPckg2)
+/**
+ * Retrieve information about an indexed SMS Message Store.
+ * @param aReqHandle	The TSY request handle associated with this request.
+ * @param aPckg1		The parameter package containing the index of the SMS Store for which
+ *						information is going to be retrieved.
+ * @param aPckg2		The parameter package in which the retrieved SMS Store information will
+ *						be passed back to the client.
+ * @return TInt			Standard error value.
+ */
+	{
+	TPckg<TInt>* indexPckg=(TPckg<TInt>*)aPckg1;
+	TInt& index=(*indexPckg)();
+	TPckg<RMobilePhoneStore::TMobilePhoneStoreInfoV1>* infoPckg=(TPckg<RMobilePhoneStore::TMobilePhoneStoreInfoV1>*)aPckg2;
+	RMobilePhoneStore::TMobilePhoneStoreInfoV1& info=(*infoPckg)();
+
+	// Check that the data structure is supported by the simulated TSY version
+	TInt err = iPhone->CheckSimTsyVersion(info);
+	if(err != KErrNone)
+		{
+		iPhone->ReqCompleted(aReqHandle, err);
+		return KErrNone;
+		}
+
+	if((index<0) || (index>=iSmsStores->Count()))
+		{
+		ReqCompleted(aReqHandle,KErrArgument);
+		return KErrNone;
+		}
+
+	info.iType=RMobilePhoneStore::EShortMessageStore;
+	info.iTotalEntries=iSmsStores->At(index)->MaxSlots();
+	info.iUsedEntries=iSmsStores->At(index)->UsedEntries();
+	info.iCaps= iSmsStores->At(index)->StoreCaps();
+	info.iName.Copy(iSmsStores->At(index)->Name());
+	ReqCompleted(aReqHandle,KErrNone);
+	return KErrNone;
+	}
+
+TInt CSimSmsMessaging::GetSmspListPhase1(const TTsyReqHandle aTsyReqHandle,
+                                            TDes8* aParam1,TDes8* aParam2)
+/** Get SMSP List Phase 1 
+ *
+ * If the GetSmspListPhase1L should leave this method takes care of that and 
+ * makes a premature ReqCompleted to the client.
+ *
+ * @param aTsyReqHandle the request ID 
+ * @param aClient The client sends down a handle that is saved together with the 
+ *				  list so the list can be returned to the right client in phase 2.
+ * @param aBufSiz The size of the retrieved network list. The size is set in 
+ * @return error code. 
+ */
+	{
+	if(iSmspBusy==EFalse)
+		{
+		iSmspBusy=ETrue;
+		UNPACK_PCKG(clientId,aParam1,RMobilePhone::TClientId);
+		UNPACK_PCKG(bufSize,aParam2,TInt);
+		TRAPD(leaveCode,GetSmspListPhase1L(aTsyReqHandle,clientId,bufSize));
+		if (leaveCode)
+			return leaveCode;
+		return KErrNone;
+		}
+	else
+		return KErrInUse;
+
+	}
+
+void CSimSmsMessaging::GetSmspListPhase1L(TTsyReqHandle aTsyReqHandle, 
+											 RMobilePhone::TClientId& aClientId, 
+											 TInt& aBufSize)
+/** Get SMSP List Phase 1 
+ *
+ * @param aTsyReqHandle the request ID 
+ * @param aClient The client sends down a handle that is saved together with the 
+ *				  list so the list can be returned to the right client in phase 2.
+ * @param aBufSiz The size of the smsp list. The size is set in 
+ * @return error code. 
+ */
+	{
+	// just check and remove if there are already existing entries from the 
+	// same client
+	TInt numberOfLists = iSmspReadAll->Count();
+	// Find the get smsplists attempts from this client, starting from end.  
+	for (TInt i = numberOfLists-1; i >= 0; --i)
+		{
+		CListReadAllAttempt* readOld=iSmspReadAll->At(i);
+		if ((readOld->iClient.iSessionHandle==aClientId.iSessionHandle) &&
+		    (readOld->iClient.iSubSessionHandle==aClientId.iSubSessionHandle))
+			{
+			iSmspReadAll->Delete(i);
+			}
+		}
+    // once we have cleaned all then we can proceed...
+	iSmspReqHandle=aTsyReqHandle;
+	// Store the streamed list and the client ID
+	
+	CListReadAllAttempt* read=CListReadAllAttempt::NewL(aClientId, aTsyReqHandle);
+	CleanupStack::PushL(read);
+	
+	read->iListBuf = iSmspEntries->StoreLC();
+	CleanupStack::Pop(read->iListBuf); // pop the CBufFlat allocated by StoreLC
+
+	iSmspReadAll->AppendL(read);
+	CleanupStack::Pop(read); // pop the CListReadAllAttempt
+
+// return the CBufFlat's size to client
+	aBufSize=(read->iListBuf)->Size();
+
+//	CleanupStack::PopAndDestroy(); // pop&destroy list
+
+	iSmspTimer->Start(iSmspBatchPause,this, ETimerIdSmsMessSmsp);
+	}
+
+TInt CSimSmsMessaging::GetSmspListPhase2(const TTsyReqHandle aTsyReqHandle,
+                                            TDes8* aParam1,TDes8* aParam2)
+/** Get SMSP List phase 2 
+ *
+ * In this metod the list which was retrieved during phase 1 is copied to 
+ * the memory which the client has allocated for this purose.
+ * @param aTsyReqHandle		Const pointer to the request ID 
+ * @param aClient			Handle to the client which list we are looking for.
+ * @param aBuf				Pointer to the memory that the etelmm has allocated. 
+ * @return error code. 
+ */
+	{	
+	UNPACK_PCKG(clientId,aParam1,RMobilePhone::TClientId);
+	TInt numberOfLists = iSmspReadAll->Count();
+	// Find the get smsplists attempts from this client  
+	for (TInt i = 0; i < numberOfLists; ++i)
+		{
+		CListReadAllAttempt* read=iSmspReadAll->At(i);
+		if ((read->iClient.iSessionHandle==clientId.iSessionHandle) &&
+		    (read->iClient.iSubSessionHandle==clientId.iSubSessionHandle))
+			{
+			TPtr8 bufPtr((read->iListBuf)->Ptr(0));
+			aParam2->Copy(bufPtr);						// Copy the streamed list to the client
+			delete read;
+			iSmspReadAll->Delete(i);
+			ReqCompleted(aTsyReqHandle,KErrNone);	// Completes the retrieval of a network list succesfully.
+			return KErrNone;
+			}
+		}
+	return(KErrNotFound);
+	}
+
+TInt CSimSmsMessaging::StoreSmspList(const TTsyReqHandle aTsyReqHandle, TDes8* aBuffer)
+/**
+ *	This function stores a new smsp list 
+ *  warning the new smsp list will only exist at run time. If the tsy is reloaded the smsp list 
+ *  will go back to the one defined in the configuration file
+ *  @param aBuffer Descriptor containing the new smsp list  
+ */
+	{
+	if (iSmspBusy==EFalse)
+		{
+		iSmspBusy=ETrue;
+		TRAPD(leaveCode,iSmspEntries->RestoreL(*aBuffer));
+		if (leaveCode)
+			return leaveCode;
+		iSmspReqHandle=aTsyReqHandle;
+		iSmspTimer->Start(iSmspBatchPause,this, ETimerIdSmsMessSmsp);
+		LOGSMS1("<<StoreSmsList,Exit function");
+		return KErrNone;
+		}
+	else
+		LOGSMS1("<<StoreSmsList,Exit function");
+		return KErrInUse;
+	
+	}
+
+void CSimSmsMessaging::StoreSmspListCancel()
+/*
+ * Cancel an outstanding store smspList request
+ * as iSmspBusy mutexes get and store, only 1 request handle wil exist at a time 
+ */
+	{
+	if(iSmspBusy != EFalse)
+		{
+		iSmspTimer->Cancel();
+		iSmspBusy=EFalse;
+		ReqCompleted(iSmspReqHandle,KErrNone);//The timer is cancelled but data has already been stored
+		}
+	}
+
+void CSimSmsMessaging::GetSmspListCancel()
+/*
+ * Cancel an outstanding get smspList request.
+ * as iSmspBusy mutexes get and store, only 1 request handle wil exist at a time 
+ */
+	{
+	if(iSmspBusy != EFalse)
+		{
+		iSmspTimer->Cancel();
+		iSmspBusy=EFalse;
+		ReqCompleted(iSmspReqHandle,KErrCancel);
+		}
+	}
+
+void CSimSmsMessaging::TimerCallBack(TInt aId)
+/**
+ * Process a timer call back event.  
+ * @param aId Contains the Id of the timer that triggered the event
+ * 
+ */
+	{
+	LOGSMS3(">>CSimSmsMesaging::TimerCallBack IN [aId=%d iSmsReceiveMode=%d]", aId, iSmsReceiveMode);
+	switch(aId)
+		{
+		case ETimerIdSmsMessTx:
+			{
+			TInt ret=ActionTxEvent(ESmsEventSubmitReportReceived);
+			__ASSERT_ALWAYS(ret==KErrNone,SimPanic(EIllegalSmsTxEvent));	// There should be no error from this action, but to check...
+			break;
+			}
+		case ETimerIdSmsMessSmsp:
+			{
+			iSmspBusy=EFalse;
+			ReqCompleted(iSmspReqHandle, KErrNone);
+			break;
+			}
+		case ETimerIdSmsMessRx:
+			{
+			TInt ret=0;
+			
+			switch (iSmsReceiveMode)//swich which state machine to enter
+				{
+			case RMobileSmsMessaging::EReceiveUnstoredClientAck:
+				ret=ActionRxEventUnstoredClientAck(ESmsEventRxTimer);
+				break;
+			case RMobileSmsMessaging::EReceiveUnstoredPhoneAck:
+				ret=ActionRxEventUnstoredPhoneAck(ESmsEventRxTimer);
+				break;
+			case RMobileSmsMessaging::EReceiveStored:
+				LOGSMS1("Recieve Stored SMS Rx Event.");
+				ret=ActionRxEventStored(ESmsEventRxTimer);
+				break;
+			default://other receive modes cannot be set
+				break;
+				}//end switch
+
+			if (ret != KErrNone)
+				{
+				LOGSMS2("ERROR: Unexpected ret code %d", ret);
+				__ASSERT_ALWAYS(ret==KErrNone,SimPanic(EIllegalSmsRxEvent, __LINE__));	// There should be no error from this action, but to check...
+				}
+
+			break;
+			}
+
+		case ETimerIdSmsMessResumeReception:
+			{
+			if (iSmsRxReqOutstanding)
+				{
+				iRxState = ESmsRxStateWaitingForSmsRx;
+				}
+			else
+				{
+				iRxState = ESmsRxStateIdle;
+				}
+			StartSmsMtTimer();
+			CompletePendingReq();
+			break;
+			}
+
+		default:
+			break;
+		}
+	LOGSMS1(">>CSimSmsMesaging::TimerCallBack OUT");
+	}
+
+const CTestConfigSection* CSimSmsMessaging::CfgFileSection()
+/**
+* Returns a pointer to the config file section
+*
+* @return CTestConfigSection a pointer to the configuration file data section
+*/
+	{
+	LOGSMS1(">>CSimSmsMessaging::CfgFileSection");
+	return iPhone->CfgFile();
+	}
+
+
+TInt CSimSmsMessaging::ReloadConfigL(const TTsyReqHandle aReqHandle)
+/**
+ * This function reloads the Rx, Tx and constraint parameters from the config file
+ * @param aReqHandle Handle to notify when operation completed
+ * @return KErrNone
+ */
+	{
+	LOGSMS1("Reloading configuration");
+	//Tell SimPhone to reread the test number property
+	iPhone->ResetTestNumber();
+	//Delete current configuration
+	iSmsRxParameterListGsm->Reset();	
+	iSmsTxParametersListGsm->Reset();
+	
+	iSmsTxCnt = 0;
+	iSmsRxCnt = 0;
+	iConstraints.Reset();
+	iCurrentConstraint = 0;
+	iConstraintRxCnt = 0;
+	//Reread the configuration
+	TInt err;
+	TRAP(err, FindAndCreateRxAttributesL());
+	if (err != KErrNone) return err;
+	TRAP(err, FindAndCreateTxAttributesL());
+	if (err != KErrNone) return err;
+	FindAndCreateConstraints();
+	
+	TInt count;
+	count = iSmsRxParameterListGsm->Count();
+		
+	if((count>0)&&(iConstraints.Count()==0))	// If there are messages to receive & no constraints, then
+		{
+		if (iRxTimer->Running())
+			{
+			iRxTimer->Cancel();
+			}
+		LOGSMS1("Starting Rx Timer");
+		iRxStatePrevious = iRxState;
+		iRxState = ESmsRxStateWaitingToStart;
+		iRxTimer->Start(iSmsRxStartDelay,this, ETimerIdSmsMessRx);
+		}
+	else if (iRxTimer->Running())
+		{
+		LOGSMS1("Stopping Rx Timer");
+		iRxTimer->Cancel();
+		}
+		
+	LOGSMS1("Finished reloading configuration");
+	ReqCompleted(aReqHandle,KErrNone);
+	return KErrNone;
+	}
+	
+HBufC8* CSimSmsMessaging::PduToAscii(TDesC8& aSmsPdu)
+/**
+ * Converts the contents of a TDes8 to their Hex representation
+ * @param aSmsPdu Reference to the descriptor to convert
+ * @return A pointer to an HBufC8 containing the Hex representation of aSmsPdu. The caller is responsible for freeing the object.
+ * @return Null if the HBufC8 was not successfuly created.
+ */
+	{
+	HBufC8* hexBuf = HBufC8::New(aSmsPdu.Length()*2+1);
+	if (hexBuf == NULL) return NULL;
+	TPtr8 des = hexBuf->Des();
+	des.FillZ();
+	des.Zero();
+	if (hexBuf != NULL)
+		{
+		for (TInt i = 0; i < aSmsPdu.Length(); i++)
+			{
+			TInt left = (aSmsPdu[i] & 0xF0) >> 4;
+			TInt right = aSmsPdu[i] & 0x0F;
+			if (left < 10)
+				{
+				des.Append(0x30 + left);
+				}
+			else
+				{
+				des.Append(0x41 + (left - 10));
+				}
+			if (right < 10)
+				{
+				des.Append(0x30 + right);
+				}
+			else
+				{
+				des.Append(0x41 + (right - 10));
+				}
+			}
+		}
+	des.Append(0);
+	return hexBuf;
+	}
+
+#ifdef _DEBUG // to prevent UREL build warnings
+void CSimSmsMessaging::DumpPdu(const TDesC8& aText, TDesC8& aSmsPdu, HBufC8* aPduInAscii)
+#else
+void CSimSmsMessaging::DumpPdu(const TDesC8& /*aText*/, TDesC8& aSmsPdu, HBufC8* aPduInAscii)
+#endif
+/**
+Print PDU in a loop, 150 chars per line
+@param aText - a header line about the PDU.
+@param aSmsPdu - PDU to log.
+@param aPduInAscii - aSmsPdu in ASCII format (default NULL).
+*/
+    {
+	LOGSMS3("%S pdu length=%d", &aText, aSmsPdu.Length());
+
+    if( !aSmsPdu.Length() )
+        return;
+
+	// In sendPdu case, caller needs to call PduToAscii for comparison.
+	// Then aPduInAscii is non-zero.
+	HBufC8* hexBuf = (aPduInAscii) ? aPduInAscii : PduToAscii(aSmsPdu);
+	if (! hexBuf)
+	    return;
+
+	//Print the pdu in a loop because LOGTEXT can only print up to 150 characters
+	for (TInt i = 0; i < hexBuf->Length(); i+=100)
+	    {
+		TInt len = Min(100, hexBuf->Mid(i).Length());
+        TPtrC8 pduChunk(hexBuf->Mid(i).Left(len).Ptr(), len);
+		LOGSMS2("PDU Chunk: %S:", &pduChunk);
+		}
+
+	if (0 == aPduInAscii)
+	  delete hexBuf;
+    }
+
+#ifdef _DEBUG
+
+/**
+Appends Type of number and Numbering plan identification to TBuf8 buffer.
+
+@param aBuffer Name of aTon will be appended to this buffer.
+@param aTon TMobileTON whose name will be appended to aBuffer.
+*/
+void CSimSmsMessaging::AppendTonToBuffer(TDes8& aBuffer,const RMobilePhone::TMobileTON& aTon)
+	{
+	switch(aTon)
+		{
+	case (RMobilePhone::EUnknownNumber):
+		{
+		aBuffer.Append(_L("EUnknownNumber"));
+		break;
+		}
+	case (RMobilePhone::EInternationalNumber):
+		{
+		aBuffer.Append(_L("EInternationalNumber"));
+		break;
+		}
+	case (RMobilePhone::ENationalNumber):
+		{
+		aBuffer.Append(_L("ENationalNumber"));
+		break;
+		}
+	case (RMobilePhone::ENetworkSpecificNumber):
+		{
+		aBuffer.Append(_L("ENetworkSpecificNumber"));
+		break;
+		}
+	case (RMobilePhone::ESubscriberNumber):
+		{
+		aBuffer.Append(_L("ESubscriberNumber"));
+		break;
+		}
+	case (RMobilePhone::EAlphanumericNumber):
+		{
+		aBuffer.Append(_L("EAlphanumericNumber"));
+		break;
+		}
+	case (RMobilePhone::EAbbreviatedNumber):
+		{
+		aBuffer.Append(_L("EAbbreviatedNumber"));
+		break;
+		}
+	default:
+		aBuffer.Append(_L("Wrong Ton Type"));
+		}
+	}
+
+void CSimSmsMessaging::AppendNpiToBuffer(TDes8& aBuffer,const RMobilePhone::TMobileNPI& aNpi)
+/**
+ *	Appends Numbering plan identification to TBuf8 buffer.
+ */
+	{
+	switch(aNpi)
+		{
+	case (RMobilePhone::EUnknownNumberingPlan):
+		{
+		aBuffer.Append(_L("EUnknownNumberingPlan"));
+		break;
+		}
+	case (RMobilePhone::EIsdnNumberPlan):
+		{
+		aBuffer.Append(_L("EIsdnNumberPlan"));
+		break;
+		}
+	case (RMobilePhone::EDataNumberPlan):
+		{
+		aBuffer.Append(_L("EDataNumberPlan"));
+		break;
+		}
+	case (RMobilePhone::ETelexNumberPlan):
+		{
+		aBuffer.Append(_L("ETelexNumberPlan"));
+		break;
+		}
+	case (RMobilePhone::EServiceCentreSpecificPlan1):
+		{
+		aBuffer.Append(_L("EServiceCentreSpecificPlan1"));
+		break;
+		}
+	case (RMobilePhone::EServiceCentreSpecificPlan2):
+		{
+		aBuffer.Append(_L("EServiceCentreSpecificPlan2"));
+		break;
+		}
+	case (RMobilePhone::ENationalNumberPlan):
+		{
+		aBuffer.Append(_L("ENationalNumberPlan"));
+		break;
+		}
+	case (RMobilePhone::EPrivateNumberPlan):
+		{
+		aBuffer.Append(_L("EPrivateNumberPlan"));
+		break;
+		}
+	case (RMobilePhone::EERMESNumberPlan):
+		{
+		aBuffer.Append(_L("EERMESNumberPlan"));
+		break;
+		}
+	default:
+		aBuffer.Append(_L("Wrong Npi Type"));
+		}
+	}
+
+void CSimSmsMessaging::LogTMobileSmsAttributesV1(const RMobileSmsMessaging::TMobileSmsAttributesV1& aSmsAttributesV1)
+	{
+	const TInt KTextWidth = 100;
+	_LIT8(KFLAGS,		"   iFlags:      ");
+	_LIT8(KSCADDR,		"   SC Address:  ");
+	_LIT8(KSCADDRTON,	"   SC Addr TON: ");
+	_LIT8(KSCADDRNPI,	"   SC Addr NPI: ");
+	_LIT8(KDATAFORMAT,	"   iDataFormat: ");
+	_LIT8(KDEADDR,		"   DE Address:  ");
+	_LIT8(KDEADDRTON,	"   DE Addr TON: ");
+	_LIT8(KDEADDRNPI,	"   DE Addr NPI: ");
+	_LIT8(KMORETOSEND,	"   iMore:       ");
+	_LIT8(KMSGREF,		"   iMsgRef:     ");
+	_LIT8(KSUBMITREP,	"   iSubmitRep:  ");
+
+	TBuf8<KTextWidth> buffer;
+
+	LOGSMS1("Send Sms Attributes:");
+	
+	buffer.Zero();
+	buffer.Copy(KFLAGS);
+	buffer.Append(_L8("0x"));
+	buffer.AppendFormat(_L8("%08X") , ((TInt)(aSmsAttributesV1.iFlags)));
+	LOGSMS2("Buffer: %S", &buffer);
+
+	if(aSmsAttributesV1.iFlags & RMobileSmsMessaging::KGsmServiceCentre)
+		{
+		buffer.Zero();
+		buffer.Copy(KSCADDR);
+		buffer.Append(aSmsAttributesV1.iGsmServiceCentre.iTelNumber);
+		LOGSMS2("buffer: %S", &buffer);
+
+		buffer.Zero();
+		buffer.Copy(KSCADDRTON);
+		AppendTonToBuffer(buffer,(aSmsAttributesV1.iGsmServiceCentre.iTypeOfNumber));
+		LOGSMS2("buffer: %S", &buffer);
+
+		buffer.Zero();
+		buffer.Copy(KSCADDRNPI);
+		AppendNpiToBuffer(buffer,(aSmsAttributesV1.iGsmServiceCentre.iNumberPlan));		   
+		LOGSMS2("buffer: %S", &buffer);
+		}
+	if(aSmsAttributesV1.iFlags & RMobileSmsMessaging::KSmsDataFormat)
+		{
+		buffer.Zero();
+		buffer.Copy(KDATAFORMAT);
+		if(aSmsAttributesV1.iDataFormat == RMobileSmsMessaging::EFormatUnspecified)
+			{
+			buffer.Append(_L("EFormatUnspecified"));
+			}
+		else if(aSmsAttributesV1.iDataFormat == RMobileSmsMessaging::EFormatGsmTpdu)
+			{
+			buffer.Append(_L("EFormatGsmTpdu"));
+			}		
+		LOGSMS2("buffer: %S", &buffer);
+		}
+	if(aSmsAttributesV1.iFlags & RMobileSmsMessaging::KRemotePartyInfo)
+		{
+		const RMobileSmsMessaging::TMobileSmsSendAttributesV1& smsSendAttributesV1 = static_cast<const RMobileSmsMessaging::TMobileSmsSendAttributesV1&> (aSmsAttributesV1);
+
+		buffer.Zero();
+		buffer.Copy(KDEADDR);
+		buffer.Append(smsSendAttributesV1.iDestination.iTelNumber);
+		LOGSMS2("buffer: %S", &buffer);
+
+		buffer.Zero();
+		buffer.Copy(KDEADDRTON);
+		AppendTonToBuffer(buffer,(smsSendAttributesV1.iDestination.iTypeOfNumber));
+		LOGSMS2("buffer: %S", &buffer);
+
+		buffer.Zero();
+		buffer.Copy(KDEADDRNPI);
+		AppendNpiToBuffer(buffer,(smsSendAttributesV1.iDestination.iNumberPlan)); 
+		LOGSMS2("buffer: %S", &buffer);
+		}
+	if(aSmsAttributesV1.iFlags & RMobileSmsMessaging::KMoreToSend)
+		{
+		const RMobileSmsMessaging::TMobileSmsSendAttributesV1& smsSendAttributesV1 = static_cast<const RMobileSmsMessaging::TMobileSmsSendAttributesV1&> (aSmsAttributesV1);
+
+		buffer.Zero();
+		buffer.Copy(KMORETOSEND);
+
+		if(smsSendAttributesV1.iMore)
+			{
+			buffer.Append(_L8("ETrue"));
+			}
+		else
+			{
+			buffer.Append(_L8("EFalse"));
+			}
+		LOGSMS2("buffer: %S", &buffer);
+		}
+	if(aSmsAttributesV1.iFlags & RMobileSmsMessaging::KMessageReference)
+		{
+		const RMobileSmsMessaging::TMobileSmsSendAttributesV1& smsSendAttributesV1 = static_cast<const RMobileSmsMessaging::TMobileSmsSendAttributesV1&> (aSmsAttributesV1);
+
+		buffer.Zero();
+		buffer.Copy(KMSGREF);
+		buffer.Append(_L("0x"));
+		buffer.AppendFormat(_L8("%08X") , smsSendAttributesV1.iMsgRef);
+		LOGSMS2("buffer: %S", &buffer);
+		}
+
+	if(aSmsAttributesV1.iFlags & RMobileSmsMessaging::KGsmSubmitReport)
+		{
+		const RMobileSmsMessaging::TMobileSmsSendAttributesV1& smsSendAttributesV1 = static_cast<const RMobileSmsMessaging::TMobileSmsSendAttributesV1&> (aSmsAttributesV1);
+
+		buffer.Zero();
+		buffer.Copy(KSUBMITREP);
+
+		TInt i = buffer.Length(); 
+		TInt j(0);
+		TInt k = (smsSendAttributesV1.iSubmitReport.Length() * 2) + buffer.Length();
+
+		TInt l = 0;
+		do
+			{
+			for(;i<=(KTextWidth-2);i+=2)
+				{
+				if(j==smsSendAttributesV1.iSubmitReport.Length())
+					{
+					break;
+					}
+				buffer.AppendFormat(_L8("%X") , smsSendAttributesV1.iSubmitReport[j]);
+				j++;
+				}
+			LOGSMS2("buffer: %S", &buffer);
+			buffer.Zero();
+			i=0;
+			l+=KTextWidth;
+			}
+		while(l < k);
+		}
+	}
+
+#endif // _DEBUG