--- /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