diff -r 000000000000 -r 3553901f7fa8 telephonyserverplugins/simtsy/src/csimsmsmess.cpp --- /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 +#include "Simlog.h" +#include +#include "CSimTsyMode.h" + +//macro +#define UNPACK_PCKG(target,source,datatype) datatype& target= (*(TPckg*)(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(KSmsSettingGranularity); + + + FindAndCreateRxAttributesL(); + + iSmsTxParametersListGsm=new(ELeave) CArrayFixFlat(KSmsSettingGranularity); + + FindAndCreateTxAttributesL(); + iSmsStores=new(ELeave) CArrayFixFlat(KSmsStoreGranularity); + FindAndCreateSmsStoresL(iPhone); + FindAndCreateConstraints(); + iSmspReadAll=new(ELeave) CArrayPtrFlat(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;iAt(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;iItem(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;iItem(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;iItem(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;iItem(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;jCount();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>CSimSmsMessaging::OpenNewObjectByNameL"); + TBuf8 name; + name.Copy(aName); // Do simple 16 bit to 8 bit conversion + for(TInt i=0;iCount();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* fullFlagPckg=(TPckg*)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* rpCausePckg=(TPckg*)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 = iSmsRxCntCount(); + + if(count) // Check that there are more messages defined in the config file. + { + if((iConstraints.Count()==0) || (iConstraintRxCnt>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(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* modePckg=(TPckg*)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* modePckg=(TPckg*)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* countPckg=(TPckg*)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* indexPckg=(TPckg*)aPckg1; + TInt& index=(*indexPckg)(); + TPckg* infoPckg=(TPckg*)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("<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 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 (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 (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 (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 (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