telephonyserverplugins/simtsy/src/csimsmsmess.cpp
changeset 0 3553901f7fa8
child 14 7ef16719d8cb
equal deleted inserted replaced
-1:000000000000 0:3553901f7fa8
       
     1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file
       
    18 */
       
    19 
       
    20 #include "csimsmsmess.h"
       
    21 #include <testconfigfileparser.h>
       
    22 #include "Simlog.h"
       
    23 #include <etelmm.h>
       
    24 #include "CSimTsyMode.h"
       
    25 
       
    26 //macro
       
    27 #define UNPACK_PCKG(target,source,datatype)  datatype& target=  (*(TPckg<datatype>*)(source))()
       
    28 
       
    29 const TInt KSmsSettingGranularity=5;	// < Granularity of SMS parameter list arrays.
       
    30 const TInt KSmsStoreGranularity=2;	// < Granularity of SMS store list array.
       
    31 const TInt KNoMessageReferenceInCofigurationFile=0;//the reference number returned to the client is 0 if
       
    32 													//no value is found in the configuration file
       
    33 			
       
    34 //
       
    35 // CSimSmsMessaging
       
    36 //
       
    37 
       
    38 void CSimSmsMessaging::CloseSmsObj(TAny* aObj)
       
    39 /**
       
    40  *	A utility function for cleaning up the stack.
       
    41  */
       
    42 	{
       
    43 	((CObject*)aObj)->Close();
       
    44 	}
       
    45 
       
    46 CSimSmsMessaging* CSimSmsMessaging::NewL(CSimPhone* aPhone)
       
    47 /**
       
    48  *	Standard two phase constructor.
       
    49  */
       
    50 	{
       
    51 	CSimSmsMessaging* smsMess=new(ELeave) CSimSmsMessaging(aPhone);
       
    52 	TCleanupItem newObjClose(CloseSmsObj,smsMess);
       
    53 	CleanupStack::PushL(newObjClose);
       
    54 	smsMess->ConstructL();
       
    55 	CleanupStack::Pop();
       
    56 	return smsMess;
       
    57 	}
       
    58 
       
    59 CSimSmsMessaging::CSimSmsMessaging(CSimPhone* aPhone)
       
    60 		: iPhone(aPhone), iSmspBusy(EFalse)
       
    61 	{}
       
    62 
       
    63 void CSimSmsMessaging::ConstructL()
       
    64 /**
       
    65  * Retrieve the SMS-related tags from the configuration file.
       
    66  *
       
    67  * 
       
    68  * If there are no constraints any SMS specified in the configuration file and the "incoming SMS event" timer will
       
    69  * be started.
       
    70  */
       
    71 	{
       
    72 	LOGSMS1("Starting to Load and Parse Sms Messaging Config ");
       
    73 	iRxTimer=CSimTimer::NewL(iPhone);
       
    74 	iTxTimer=CSimTimer::NewL(iPhone);
       
    75 	iSmspTimer=CSimTimer::NewL(iPhone);
       
    76 		
       
    77 	iSmsRxParameterListGsm=new(ELeave) CArrayFixFlat<TSmsRxParametersGsm>(KSmsSettingGranularity);	
       
    78 		
       
    79 		
       
    80 	FindAndCreateRxAttributesL();
       
    81 	
       
    82 	iSmsTxParametersListGsm=new(ELeave) CArrayFixFlat<TSmsTxParametersGsm>(KSmsSettingGranularity);		
       
    83 			
       
    84 	FindAndCreateTxAttributesL();
       
    85 	iSmsStores=new(ELeave) CArrayFixFlat<CSimSmsStore*>(KSmsStoreGranularity);
       
    86 	FindAndCreateSmsStoresL(iPhone);
       
    87 	FindAndCreateConstraints();
       
    88 	iSmspReadAll=new(ELeave) CArrayPtrFlat<CListReadAllAttempt>(KSmsStoreGranularity);
       
    89 	FindAndCreateSmsParamsL();
       
    90 
       
    91 	// NOTE - no need to start iRxTimer; this will be started once a EMobileSmsMessagingReceiveMessage
       
    92 	// request is received and/or Send Sms contrainst satisfied (see CompleteTxPendingReq)
       
    93 	
       
    94 	LOGSMS1("Finished parsing SMS Messaging config parameters");
       
    95 	}
       
    96 
       
    97 
       
    98 CSimSmsMessaging::~CSimSmsMessaging()
       
    99 /**
       
   100  *	Standard destructor.  Any objects created by the ::ConstructL() function should be destroyed here.
       
   101  */
       
   102 	{
       
   103 	if(iSmsRxParameterListGsm)
       
   104 		{
       
   105 		iSmsRxParameterListGsm->Delete(0,iSmsRxParameterListGsm->Count());
       
   106 		delete iSmsRxParameterListGsm;
       
   107 		}
       
   108 		
       
   109 	if(iSmsTxParametersListGsm)
       
   110 		{
       
   111 		iSmsTxParametersListGsm->Delete(0,iSmsTxParametersListGsm->Count());
       
   112 		delete iSmsTxParametersListGsm;
       
   113 		}
       
   114 			
       
   115 	delete iSmspEntries;
       
   116 
       
   117 	if (iSmsStores)
       
   118 		{
       
   119 		TInt storeCount=iSmsStores->Count();	
       
   120 		for(TInt i=0;i<storeCount;i++)
       
   121 			{
       
   122 			iSmsStores->At(i)->Close();
       
   123 			}
       
   124 		delete iSmsStores;
       
   125 		}
       
   126 
       
   127 	if (iSmspReadAll)
       
   128 		{
       
   129 		iSmspReadAll->ResetAndDestroy();
       
   130 		delete iSmspReadAll;
       
   131 		}
       
   132 	
       
   133 	iConstraints.Close();
       
   134 	if(iRxTimer)
       
   135 		delete iRxTimer;
       
   136 	if(iTxTimer)
       
   137 		delete iTxTimer;
       
   138 	if(iSmspTimer)
       
   139 		delete iSmspTimer;
       
   140 	}
       
   141 
       
   142 void CSimSmsMessaging::FindAndCreateRxAttributesL()
       
   143 /**
       
   144  * Extract values from the tags
       
   145  * SmsRx, SmsRxPeriod, SmsAckNackPause, SmsResumePause, SmsDeliveryReport
       
   146  *
       
   147  */	{
       
   148 	TInt ret=KErrNone;
       
   149 	TInt count=CfgFileSection()->ItemCount(KSmsRx);
       
   150 	const CTestConfigItem* item=NULL;
       
   151 	TInt i;
       
   152 	TSmsRxParametersGsm smsRxParameterGsm;
       
   153 	
       
   154 	LOGSMS2("CSimSmsMessaging::FindAndCreateRxAttributesL IN [count=%d]", count);
       
   155 
       
   156 	// Need to do this *before* entering the loop (so that we know 
       
   157 	// whether or not to read a delivery report pdu off the config file).
       
   158 	iSmsControlCaps=RMobileSmsMessaging::TMobileSmsControlCaps(CfgFileSection()->ItemValue(KSmsControlCaps,KDefaultSmsControlCaps));
       
   159 
       
   160 	for(i=0;i<count;i++)
       
   161 		{
       
   162 		item=CfgFileSection()->Item(KSmsRx,i);
       
   163 		if(!item)
       
   164 			break;
       
   165 
       
   166 		TPtrC8 smsPdu,sca;
       
   167 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,smsPdu);
       
   168 		if(ret!=KErrNone)
       
   169 			{
       
   170 			LOGPARSERR("smsPdu",ret,0,&KSmsRx);
       
   171 			continue;
       
   172 			}
       
   173 		else
       
   174 			{
       
   175 			smsRxParameterGsm.iPdu.Zero();
       
   176 			ConvertAsciiSms(smsPdu,smsRxParameterGsm.iPdu);
       
   177 			}
       
   178 		
       
   179 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,sca);
       
   180 		if(ret!=KErrNone)
       
   181 			{
       
   182 			LOGPARSERR("sca",ret,1,&KSmsRx);
       
   183 			continue;
       
   184 			}
       
   185 		else
       
   186 			{
       
   187 			smsRxParameterGsm.iSca=sca;
       
   188 			}
       
   189 			
       
   190 		//get delivery report pdu 
       
   191 		smsRxParameterGsm.iDeliveryReport.Zero(); 	
       
   192 		if (!(iSmsControlCaps & RMobileSmsMessaging::KCapsReceiveUnstoredClientAck))
       
   193 			{
       
   194 			TPtrC8 deliveryReportPdu;
       
   195 			ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,deliveryReportPdu);
       
   196 			if( (ret!=KErrNone) && (ret!=KErrGeneral) )
       
   197 				{
       
   198 				LOGPARSERR("deliveryReportPdu",ret,2,&KSmsRx);
       
   199 				}
       
   200 			else
       
   201 				{
       
   202 				if (CSimTsyMode::GetMode() != CSimTsyMode::ECdmaV1)			
       
   203 					{
       
   204   					ConvertAsciiSms(deliveryReportPdu,smsRxParameterGsm.iDeliveryReport); 
       
   205   					}
       
   206 
       
   207 				}
       
   208 			}
       
   209 
       
   210 		// add to list of params
       
   211 		iSmsRxParameterListGsm->AppendL(smsRxParameterGsm);	
       
   212 	
       
   213 		}// for
       
   214 	
       
   215 	iSmsRxPeriod=CfgFileSection()->ItemValue(KSmsRxPeriod,KDefaultSmsRxPeriod);
       
   216 	iAckNackCompletePause=CfgFileSection()->ItemValue(KSmsAckNackPause,KDefaultSmsAckNackPause);
       
   217 	iResumeCompletePause=CfgFileSection()->ItemValue(KSmsResumePause,KDefaultSmsResumePause);
       
   218 
       
   219 	if (iSmsControlCaps & RMobileSmsMessaging::KCapsReceiveUnstoredClientAck)
       
   220 		iSmsReceiveMode=RMobileSmsMessaging::EReceiveUnstoredClientAck;
       
   221 	else iSmsReceiveMode=RMobileSmsMessaging::EReceiveModeUnspecified;
       
   222 	LOGSMS5("iSmsRxPeriod =%d, iAckNackCompletePause=%d, iResumeCompletePause=%d, iSmsControlCaps=%d",iSmsRxPeriod, iAckNackCompletePause, iResumeCompletePause, iSmsControlCaps); 
       
   223 	LOGSMS4("iSmsModeCaps =%d, iSmsRxStartDelay = %d, iSmsReceiveMode = %d",iSmsModeCaps , iSmsRxStartDelay, iSmsReceiveMode);	
       
   224 	LOGSMS2("CSimSmsMessaging::FindAndCreateRxAttributesL OUT [count=%d]", iSmsRxParameterListGsm->Count());	
       
   225 	}
       
   226 
       
   227 void CSimSmsMessaging::FindAndCreateTxAttributesL()
       
   228 /**
       
   229  * Extract values from the tags
       
   230  * SmsTx, SmsTxPause
       
   231  *
       
   232  */
       
   233 	{
       
   234 	TInt ret=KErrNone;
       
   235 	TInt count=CfgFileSection()->ItemCount(KSmsTx);
       
   236 		
       
   237 	TSmsTxParametersGsm   smsTxParametersGsm;
       
   238 	
       
   239 	const CTestConfigItem* item=NULL;
       
   240 	for(TInt i=0;i<count;i++)
       
   241 		{
       
   242 		item=CfgFileSection()->Item(KSmsTx,i);//Tx
       
   243 		if(!item)
       
   244 			break;
       
   245 
       
   246 		//get pdu
       
   247 		TPtrC8 smsTx;
       
   248 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,smsTx);
       
   249 		if(ret!=KErrNone)
       
   250 			{
       
   251 			LOGPARSERR("smsTx",ret,0,&KSmsTx);
       
   252 			continue;
       
   253 			}
       
   254 		else
       
   255 			{			
       
   256 			smsTxParametersGsm.iPdu.Zero();
       
   257 			ConvertAsciiSms(smsTx,smsTxParametersGsm.iPdu);
       
   258 			}
       
   259 
       
   260 		//get Sca
       
   261 		TPtrC8 sca;
       
   262 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,sca);
       
   263 		if (ret!=KErrNone)
       
   264 			{
       
   265 			LOGPARSERR("sca",ret,1,&KSmsTx);
       
   266 			continue;
       
   267 			}
       
   268 		else
       
   269 			{			
       
   270 			smsTxParametersGsm.iSca.Copy(sca);				
       
   271 			}
       
   272 			
       
   273 		//get reference
       
   274 		TInt reference;
       
   275 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,reference);
       
   276 		if(ret!=KErrNone)
       
   277 			{
       
   278 			LOGPARSERR("reference",ret,2,&KSmsTx);
       
   279 			smsTxParametersGsm.iRef=KNoMessageReferenceInCofigurationFile;	
       
   280 			}
       
   281 		else
       
   282 			{	
       
   283 			smsTxParametersGsm.iRef=reference;				
       
   284 			}
       
   285 	
       
   286 		//get submit report pdu
       
   287 		TPtrC8 submitReportPdu;
       
   288 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,submitReportPdu);
       
   289 		if(ret!=KErrNone)
       
   290 			{
       
   291 			LOGPARSERR("submitReportPdu",ret,3,&KSmsTx);
       
   292 			continue;
       
   293 			}
       
   294 		else
       
   295 			{			
       
   296 			smsTxParametersGsm.iSubmitReport.Zero(); 	
       
   297 			ConvertAsciiSms(submitReportPdu,smsTxParametersGsm.iSubmitReport); 
       
   298 			}
       
   299 		
       
   300 		//get expected error code
       
   301 		TInt errorCode;
       
   302 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,4,errorCode);
       
   303 		if(ret!=KErrNone)
       
   304 			{
       
   305 			LOGPARSERR("errorCode",ret,4,&KSmsTx);
       
   306 			continue;
       
   307 			}
       
   308 		else
       
   309 			{		
       
   310 			smsTxParametersGsm.iExpectedError=errorCode;					
       
   311 			}		
       
   312 		
       
   313 		iSmsTxParametersListGsm->AppendL(smsTxParametersGsm);			
       
   314 
       
   315 		} //end for SmsTx Tag
       
   316 	
       
   317 	iSmsTxPause=CfgFileSection()->ItemValue(KSmsTxPause,KDefaultSmsTxPause);
       
   318 	}
       
   319 
       
   320 void CSimSmsMessaging::FindAndCreateConstraints()
       
   321 /**
       
   322  * Extract values from the tags
       
   323  * SmsStartRxDelay
       
   324  *
       
   325  */
       
   326 	{
       
   327 	TInt ret=KErrNone;
       
   328 	TInt count=CfgFileSection()->ItemCount(KSmsStartRxDelay);
       
   329 	const CTestConfigItem* item=NULL;
       
   330 	TConstraintEntry constraint;
       
   331 	for(TInt i=0;i<count;i++)//Rx delay
       
   332 		{
       
   333 		item=CfgFileSection()->Item(KSmsStartRxDelay,i);
       
   334 		if(!item)
       
   335 			break;
       
   336 		
       
   337 		TInt ipc,noBefore,noAfter;
       
   338 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,ipc);//only :SendMessage() is supported
       
   339 		if(ret!=KErrNone || ipc!=4207)
       
   340 			{
       
   341 			LOGPARSERR("ipc",ret,0,&KSmsStartRxDelay);
       
   342 			continue;
       
   343 			}
       
   344 
       
   345 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,noBefore);
       
   346 		if(ret==KErrNone)
       
   347 			constraint.iIpcCnt=noBefore;
       
   348 		else
       
   349 			{
       
   350 			LOGPARSERR("noBefore",ret,1,&KSmsStartRxDelay);
       
   351 			continue;
       
   352 			}
       
   353 
       
   354 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,noAfter);
       
   355 		if(ret==KErrNone)
       
   356 			constraint.iRxCnt=noAfter;
       
   357 		else
       
   358 			{
       
   359 			LOGPARSERR("noAfter",ret,2,&KSmsStartRxDelay);
       
   360 			continue;
       
   361 			}
       
   362 		
       
   363 		__ASSERT_ALWAYS(iConstraints.Append(constraint) == KErrNone,SimPanic(EGeneral));
       
   364 		}
       
   365 	}
       
   366 
       
   367 void CSimSmsMessaging::FindAndCreateSmsStoresL(CSimPhone* aPhone)
       
   368 /**
       
   369  *	Creates sms stores as defined in the comfiguation files
       
   370  *	Extract values from the tags
       
   371  *	SmsStore, SmsStoreEntry, SmsStoreIndividualReqPause, SmsStoreBatchReqPause
       
   372  */
       
   373 	{
       
   374 	TInt count=CfgFileSection()->ItemCount(KSmsStore);
       
   375 	const CTestConfigItem* item=NULL;
       
   376 	TInt ret=KErrNone;
       
   377 
       
   378 	for(TInt i=0;i<count;i++)
       
   379 		{
       
   380 		item=CfgFileSection()->Item(KSmsStore,i);
       
   381 		if(!item)
       
   382 			break;
       
   383 
       
   384 		TPtrC8 storeName;
       
   385 		TInt maxNumSlots;
       
   386 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,storeName);
       
   387 		if(ret!=KErrNone)
       
   388 			{
       
   389 			LOGPARSERR("storeName",ret,0,&KSmsStore);
       
   390 			continue;
       
   391 			}
       
   392 
       
   393 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,maxNumSlots);
       
   394 		if(ret!=KErrNone)
       
   395 			{
       
   396 			LOGPARSERR("maxNumSlots",ret,1,&KSmsStore);
       
   397 			continue;
       
   398 			}
       
   399 
       
   400 		CSimSmsStore* smsStore=CSimSmsStore::NewL(this,storeName,maxNumSlots,aPhone);
       
   401 		TCleanupItem newObjClose(CloseSmsObj,smsStore);
       
   402 		CleanupStack::PushL(newObjClose);
       
   403 		iSmsStores->AppendL(smsStore);
       
   404 		CleanupStack::Pop();
       
   405 		}
       
   406 
       
   407 	for(TInt j=0;j<iSmsStores->Count();j++)
       
   408 		{
       
   409 		iSmsStores->At(j)->PopulateStoreFromConfigFile();
       
   410 		}
       
   411 	}
       
   412 
       
   413 void CSimSmsMessaging::FindAndCreateSmsParamsL()
       
   414 /**
       
   415  *Populates the sms parameter List as defined in the configuration file
       
   416  *Extract values from the tags
       
   417  *SmsParamEntry, SmsParamEntry, SmsParamBatchReqPause, SmsParamMaxNumSlots
       
   418  */
       
   419 	{
       
   420 	iSmspEntries= CMobilePhoneSmspList::NewL();
       
   421 
       
   422 	const TInt maxSlots = CfgFileSection()->ItemValue(KSmspMaxNumSlots ,KDefaultSmspMaxNumSlots);
       
   423 	iSmspEntries->SetMaxNumberEntries(maxSlots);
       
   424 
       
   425 	iSmspBatchPause = CfgFileSection()->ItemValue(KSmspBatchReqPause,KDefaultSmspBatchReqPause);
       
   426 
       
   427 	const TInt numberOfSmspEntries = Min(CfgFileSection()->ItemCount(KSmsParamEntry), maxSlots);
       
   428 	const CTestConfigItem* item=NULL;
       
   429 	TInt ret=KErrNone;
       
   430 	
       
   431 	for(TInt i=0;i < numberOfSmspEntries;i++)
       
   432 		{
       
   433 		item=CfgFileSection()->Item(KSmsParamEntry,i);
       
   434 
       
   435 		if(!item)
       
   436 			break;
       
   437 
       
   438 		RMobileSmsMessaging::TMobileSmspEntryV1 entry = RMobileSmsMessaging::TMobileSmspEntryV1();
       
   439 
       
   440 		TInt index, pid, dcs, validityPeriod;
       
   441 		TPtrC8 destAddress, sca, smspName;
       
   442 
       
   443 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,index);
       
   444 		if((ret==KErrNone)&&(index < maxSlots))
       
   445 			entry.iIndex=index;
       
   446 		else
       
   447 			{
       
   448 			LOGPARSERR("index",ret,0,&KSmsParamEntry);
       
   449 			continue;
       
   450 			}
       
   451 
       
   452 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,smspName);
       
   453 		if(ret==KErrNone)
       
   454 			entry.iText.Copy(smspName);
       
   455 		else
       
   456 			{
       
   457 			LOGPARSERR("smspName",ret,1,&KSmsParamEntry);
       
   458 			continue;
       
   459 			}
       
   460 
       
   461 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,pid);
       
   462 		if(ret==KErrNone)
       
   463 			{
       
   464 			entry.iProtocolId=TUint8(pid);
       
   465 			entry.iValidParams |= RMobileSmsMessaging::KProtocolIdIncluded;
       
   466 			}
       
   467 		else
       
   468 			{
       
   469 			LOGPARSERR("pid",ret,2,&KSmsParamEntry);
       
   470 			continue;
       
   471 			}
       
   472 
       
   473 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,dcs);
       
   474 		if(ret==KErrNone)
       
   475 			{
       
   476 			entry.iDcs=TUint8(dcs);
       
   477 			entry.iValidParams |= RMobileSmsMessaging::KDcsIncluded;
       
   478 			}
       
   479 		else
       
   480 			{
       
   481 			LOGPARSERR("dcs",ret,3,&KSmsParamEntry);
       
   482 			continue;
       
   483 			}
       
   484 
       
   485 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,4,validityPeriod);
       
   486 		if(ret==KErrNone)
       
   487 			{
       
   488 			entry.iValidityPeriod=TUint8(validityPeriod);
       
   489 			entry.iValidParams |= RMobileSmsMessaging::KValidityPeriodIncluded;
       
   490 			}
       
   491 		else
       
   492 			{
       
   493 			LOGPARSERR("validityPeriod",ret,4,&KSmsParamEntry);
       
   494 			continue;
       
   495 			}
       
   496 
       
   497 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,5,destAddress);
       
   498 		if(ret==KErrNone)
       
   499 			{
       
   500 			RecordDestination(destAddress, entry);
       
   501 			}
       
   502 		else
       
   503 			{
       
   504 			LOGPARSERR("destAddress",ret,5,&KSmsParamEntry);
       
   505 			continue;
       
   506 			}
       
   507 
       
   508 		ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,6,sca);
       
   509 		if(ret==KErrNone)
       
   510 			{
       
   511 			RecordSca(sca, entry);
       
   512 			}
       
   513 		else
       
   514 			{
       
   515 			LOGPARSERR("sca",ret,6,&KSmsParamEntry);
       
   516 			continue;
       
   517 			}
       
   518 
       
   519 		iSmspEntries->AddEntryL(entry);
       
   520 		}
       
   521 	}
       
   522 
       
   523 void CSimSmsMessaging::RecordSca(const TDesC8& aAsciiAddr, RMobileSmsMessaging::TMobileSmspEntryV1& aEntry)
       
   524 /**
       
   525  * Used to set the sca number in the smsp
       
   526  *
       
   527  * @param aAsciiSca Ascii representation of a telephone number such as the one found in the configuration file
       
   528  * @param aEntry reference to the actual smspentry in which the sca is going to be recorded
       
   529  */
       
   530 	{
       
   531 	if(aAsciiAddr.Length()>0)//only support for international numbers
       
   532 		{
       
   533 		aEntry.iServiceCentre.iNumberPlan=RMobilePhone::EIsdnNumberPlan;
       
   534 		aEntry.iServiceCentre.iTypeOfNumber=RMobilePhone::EInternationalNumber;
       
   535 		aEntry.iServiceCentre.iTelNumber.Copy(aAsciiAddr);
       
   536 		aEntry.iValidParams |= RMobileSmsMessaging::KSCAIncluded;
       
   537 		}
       
   538 	}
       
   539 
       
   540 void CSimSmsMessaging::RecordDestination(const TDesC8& aAsciiAddr, RMobileSmsMessaging::TMobileSmspEntryV1& aEntry)
       
   541 /**
       
   542  * Used to set the destination number in the smsp
       
   543  *
       
   544  * @param aAsciiAddr Ascii representation of a telephone number such as the one found in the configuration file
       
   545  * @param aEntry reference to the actual smspentry in which the destination is going to be recorded
       
   546  */
       
   547 	{
       
   548 	if(aAsciiAddr.Length()>0)//only support for international numbers
       
   549 		{
       
   550 		aEntry.iDestination.iNumberPlan=RMobilePhone::EIsdnNumberPlan;
       
   551 		aEntry.iDestination.iTypeOfNumber=RMobilePhone::EInternationalNumber;
       
   552 		aEntry.iDestination.iTelNumber.Copy(aAsciiAddr);
       
   553 		aEntry.iValidParams |= RMobileSmsMessaging::KDestinationIncluded;
       
   554 		}	
       
   555 	}
       
   556 
       
   557 #ifdef _DEBUG	// to stop the UREL build warnings
       
   558 void CSimSmsMessaging::LogRequest(const TBool aEntering, TInt aIpc, TInt aError)
       
   559 #else
       
   560 void CSimSmsMessaging::LogRequest(const TBool aEntering, TInt aIpc, TInt /*aError*/)
       
   561 #endif
       
   562 /**
       
   563  * This method logs client requests to the t_reg.txt
       
   564  * @param aDirection Tells if the request is coming into simtsy tsy or completing
       
   565  * @param aIpc IPC number of request
       
   566  * @param aError Error code that the request has
       
   567  */
       
   568  	{
       
   569 	TBuf8<64> ipcBuf;
       
   570 
       
   571 	switch (aIpc)
       
   572 		{
       
   573 		case EEtelServerLoadPhoneModule:
       
   574 			ipcBuf = _L8("ServerLoadPhoneModule");
       
   575 			break;
       
   576 
       
   577 		case EEtelPhoneGetStatus:
       
   578 			ipcBuf = _L8("PhoneGetStatus");
       
   579 			break;
       
   580 
       
   581 		case EEtelPhoneNotifyModemDetected:
       
   582 			ipcBuf = _L8("PhoneNotifyModemDetected");
       
   583 			break;
       
   584 		case EEtelPhoneInitialise:
       
   585 			ipcBuf = _L8("PhoneInitialise");
       
   586 			break;
       
   587 		case EMobileSmsMessagingGetCaps:
       
   588 			ipcBuf = _L8("GetCaps");
       
   589 			break;
       
   590 		case EMobileSmsMessagingGetReceiveMode:
       
   591 			ipcBuf = _L8("GetReceiveMode");
       
   592 			break;
       
   593 		case EMobileSmsMessagingGetMoSmsBearer:
       
   594 			ipcBuf = _L8("GetMoSmsBearer");
       
   595 			break;
       
   596 		case EMobileSmsMessagingEnumerateMessageStores:
       
   597 			ipcBuf = _L8("EnumerateMessageStores");
       
   598 			break;
       
   599 		case EMobileSmsMessagingGetMessageStoreInfo:
       
   600 			ipcBuf = _L8("GetMessageStoreInfo");
       
   601 			break;
       
   602 		case EMobileSmsMessagingGetSmspListPhase2:
       
   603 			ipcBuf = _L8("GetSmspListPhase2");
       
   604 			break;
       
   605 		case EMobileSmsMessagingSetReceiveMode:
       
   606 			ipcBuf = _L8("SetReceiveMode");
       
   607 			break;
       
   608 		case EMobileSmsMessagingSetMoSmsBearer:
       
   609 			ipcBuf = _L8("SetMoSmsBearer");
       
   610 			break;
       
   611 		case EMobileSmsMessagingAckSmsStored:
       
   612 			ipcBuf = _L8("AckSmsStored");
       
   613 			break;
       
   614 		case EMobileSmsMessagingNackSmsStored:
       
   615 			ipcBuf = _L8("NackSmsStored");
       
   616 			break;
       
   617 		case EMobileSmsMessagingResumeSmsReception:
       
   618 			ipcBuf = _L8("ResumeSmsReception");
       
   619 			break;
       
   620 		case EMobileSmsMessagingSendMessage:
       
   621 			ipcBuf = _L8("SendMessage");
       
   622 			break;
       
   623 		case EMobileSmsMessagingGetSmspListPhase1:
       
   624 			ipcBuf = _L8("GetSmspListPhase1");
       
   625 			break;
       
   626 		case EMobileSmsMessagingStoreSmspList:
       
   627 			ipcBuf = _L8("StoreSmspList");
       
   628 			break;
       
   629 		case EMobileSmsMessagingReceiveMessage:
       
   630 			ipcBuf = _L8("ReceiveMessage");
       
   631 			break;
       
   632 		case EMobileSmsMessagingNotifyReceiveModeChange:
       
   633 			ipcBuf = _L8("NotifyReceiveModeChange");
       
   634 			break;
       
   635 		case EMobileSmsMessagingNotifyMoSmsBearerChange:
       
   636 			ipcBuf = _L8("NotifyMoSmsBearerChange");
       
   637 			break;
       
   638 		case EMobileSmsMessagingNotifySmspListChange:
       
   639 			ipcBuf = _L8("NotifySmspListChange");
       
   640 			break;
       
   641 		case EMobileSmsMessagingSetReceiveModeCancel:
       
   642 			ipcBuf = _L8("SetReceiveModeCancel");
       
   643 			break;
       
   644 		case EMobileSmsMessagingNotifyReceiveModeChangeCancel:
       
   645 			ipcBuf = _L8("NotifyReceiveModeChangeCancel");
       
   646 			break;
       
   647 		case EMobileSmsMessagingSetMoSmsBearerCancel:
       
   648 			ipcBuf = _L8("SetMoSmsBearerCancel");
       
   649 			break;
       
   650 		case EMobileSmsMessagingNotifyMoSmsBearerChangeCancel:
       
   651 			ipcBuf = _L8("NotifyMoSmsBearerChangeCancel");
       
   652 			break;
       
   653 		case EMobileSmsMessagingAckSmsStoredCancel:
       
   654 			ipcBuf = _L8("AckSmsStoredCancel");
       
   655 			break;
       
   656 		case EMobileSmsMessagingNackSmsStoredCancel:
       
   657 			ipcBuf = _L8("NackSmsStoredCancel");
       
   658 			break;
       
   659 		case EMobileSmsMessagingResumeSmsReceptionCancel:
       
   660 			ipcBuf = _L8("ResumeSmsReceptionCancel");
       
   661 			break;
       
   662 		case EMobileSmsMessagingSendMessageCancel:
       
   663 			ipcBuf = _L8("SendMessageCancel");
       
   664 			break;
       
   665 		case EMobileSmsMessagingReceiveMessageCancel:
       
   666 			ipcBuf = _L8("ReceiveMessageCancel");
       
   667 			break;
       
   668 		case EMobileSmsMessagingGetMessageStoreInfoCancel:
       
   669 			ipcBuf = _L8("GetMessageStoreInfoCancel");
       
   670 			break;
       
   671 		case EMobileSmsMessagingGetSmspListCancel:
       
   672 			ipcBuf = _L8("GetSmspListCancel");
       
   673 			break;
       
   674 		case EMobileSmsMessagingStoreSmspListCancel:
       
   675 			ipcBuf = _L8("StoreSmspListCancel");
       
   676 			break;
       
   677 		case EMobileSmsMessagingNotifySmspListChangeCancel:
       
   678 			ipcBuf = _L8("NotifySmspListChangeCancel");
       
   679 			break;
       
   680 		default:
       
   681 			ipcBuf = _L8("OTHER");
       
   682 			break;
       
   683 		}
       
   684 
       
   685 	if (aEntering!=EFalse)
       
   686 		{
       
   687 		LOGSMS3(">>%d,CSimSmsMessaging::%S",aIpc, &ipcBuf );
       
   688 		}
       
   689 	else
       
   690 		{
       
   691 		LOGSMS4("<<%d, CSimSmsMessaging::%S with error %d",aIpc, &ipcBuf, aError);
       
   692 		}
       
   693 	}
       
   694 
       
   695 
       
   696 TInt CSimSmsMessaging::ExtFunc(const TTsyReqHandle aReqHandle,const TInt aIpc, const TDataPackage& aPckg)
       
   697 /**
       
   698  * Sms Read/Send Dispatch Function.
       
   699  *
       
   700  * If this method returns with an KErr code apart from KErrNone then Etel will 
       
   701  * complete and destory the clients request for us. 
       
   702  *
       
   703  * @param aTsyReqHandle The handle of the request which started the IPC
       
   704  * @param aIpc The IPC being requested
       
   705  * @param aPackage Package of parameters associated with the IPC
       
   706  * @return Standard KErr... codes
       
   707  */	{
       
   708 	TInt ret=KErrNone;//error is only used with LogRequest when at the end of ExtFunc
       
   709 	LogRequest(ETrue, aIpc, ret);
       
   710 
       
   711 	switch(aIpc)
       
   712 		{
       
   713 	case EMobileSmsMessagingReceiveMessage://4211
       
   714 		{
       
   715 		TRAPD(leaveCode, ret = ReceiveMessageL(aReqHandle,aPckg.Des1n(),aPckg.Des2n()));
       
   716 		if (leaveCode != KErrNone)
       
   717 			{
       
   718 			ret = leaveCode;
       
   719 			}
       
   720 		}
       
   721 		break;
       
   722 		
       
   723 	case EMobileSmsMessagingGetCaps:
       
   724 		ret = GetCaps(aReqHandle,aPckg.Des1n());
       
   725 		break;
       
   726 
       
   727 	case EMobileSmsMessagingEnumerateMessageStores:
       
   728 		ret = EnumerateMessagingStores(aReqHandle,aPckg.Des1n());
       
   729 		break;
       
   730 
       
   731 	case EMobileSmsMessagingGetMessageStoreInfo:
       
   732 		ret = GetMessageStoreInfo(aReqHandle,aPckg.Des1n(),aPckg.Des2n());
       
   733 		break;
       
   734 
       
   735 	case EMobileSmsMessagingGetReceiveMode:
       
   736 		ret = GetReceiveMode(aReqHandle,aPckg.Des1n());
       
   737 		break;
       
   738 		
       
   739 	case EMobileSmsMessagingSetReceiveMode:
       
   740 		ret = SetReceiveMode(aReqHandle,aPckg.Des1n());//4202
       
   741 		break;
       
   742 
       
   743 	case EMobileSmsMessagingAckSmsStored:
       
   744 		ret = AckSmsStored(aReqHandle,aPckg.Des1n(),aPckg.Des2n());
       
   745 		break;
       
   746 
       
   747 	case EMobileSmsMessagingNackSmsStored:
       
   748 		ret = NackSmsStored(aReqHandle,aPckg.Des1n(),aPckg.Des2n());
       
   749 		break;
       
   750 
       
   751 	case EMobileSmsMessagingResumeSmsReception:
       
   752 		ret = ResumeSmsReception(aReqHandle);
       
   753 		break;
       
   754 
       
   755 	case EMobileSmsMessagingGetSmspListPhase1:
       
   756 		ret = GetSmspListPhase1(aReqHandle,aPckg.Des1n(), aPckg.Des2n());
       
   757 		break;
       
   758 
       
   759 	case EMobileSmsMessagingGetSmspListPhase2:
       
   760 		ret = GetSmspListPhase2(aReqHandle,aPckg.Des1n(), aPckg.Des2n());
       
   761 		break;
       
   762 
       
   763 	case EMobileSmsMessagingStoreSmspList:
       
   764 		ret = StoreSmspList(aReqHandle,aPckg.Des1n());
       
   765 		break;
       
   766 
       
   767 	case EMobileSmsMessagingSendMessage://4207
       
   768 		{
       
   769 		TRAPD(leaveCode, ret = SendMessageL(aReqHandle,aPckg.Des1n(),aPckg.Des2n()));
       
   770 		if (leaveCode != KErrNone)
       
   771 			{
       
   772 			ret = leaveCode;
       
   773 			}
       
   774 		}
       
   775 		break;
       
   776 	
       
   777 	//This is used to re-read the configuration without having to restart the TSY
       
   778 	//For testing purposes
       
   779 	case EMobileSmsMessagingGetMoSmsBearer:
       
   780 		//  FALLTHRU
       
   781 
       
   782 	default:
       
   783 		ret=KErrNotSupported;
       
   784 		break;
       
   785 		}
       
   786 	LogRequest(EFalse, aIpc, ret);
       
   787 	return ret;
       
   788 	}
       
   789 
       
   790 TBool CSimSmsMessaging::ConstraintEllapsed() const
       
   791 /**
       
   792  * Check if the current contraint has ellapsed - i.e. check that that the number of received SMS
       
   793  * messages has reached the expected number for the current constraint.
       
   794  * @return ETrue if a constraint has ellapsed
       
   795  */
       
   796 	{
       
   797 	TBool ellapsed = EFalse;
       
   798 	if( iConstraints.Count()>0 )
       
   799 		{
       
   800 		//check if the number of rx mess has been reached
       
   801 		ellapsed=(iConstraintRxCnt==iConstraints[iCurrentConstraint].iRxCnt);
       
   802 		}
       
   803 	return ellapsed;
       
   804 	}
       
   805 
       
   806 TBool CSimSmsMessaging::IpcMatch()
       
   807 /**
       
   808  * Check if the number of Sms sent matches a constraint i.e. the number of messages sent reaches the number
       
   809  * of sms to be sent to allow incoming messages to start being simulated.
       
   810  * @return ETrue if a match is found
       
   811  */
       
   812 	{
       
   813 	TInt i;
       
   814 	TBool constraintEllapsed=ConstraintEllapsed();
       
   815 	
       
   816 	// NOTE - call ConstraintEllapsed() before doing loop below as iCurrentConstraint
       
   817 	// is updated in the loop and so can result in ConstraintEllapsed() giving a 
       
   818 	// different result
       
   819 	
       
   820 	for(i=0;i<iConstraints.Count();i++)
       
   821 		{
       
   822 		if(iSmsTxCnt==(iConstraints[i].iIpcCnt))
       
   823 			{
       
   824 			iCurrentConstraint=i;
       
   825 			LOGSMS2("New Constraint : %d", iCurrentConstraint);
       
   826 			if(i!=0)
       
   827 				{
       
   828 				if( !constraintEllapsed )
       
   829 					{
       
   830 					LOGSMS1("Panic The constraints are overlapping...Compare test code and config file");
       
   831 					}
       
   832 				__ASSERT_ALWAYS(constraintEllapsed!=EFalse,SimPanic(EConstraintsOverlapping));
       
   833 				}
       
   834 			return ETrue;
       
   835 			}
       
   836 		}
       
   837 	return EFalse;
       
   838 	}
       
   839 
       
   840 CTelObject* CSimSmsMessaging::OpenNewObjectByNameL(const TDesC& aName)
       
   841 /**
       
   842  *
       
   843  */
       
   844 	{
       
   845 	LOGSMS1(">>CSimSmsMessaging::OpenNewObjectByNameL");
       
   846 	TBuf8<KMaxName> name;
       
   847 	name.Copy(aName);		// Do simple 16 bit to 8 bit conversion
       
   848 	for(TInt i=0;i<iSmsStores->Count();i++)
       
   849 		{
       
   850 		if(name.MatchF(iSmsStores->At(i)->Name())==0)
       
   851 			{
       
   852 			// Base class open
       
   853 			(void)iSmsStores->At(i)->Open();
       
   854 			return iSmsStores->At(i);
       
   855 			}
       
   856 		}
       
   857 	User::Leave(KErrNotFound);
       
   858 	return NULL;
       
   859 	}
       
   860 
       
   861 CTelObject* CSimSmsMessaging::OpenNewObjectL(TDes&)
       
   862 /**
       
   863  *
       
   864  */
       
   865 	{
       
   866 	User::Leave(KErrNotSupported);
       
   867 	return NULL;
       
   868 	}
       
   869 
       
   870 CTelObject::TReqMode CSimSmsMessaging::ReqModeL(const TInt aIpc)
       
   871 /**
       
   872  *	This function returns the Request Mode for the request with the passed IPC value.
       
   873  *	The ETel Server provides a function for returning the standard request modes for
       
   874  *	the Core API requests.
       
   875  */
       
   876 	{
       
   877 	CTelObject::TReqMode ret=0;	
       
   878 
       
   879 	switch(aIpc)
       
   880 		{
       
   881 	case EMobileSmsMessagingReceiveMessage:
       
   882 		ret=KReqModeRePostImmediately;
       
   883 		break;
       
   884 
       
   885 	case EMobileSmsMessagingGetCaps:
       
   886 	case EMobileSmsMessagingSetReceiveMode:
       
   887 	case EMobileSmsMessagingGetReceiveMode:
       
   888 	case EMobileSmsMessagingAckSmsStored:
       
   889 	case EMobileSmsMessagingNackSmsStored:
       
   890 	case EMobileSmsMessagingResumeSmsReception:
       
   891 	case EMobileSmsMessagingEnumerateMessageStores:
       
   892 	case EMobileSmsMessagingGetMessageStoreInfo:
       
   893 	case EMobileSmsMessagingSendMessage:
       
   894 	case EMobileSmsMessagingGetSmspListPhase1:
       
   895 	case EMobileSmsMessagingGetSmspListPhase2:
       
   896 	case EMobileSmsMessagingStoreSmspList:
       
   897 		ret=0;
       
   898 		break;
       
   899 	case EMobileSmsMessagingGetMoSmsBearer:
       
   900 		// FALLTHRU
       
   901 	default:
       
   902 		User::Leave(KErrNotSupported);
       
   903 		break;
       
   904 		}
       
   905 
       
   906 	return ret;
       
   907 	}
       
   908 
       
   909 TInt CSimSmsMessaging::RegisterNotification(const TInt /*aIpc*/)
       
   910 /**
       
   911 	The ETel Server calls this function when the first client makes a notification
       
   912 	request.  If supported by the underlying protocol controlling the
       
   913 	signalling stack, this can be used to start requesting updates for the relevant
       
   914 	service.
       
   915 */
       
   916 	{
       
   917 	return KErrNone;
       
   918 	}
       
   919 
       
   920 TInt CSimSmsMessaging::DeregisterNotification(const TInt /*aIpc*/)
       
   921 /**
       
   922 	The ETel Server calls this function when the last client that had previously
       
   923 	made a notification request closes its ETel Server handle.  If supported by
       
   924 	the underlying protocol controlling the	signalling stack, this can be used
       
   925 	to stop requesting updates for the relevant service.
       
   926 */
       
   927 	{
       
   928 	return KErrNone;
       
   929 	}
       
   930 
       
   931 TInt CSimSmsMessaging::NumberOfSlotsL(const TInt /*aIpc*/)
       
   932 /**
       
   933  * Return the number of slots that the ETel Server should allocate for buffering requests
       
   934  * of the given IPC number.
       
   935  */
       
   936 	{
       
   937 	return KDefaultNumberOfSlots;
       
   938 	}
       
   939 
       
   940 TInt CSimSmsMessaging::CancelService(const TInt aIpc,const TTsyReqHandle /*aTsyReqHandle*/)
       
   941 /**
       
   942  * Cancel an outstanding request.
       
   943  */
       
   944 	{
       
   945 	switch(aIpc)
       
   946 		{
       
   947 	case EMobileSmsMessagingReceiveMessage:
       
   948 		ReceiveMessageCancel();
       
   949 		break;
       
   950 	case EMobileSmsMessagingSendMessage:
       
   951 		SendMessageCancel();
       
   952 		break;
       
   953 	case EMobileSmsMessagingGetSmspListPhase1:
       
   954 		StoreSmspListCancel();
       
   955 		break;
       
   956 	case EMobileSmsMessagingStoreSmspList:
       
   957 		GetSmspListCancel();
       
   958 		break;
       
   959 	case EMobileSmsMessagingAckSmsStored:
       
   960 	case EMobileSmsMessagingNackSmsStored:
       
   961 		AckNackCancel();
       
   962 		break;
       
   963 	case EMobileSmsMessagingResumeSmsReception:
       
   964 		ResumeSmsReceptionCancel();
       
   965 		break;
       
   966 // These are actually implemented in a synchronous manner, so there's no cancel to perform.
       
   967 	case EMobileSmsMessagingSetReceiveMode:
       
   968 	case EMobileSmsMessagingGetReceiveMode:	
       
   969 		break;
       
   970 	default:
       
   971 		break;
       
   972 		}
       
   973 	return KErrNone;
       
   974 	}
       
   975 
       
   976 void CSimSmsMessaging::Init()
       
   977 /**
       
   978 	This function can be used to perform any necessary synchronous initialisation.
       
   979 */
       
   980 	{
       
   981 	}
       
   982 
       
   983 TBool CSimSmsMessaging::CanStartRxEvent() const
       
   984 /** Check to see if the Rx event can be started. Conditions are that there are no constraints
       
   985  * and Rx PDUs have been defined, OR SMS messages have been sent and current constraint has 
       
   986  * not ellapsed
       
   987  * @return ETrue if the Rx event can be started
       
   988  */ 
       
   989 	{
       
   990 	TBool canStart = EFalse;
       
   991 	if( (iConstraints.Count()==0 && iSmsRxParameterListGsm->Count()>0) ||
       
   992 		(iConstraints.Count()>0 && (iSmsTxCnt == iConstraints[iCurrentConstraint].iIpcCnt) && !ConstraintEllapsed()) )
       
   993 		{
       
   994 		// No Constraints listed OR current constraint has not ellapsed
       
   995 		canStart = ETrue;
       
   996 		}
       
   997 	return canStart;	
       
   998 	}
       
   999 
       
  1000 TInt CSimSmsMessaging::ActionRxEventUnstoredClientAck(TSmsRxEvent aRxEvent)
       
  1001 /**
       
  1002  *	This function, triggered by sms receive events, manages the stated machine of 
       
  1003  *  receiving Unstored clientacked sms messages
       
  1004  *  
       
  1005  */
       
  1006 	{
       
  1007 	LOGSMS3(">>CSimSmsMessaging::ActionRxEventUnstoredClientAck [iRxState=%d aRxEvent=%d]", iRxState, aRxEvent);
       
  1008 	switch(iRxState)
       
  1009 		{
       
  1010 	case ESmsRxStateIdle:
       
  1011 		{
       
  1012 		if(aRxEvent==ESmsEventPostedRxReq)
       
  1013 			{
       
  1014 			iRxState=ESmsRxStateWaitingForSmsRx;
       
  1015 			if( CanStartRxEvent() )
       
  1016 				{
       
  1017 				// Start the Rx timer to simulate received SMS from network
       
  1018 				StartSmsMtTimer();	
       
  1019 				}
       
  1020 			return KErrNone;
       
  1021 			}
       
  1022 		return KErrGeneral;
       
  1023 		}
       
  1024 	case ESmsRxStateWaitingForSmsRx:
       
  1025 		{
       
  1026 		if(aRxEvent==ESmsEventRxTimer )
       
  1027 			{
       
  1028 			iRxState=ESmsRxStateWaitingForAckNack;
       
  1029 			TInt ret = AttemptSmsRxComplete();	//If successful Etel will repost the request and the state machine may be re-entered
       
  1030 			return ret;
       
  1031 			}
       
  1032 		return KErrGeneral;
       
  1033 		} 
       
  1034 	case ESmsRxStateWaitingForAckNack:
       
  1035 		{
       
  1036 		__ASSERT_ALWAYS(aRxEvent!=ESmsEventRxTimer,SimPanic(EIllegalSmsRxEvent, __LINE__));
       
  1037 		if(aRxEvent==ESmsEventRxAckNack)
       
  1038 			{
       
  1039 			iRxState=ESmsRxStateWaitingForNetworkAckNackResponse;
       
  1040 			if (!iRxTimer->IsActive() && !iRxTimer->Running())
       
  1041 				{
       
  1042 				LOGSMS1(">>CSimSmsMessaging::ActionRxEventUnstoredClientAck Starting Rx Timer");
       
  1043 				iRxTimer->Start(iAckNackCompletePause,this, ETimerIdSmsMessRx);
       
  1044 				}
       
  1045 
       
  1046 			return KErrNone;
       
  1047 			}
       
  1048 		else if(aRxEvent==ESmsEventResume)
       
  1049 			{
       
  1050 			return KErrGeneral;
       
  1051 			}
       
  1052 		} break;
       
  1053 	case ESmsRxStateWaitingForNetworkAckNackResponse:
       
  1054 		if(aRxEvent==ESmsEventRxTimer)
       
  1055 			{
       
  1056 			if(iSmsStoreFull)
       
  1057 				iRxState=ESmsRxStateSuspend;
       
  1058 			else if(iSmsRxReqOutstanding)
       
  1059 				{
       
  1060 				iRxState=ESmsRxStateWaitingForSmsRx;
       
  1061 				StartSmsMtTimer();
       
  1062 				}
       
  1063 			else
       
  1064 				{
       
  1065 				iRxState=ESmsRxStateIdle;
       
  1066 				StartSmsMtTimer();
       
  1067 				}
       
  1068 			CompletePendingReq();
       
  1069 			return KErrNone;
       
  1070 			}
       
  1071 		if(aRxEvent==ESmsEventPostedRxReq)
       
  1072 			return KErrNone;
       
  1073 		return KErrGeneral;
       
  1074 	case ESmsRxStateSuspend:
       
  1075 		{
       
  1076 		__ASSERT_ALWAYS(aRxEvent!=ESmsEventRxTimer,SimPanic(EIllegalSmsRxEvent, __LINE__));
       
  1077 		if(aRxEvent==ESmsEventResume)
       
  1078 			{
       
  1079 			iRxState=ESmsRxStateWaitingForNetworkResumeResponse;
       
  1080 			iRxTimer->Start(iResumeCompletePause,this, ETimerIdSmsMessResumeReception);
       
  1081 			return KErrNone;
       
  1082 			}
       
  1083 		return KErrGeneral;
       
  1084 		}
       
  1085 	case ESmsRxStateWaitingForNetworkResumeResponse:
       
  1086 		{
       
  1087 		if(aRxEvent==ESmsEventPostedRxReq)
       
  1088 			return KErrNone;
       
  1089 		return KErrGeneral;
       
  1090 		}
       
  1091 	default:
       
  1092 		return KErrGeneral;
       
  1093 		}
       
  1094 	return KErrNone;
       
  1095 	}
       
  1096 
       
  1097 TInt CSimSmsMessaging::ActionRxEventUnstoredPhoneAck(TSmsRxEvent aRxEvent)
       
  1098 /**
       
  1099  *	This function, triggered by sms receive events, manages the stated machine of 
       
  1100  *  receiving Unstored Phone acked sms messages
       
  1101  *  
       
  1102  */
       
  1103 	{
       
  1104 	LOGSMS3(">> ActionRxEventUnstoredPhoneAck Enter function. Event=%d, State=%d",aRxEvent,iRxState);
       
  1105 	
       
  1106 	TInt ret = KErrGeneral;
       
  1107 	
       
  1108 	switch(iRxState)
       
  1109 		{
       
  1110 	case ESmsRxStateIdle:
       
  1111 		{
       
  1112 		if(aRxEvent==ESmsEventPostedRxReq)
       
  1113 			{
       
  1114 			iRxState=ESmsRxStateWaitingForSmsRx;
       
  1115 			if( CanStartRxEvent() )
       
  1116 				{
       
  1117 				// Start the Rx timer to simulate received SMS from network
       
  1118 				StartSmsMtTimer();	
       
  1119 				}
       
  1120 			ret = KErrNone;
       
  1121 			}
       
  1122 		} break;
       
  1123 	case ESmsRxStateWaitingForSmsRx:
       
  1124 		{
       
  1125 		if(aRxEvent==ESmsEventRxTimer )
       
  1126 			{
       
  1127 			iRxState=ESmsRxStateIdle;
       
  1128 			ret = AttemptSmsRxComplete();	//If successful Etel will repost the request and the state machine may be re-entered
       
  1129 			}
       
  1130 		} break; 
       
  1131 	default: 
       
  1132 		// Do nothing - return default value of KErrGeneral
       
  1133 		break;
       
  1134 		}
       
  1135 	return ret;
       
  1136 	}
       
  1137 
       
  1138 TInt CSimSmsMessaging::ActionRxEventStored(TSmsRxEvent aRxEvent)
       
  1139 /**
       
  1140  *	This function, triggered by sms receive events, manages the stated machine of 
       
  1141  *  receiving stored Phone acked  sms messages
       
  1142  *  
       
  1143  */
       
  1144 	{
       
  1145 	LOGSMS3(">> ActionRxEventStored Enter function. Event=%d, State=%d",aRxEvent,iRxState);
       
  1146 	TInt ret = KErrGeneral;
       
  1147 	
       
  1148 	switch(iRxState)
       
  1149 		{
       
  1150 	case ESmsRxStateIdle:
       
  1151 		{
       
  1152 		if(aRxEvent==ESmsEventPostedRxReq)
       
  1153 			{
       
  1154 			iRxState=ESmsRxStateWaitingForSmsRx;
       
  1155 			if( CanStartRxEvent() )
       
  1156 				{
       
  1157 				// Start the Rx timer to simulate received SMS from network
       
  1158 				StartSmsMtTimer();	
       
  1159 				}
       
  1160 			ret = KErrNone;
       
  1161 			}
       
  1162 		} break;
       
  1163 	case ESmsRxStateWaitingForSmsRx:
       
  1164 		{
       
  1165 		if(aRxEvent==ESmsEventRxTimer )
       
  1166 			{
       
  1167 			iRxState=ESmsRxStateIdle;
       
  1168 			ret = AttemptSmsRxComplete();	//If successful Etel will repost the request and the state machine may be re-entered
       
  1169 			if( ret != KErrNone )
       
  1170 				{
       
  1171 				//the message wasn't stored ->ignore it and re-run the network event
       
  1172 				iRxState=ESmsRxStateWaitingForSmsRx;
       
  1173 				StartSmsMtTimer();
       
  1174 				}
       
  1175 			ret = KErrNone;	
       
  1176 			}
       
  1177 		} break; 
       
  1178 	default: 
       
  1179 		// Do nothing - return default value of KErrGeneral
       
  1180 		break;
       
  1181 		}
       
  1182 	return ret;
       
  1183 	}
       
  1184 
       
  1185 TInt CSimSmsMessaging::ReceiveMessageL(const TTsyReqHandle aReqHandle, TDes8* aSmsPdu, TDes8* aParam2)
       
  1186 /**
       
  1187  * Process a Receive Message request.  This boils down to recording the parameters for later completion.
       
  1188  * The mode of operation where first an SMS receive request is made and then later an SMS
       
  1189  * receive event is simulated is supported.  If an SMS receive event is simulated and there is
       
  1190  * no receive request outstanding, the simulated incoming SMS will be discarded.  This assumption
       
  1191  * may need to be revisited later.
       
  1192  */
       
  1193 	{
       
  1194 	if (iSmsRxReqOutstanding!=EFalse)//Check if another client posts the request
       
  1195 		{
       
  1196 		ReqCompleted(aReqHandle, KErrInUse);
       
  1197 		return KErrNone;
       
  1198 		}
       
  1199 	iSmsRxReqHandle=aReqHandle;
       
  1200 	iSmsRxPdu=aSmsPdu;
       
  1201 	RMobileSmsMessaging::TMobileSmsReceiveAttributesV1Pckg* aAttribPckg=(RMobileSmsMessaging::TMobileSmsReceiveAttributesV1Pckg*)aParam2;
       
  1202 	RMobileSmsMessaging::TMobileSmsReceiveAttributesV1& attrib=(*aAttribPckg)();
       
  1203 
       
  1204 	// Check that the data structure is supported by the simulated TSY version
       
  1205 	TInt err = iPhone->CheckSimTsyVersion(attrib);
       
  1206 	if(err != KErrNone)
       
  1207 		{
       
  1208 		iPhone->ReqCompleted(aReqHandle, err);
       
  1209 		return KErrNone;
       
  1210 		}
       
  1211 
       
  1212 	iSmsRxAttrib=&attrib;
       
  1213 	iSmsRxReqOutstanding=ETrue;
       
  1214 	LOGSMS3(">>ReceiveMessageL. aSmsPdu&=%x, aParam2&=%x",aSmsPdu,iSmsRxAttrib);
       
  1215 	
       
  1216 	//  Print received PDU to simTSY log.
       
  1217 	__ASSERT_ALWAYS(iSmsReceiveMode!=RMobileSmsMessaging::EReceiveModeUnspecified,SimPanic(EMobileSmsMessagingPhoneNotSetToAReceiveMode));
       
  1218 	TInt ret=0;
       
  1219 	switch (iSmsReceiveMode)//swich which state machine to enter
       
  1220 		{
       
  1221 	case RMobileSmsMessaging::EReceiveUnstoredClientAck:
       
  1222 		ret=ActionRxEventUnstoredClientAck(ESmsEventPostedRxReq);
       
  1223 		break;
       
  1224 	case RMobileSmsMessaging::EReceiveUnstoredPhoneAck:
       
  1225 		ret=ActionRxEventUnstoredPhoneAck(ESmsEventPostedRxReq);
       
  1226 		break;
       
  1227 	case RMobileSmsMessaging::EReceiveStored:
       
  1228 		ret=ActionRxEventStored(ESmsEventPostedRxReq);
       
  1229 		break;
       
  1230 	default:
       
  1231 		ret=KErrNotSupported;
       
  1232 		}//end switch
       
  1233 
       
  1234 	if(ret==KErrNone)
       
  1235 		{
       
  1236 		
       
  1237 		}
       
  1238 	else
       
  1239 		ReqCompleted(aReqHandle,ret);
       
  1240 	return KErrNone;
       
  1241 	}
       
  1242 
       
  1243 void CSimSmsMessaging::ReceiveMessageCancel()
       
  1244 /*
       
  1245  * Cancel an outstanding Receive Message request.
       
  1246  */
       
  1247 	{
       
  1248 	if(iSmsRxReqOutstanding)
       
  1249 		{
       
  1250 		iSmsRxReqOutstanding=EFalse;
       
  1251 		iRxState=ESmsRxStateIdle;
       
  1252 		ReqCompleted(iSmsRxReqHandle,KErrCancel);
       
  1253 		}
       
  1254 	}
       
  1255 
       
  1256 TInt CSimSmsMessaging::AckSmsStored(const TTsyReqHandle aReqHandle,TDes8* aMsg,TDes8* aFullFlagPckg)
       
  1257 /**
       
  1258  *	In response to an incoming sms message the sms stack Acks/Nacks the message
       
  1259  *  This function implements the Ack action.
       
  1260  *  The flag aFullFlagPckg if set informs the SC that the client has no space to store this message
       
  1261  *  and hence that it should retry once instructed by the ME
       
  1262  */
       
  1263 	{
       
  1264 	TPckg<TBool>* fullFlagPckg=(TPckg<TBool>*)aFullFlagPckg;
       
  1265 	TBool& fullFlag=(*fullFlagPckg)();
       
  1266 
       
  1267 	//  SMS-DELIVER-REPORT TPDU check 
       
  1268 	_LIT8(emptyDesc,"");
       
  1269 	if(aMsg->Compare(emptyDesc) != KErrNone)
       
  1270 		{
       
  1271 		RMobileSmsMessaging::TMobileSmsGsmTpdu reportPdu;
       
  1272 		reportPdu.Zero();
       
  1273 		if (CSimTsyMode::GetMode() != CSimTsyMode::ECdmaV1)
       
  1274   			{
       
  1275  			reportPdu = iSmsRxParameterListGsm->At(iSmsRxCnt-1).iDeliveryReport;
       
  1276   			}
       
  1277 
       
  1278 					
       
  1279 		if (reportPdu.Length() > 0)	// check if SMS-DELIVER-REPORT TPDU in config file is present
       
  1280 			{
       
  1281 			if(aMsg->Match(reportPdu)!=0)//check if the transmitted pdu and the one in config file are not identical
       
  1282 				{
       
  1283 				ReqCompleted(aReqHandle,KErrCorrupt);
       
  1284 				return KErrNone;
       
  1285 				}
       
  1286 			}
       
  1287 		}
       
  1288 
       
  1289 	iSmsStoreFull=fullFlag;		// Record the "Store Full" status for future state transitions.
       
  1290 	TInt ret=ActionRxEventUnstoredClientAck(ESmsEventRxAckNack);
       
  1291 
       
  1292 	// Handle any state transition errors now.  Simulated Ack/Nack failures are not supported yet...
       
  1293 	if(ret!=KErrNone)
       
  1294 		{
       
  1295 		ReqCompleted(aReqHandle,ret);
       
  1296 		return KErrNone;
       
  1297 		}
       
  1298 	iPendingReqHandle=aReqHandle;
       
  1299 	return KErrNone;
       
  1300 	}
       
  1301 
       
  1302 TInt CSimSmsMessaging::NackSmsStored(const TTsyReqHandle aReqHandle,TDes8* aMsg,TDes8* aRpCausePckg)
       
  1303 /**
       
  1304  *	In response to an incoming sms message the sms stack Acks/Nacks the message
       
  1305  *  This function implements the NAck action.
       
  1306  *  aRpCausePckg must be filled in with the reason
       
  1307  */
       
  1308 	{
       
  1309 	TPckg<TInt>* rpCausePckg=(TPckg<TInt>*)aRpCausePckg;
       
  1310 	TInt& rpCause=(*rpCausePckg)();
       
  1311 
       
  1312 	//  SMS-DELIVER-REPORT TPDU check 
       
  1313 	_LIT8(emptyDesc,"");
       
  1314 	if(aMsg->Compare(emptyDesc) != KErrNone)
       
  1315 		{
       
  1316 		RMobileSmsMessaging::TMobileSmsGsmTpdu reportPdu;
       
  1317 		reportPdu.Zero();
       
  1318 		if (CSimTsyMode::GetMode() != CSimTsyMode::ECdmaV1)
       
  1319   			{
       
  1320   			reportPdu = iSmsRxParameterListGsm->At(iSmsRxCnt-1).iDeliveryReport;
       
  1321   			}
       
  1322 
       
  1323 			
       
  1324 		if (reportPdu.Length() > 0)	// check if SMS-DELIVER-REPORT TPDU in config file is present
       
  1325 			{
       
  1326 			if(aMsg->Match(reportPdu)!=0)//check if the transmitted pdu and the one in config file are not identical
       
  1327 				{
       
  1328 				ReqCompleted(aReqHandle,KErrCorrupt);
       
  1329 				return KErrNone;
       
  1330 				}
       
  1331 			}
       
  1332 		}
       
  1333 
       
  1334 	if(rpCause==KErrGsmSMSMemoryCapacityExceeded)
       
  1335 		iSmsStoreFull=ETrue;
       
  1336 	else
       
  1337 		iSmsStoreFull=EFalse;
       
  1338 
       
  1339 	TInt ret=ActionRxEventUnstoredClientAck(ESmsEventRxAckNack);
       
  1340 
       
  1341 	// Handle any state transition errors now.  Simulated Ack/Nack failures are not supported yet...
       
  1342 	if(ret!=KErrNone)
       
  1343 		{
       
  1344 		ReqCompleted(aReqHandle,ret);
       
  1345 		return KErrNone;
       
  1346 		}
       
  1347 
       
  1348 	iPendingReqHandle=aReqHandle;
       
  1349 	return KErrNone;
       
  1350 	}
       
  1351 
       
  1352 
       
  1353 void CSimSmsMessaging::AckNackCancel()
       
  1354 /*
       
  1355  * Cancel an outstanding Receive Message request.
       
  1356  */
       
  1357 	{
       
  1358 	//This method does nothing,, a complex implementation would have to be used to simulate a real tsy
       
  1359 	}
       
  1360 
       
  1361 
       
  1362 TInt CSimSmsMessaging::ResumeSmsReception(const TTsyReqHandle aReqHandle)
       
  1363 /**
       
  1364  *  After the sms reception has been suspended(store full), if the client frees some space
       
  1365  *  the ME will inform the SC that reception can resume
       
  1366  *
       
  1367  */
       
  1368 	{
       
  1369 	TInt ret=ActionRxEventUnstoredClientAck(ESmsEventResume);
       
  1370 // In case of state transition error, return the error code.
       
  1371 // Resume failures cannot be simulated by the tsy yet...
       
  1372 	if(ret!=KErrNone)
       
  1373 		{
       
  1374 		ReqCompleted(aReqHandle,ret);
       
  1375 		return KErrNone;
       
  1376 		}
       
  1377 	iPendingReqHandle=aReqHandle;
       
  1378 	return KErrNone;
       
  1379 	}
       
  1380 
       
  1381 void CSimSmsMessaging::ResumeSmsReceptionCancel()
       
  1382 	{
       
  1383 	//Does nothing, a complex implementation would have to be used to simulate a real tsy
       
  1384 	}
       
  1385 
       
  1386 //**********************************************
       
  1387 //send
       
  1388 //*********************************************
       
  1389 
       
  1390 
       
  1391 TInt CSimSmsMessaging::ActionTxEvent(TSmsTxEvent aTxEvent)
       
  1392 /**
       
  1393  *  This function actions the sms message sending state machine. It is triggered by sms sending events
       
  1394  *
       
  1395  */
       
  1396 	{
       
  1397 	LOGSMS1(">>ActionTxEvent ");
       
  1398 	switch(iTxState)
       
  1399 	{
       
  1400 	case ESmsTxStateIdle:
       
  1401 		__ASSERT_ALWAYS(aTxEvent!=ESmsEventSubmitReportReceived,SimPanic(EIllegalSmsTxEvent));
       
  1402 		if(aTxEvent==ESmsEventSendReq)
       
  1403 			{
       
  1404 			iTxState=ESmsTxStateWaitingForSubmitReport;
       
  1405 			iTxTimer->Start(iSmsTxPause,this, ETimerIdSmsMessTx);
       
  1406 			}
       
  1407 		break;
       
  1408 	case ESmsTxStateWaitingForSubmitReport:
       
  1409 		__ASSERT_ALWAYS(aTxEvent!=ESmsEventSendReq,SimPanic(EIllegalSmsTxEvent));	
       
  1410 		if(aTxEvent==ESmsEventSubmitReportReceived)
       
  1411 			{
       
  1412 			iTxState=ESmsTxStateIdle;
       
  1413 
       
  1414 			PopulateSmsTxAttrib(iSmsTxAttrib);				
       
  1415 			CompleteTxPendingReq(KErrNone);			
       
  1416 			}
       
  1417 		break;
       
  1418 	}
       
  1419 	return KErrNone;
       
  1420 	}
       
  1421 
       
  1422 TInt CSimSmsMessaging::SendMessageL(const TTsyReqHandle aReqHandle,TDes8* aSmsPdu,TDes8* aParam2)
       
  1423 /**
       
  1424  *	This function simulates the transmission of an sms from the ME to the SC.
       
  1425  *  It returns directly if 
       
  1426  *  -The Sms message description(SmsTx)tag in the config file specifies that this sms message should return with this error 
       
  1427  *  -The Pdu is corrupted
       
  1428  *  Otherwise it start the sms message sending state machine
       
  1429  * 
       
  1430  */
       
  1431 
       
  1432 	{
       
  1433     iSmsTxReqHandle=aReqHandle;
       
  1434     RMobileSmsMessaging::TMobileSmsSendAttributesV1Pckg* aAttribPckg=(RMobileSmsMessaging::TMobileSmsSendAttributesV1Pckg*)aParam2;
       
  1435 	RMobileSmsMessaging::TMobileSmsSendAttributesV1& attrib=(*aAttribPckg)();
       
  1436 		
       
  1437 	// Check that the data structure is supported by the simulated TSY version
       
  1438 	TInt err = iPhone->CheckSimTsyVersion(attrib);
       
  1439 	if(err != KErrNone)
       
  1440 		{
       
  1441 		iPhone->ReqCompleted(aReqHandle, err);
       
  1442 		return KErrNone;
       
  1443 		}
       
  1444 		
       
  1445 	iSmsTxAttrib=&attrib;
       
  1446 #ifdef _DEBUG
       
  1447 		LogTMobileSmsAttributesV1(*iSmsTxAttrib);
       
  1448 #endif // _DEBUG
       
  1449 		
       
  1450 
       
  1451 	//check if messages defined in cfg file
       
  1452 	TInt count = 0;	
       
  1453 	count = iSmsTxParametersListGsm->Count();  
       
  1454 	
       
  1455 	if (count<=iSmsTxCnt)
       
  1456 		return KErrTotalLossOfPrecision;
       
  1457 
       
  1458 	//check if expected error
       
  1459 	//TInt err = KErrNone;
       
  1460 	err = KErrNone;
       
  1461 	err = iSmsTxParametersListGsm->At(iSmsTxCnt).iExpectedError;		
       
  1462 	if (err!=KErrNone)
       
  1463 		{
       
  1464 		PopulateSmsTxAttrib(iSmsTxAttrib);			
       
  1465 		CompleteTxPendingReq(err);
       
  1466 		return KErrNone;
       
  1467 		}
       
  1468 
       
  1469 		//check if a non null pdu is defined in the config file
       
  1470 	RMobileSmsMessaging::TMobileSmsGsmTpdu octetPdu;
       
  1471 	octetPdu = iSmsTxParametersListGsm->At(iSmsTxCnt).iPdu;
       
  1472 
       
  1473 	RMobileSmsMessaging::TMobileSmsGsmTpdu pduWith0;
       
  1474 	TUint8 zero=0;
       
  1475 	pduWith0.Append(&zero, 1);
       
  1476 	if(octetPdu!=pduWith0)//if the pdu in config file is 00, skip the pdu check
       
  1477 		{
       
  1478 			if(aSmsPdu->Match(octetPdu)!=0)//check if the transmitted pdu and the one in config file are identical
       
  1479 				{
       
  1480 				CompleteTxPendingReq(KErrCorrupt);
       
  1481 				return KErrNone;
       
  1482 				}
       
  1483 		}	
       
  1484 
       
  1485 	ActionTxEvent(ESmsEventSendReq);
       
  1486 	return KErrNone;
       
  1487 	}
       
  1488 
       
  1489 
       
  1490 void CSimSmsMessaging::SendMessageCancel()
       
  1491 /*
       
  1492  * Cancel an outstanding send Message request.
       
  1493  */
       
  1494 	{
       
  1495 	if(iTxState==ESmsTxStateWaitingForSubmitReport)
       
  1496 		{
       
  1497 		iTxTimer->Cancel();
       
  1498 		iTxState=ESmsTxStateIdle;
       
  1499 		CompleteTxPendingReq(KErrCancel);
       
  1500 		}
       
  1501 	}
       
  1502 
       
  1503 void CSimSmsMessaging::CompletePendingReq()
       
  1504 	{
       
  1505 	ReqCompleted(iPendingReqHandle,KErrNone);
       
  1506 	}
       
  1507 
       
  1508 TInt CSimSmsMessaging::AttemptSmsRxComplete()
       
  1509 /**
       
  1510  * Complete an outstanding SMS message receive request if one is outstanding.  If there is
       
  1511  * no request outstanding, the message will be discared.
       
  1512  * update the constraint count
       
  1513  */
       
  1514 	{
       
  1515 	LOGSMS1(">>AttemptSmsRxComplete ");
       
  1516 
       
  1517 	if (CSimTsyMode::GetMode() != CSimTsyMode::ECdmaV1)
       
  1518 		{
       
  1519 		iConstraintRxCnt++;
       
  1520 		}
       
  1521 
       
  1522 	TInt ret=KErrNone;
       
  1523 	if(iSmsRxReqOutstanding)
       
  1524 		{
       
  1525 		if (iSmsReceiveMode==RMobileSmsMessaging::EReceiveStored)
       
  1526 			{
       
  1527 			LOGSMS4(">>Populating SMS Structures. iSmsRxPdu&=%x, iSmsRxAttrib&=%x, iSmsRxCnt=%d.",iSmsRxPdu,iSmsRxAttrib,iSmsRxCnt);
       
  1528 			RMobileSmsStore::TMobileGsmSmsEntryV1 sms;
       
  1529 
       
  1530 			*iSmsRxPdu=iSmsRxParameterListGsm->At(iSmsRxCnt).iPdu;
       
  1531 			
       
  1532 			sms.iMsgData=RMobileSmsMessaging::TMobileSmsGsmTpdu(*iSmsRxPdu);
       
  1533 			sms.iServiceCentre.iTelNumber.Copy(iSmsRxParameterListGsm->At(iSmsRxCnt).iSca);
       
  1534 		
       
  1535 			sms.iServiceCentre.iTypeOfNumber=RMobilePhone::EInternationalNumber;//SmsMessaging only deals with international numbers
       
  1536 			sms.iServiceCentre.iNumberPlan=RMobilePhone::EIsdnNumberPlan;
       
  1537 			sms.iMsgStatus=RMobileSmsStore::EStoredMessageUnread;
       
  1538 			ret = iSmsStores->At(0)->StoreIncomingMessage(&sms);//todo if several stores find the right one
       
  1539 			if (ret==KErrNone)
       
  1540 				{
       
  1541 				iSmsRxAttrib->iStore.Copy(iSmsStores->At(0)->Name());
       
  1542 				iSmsRxAttrib->iStoreIndex=sms.iIndex;
       
  1543 				}
       
  1544 			}
       
  1545 		else
       
  1546 			{			
       
  1547 			*iSmsRxPdu = iSmsRxParameterListGsm->At(iSmsRxCnt).iPdu;				
       
  1548 			}
       
  1549 
       
  1550 		if (ret==KErrNone)
       
  1551 			{
       
  1552 			iSmsRxReqOutstanding=EFalse;			
       
  1553 			PopulateSmsRxAttrib(iSmsRxParameterListGsm->At(iSmsRxCnt).iSca,iSmsRxAttrib);	
       
  1554 							
       
  1555 			ReqCompleted(iSmsRxReqHandle,ret);
       
  1556 			iSmsRxCnt++;
       
  1557 			}
       
  1558 		}
       
  1559 	return ret;
       
  1560 	}
       
  1561 
       
  1562 void CSimSmsMessaging::CompleteTxPendingReq(TInt aError)
       
  1563 /**
       
  1564  * Complete a SmsTx request and increments the SmsTx counter
       
  1565  *
       
  1566  */
       
  1567 	{
       
  1568 	LOGSMS1(">>CompleteTxPendingReq ");
       
  1569 	iSmsTxCnt++;
       
  1570 	if(IpcMatch())
       
  1571 		{
       
  1572 		iConstraintRxCnt=0;
       
  1573 		if( iSmsRxReqOutstanding )
       
  1574 			{
       
  1575 			// Client has a pending receive request - safe to start Rx timer
       
  1576 			// to simulate received SMS from network.
       
  1577 			StartSmsMtTimer();
       
  1578 			}
       
  1579 		else
       
  1580 			{
       
  1581 			// No pending client receive request - need to wait for it before
       
  1582 			// simulating received SMS from network.
       
  1583 			LOGSMS1(" - no pending receive req from client - do not start Rx timer");
       
  1584 			}
       
  1585 		}
       
  1586 	ReqCompleted(iSmsTxReqHandle, aError);
       
  1587 	}
       
  1588 
       
  1589 void CSimSmsMessaging::StartSmsMtTimer()
       
  1590 	{
       
  1591 	LOGSMS1(">>StartSmsMtTimer ");
       
  1592 	TInt count = 0;
       
  1593 	count = iSmsRxCnt<iSmsRxParameterListGsm->Count();
       
  1594 			
       
  1595 		if(count)		// Check that there are more messages defined in the config file.
       
  1596 			{
       
  1597 			if((iConstraints.Count()==0) ||	(iConstraintRxCnt<iConstraints[iCurrentConstraint].iRxCnt))	// If there are no constraints, or there are constraints and they're not exhausted.
       
  1598 				{
       
  1599 				LOGSMS1(">>StartSmsMtTimer Starting");
       
  1600 				iRxTimer->Start(iSmsRxPeriod,this, ETimerIdSmsMessRx);
       
  1601 				LOGSMS1(">>StartSmsMtTimer Started");
       
  1602 				}
       
  1603 			}
       
  1604 	}
       
  1605 
       
  1606 
       
  1607 void CSimSmsMessaging::PopulateSmsRxAttrib(const TDesC8& aAsciiScaAddr,RMobileSmsMessaging::TMobileSmsReceiveAttributesV1* aAttrib)
       
  1608 /**
       
  1609  * Populate the SMS Rx Attributes from an ASCII respresentation, such as that stored in the configuration file.
       
  1610  * This involves checking the address for a leading '+' character and setting the TON and NPI
       
  1611  * accordingly.  The address can then be copied into the iTelNumber structure.
       
  1612  */
       
  1613 	{
       
  1614 	LOGSMS1(">>PopulateSmsRxAttrib, ");
       
  1615 	aAttrib->iOriginator.iTelNumber.SetLength(0);
       
  1616 	
       
  1617 	switch (iSmsReceiveMode)
       
  1618 		{
       
  1619 	case RMobileSmsMessaging::EReceiveUnstoredClientAck:
       
  1620 		aAttrib->iStatus=RMobileSmsMessaging::EMtMessageUnstoredClientAck;
       
  1621 		aAttrib->iStore.SetLength(0);
       
  1622 		aAttrib->iStoreIndex=-1;
       
  1623 		break;
       
  1624 	case RMobileSmsMessaging::EReceiveUnstoredPhoneAck:
       
  1625 		aAttrib->iStatus=RMobileSmsMessaging::EMtMessageUnstoredPhoneAck;
       
  1626 		aAttrib->iStore.SetLength(0);
       
  1627 		aAttrib->iStoreIndex=-1;
       
  1628 		break;
       
  1629 	case RMobileSmsMessaging::EReceiveStored:
       
  1630 		aAttrib->iStatus=RMobileSmsMessaging::EMtMessageStored;
       
  1631 		break;
       
  1632 	
       
  1633 	default:
       
  1634 		break;
       
  1635 		}
       
  1636 	aAttrib->iFlags=RMobileSmsMessaging::KGsmServiceCentre | RMobileSmsMessaging::KSmsDataFormat | RMobileSmsMessaging::KIncomingStatus;
       
  1637 	aAttrib->iDataFormat=RMobileSmsMessaging::EFormatGsmTpdu;
       
  1638 
       
  1639 	if(aAsciiScaAddr.Length()>0)
       
  1640 		{
       
  1641 		aAttrib->iGsmServiceCentre.iNumberPlan=RMobilePhone::EIsdnNumberPlan;
       
  1642 		aAttrib->iGsmServiceCentre.iTypeOfNumber=RMobilePhone::EInternationalNumber;
       
  1643 		aAttrib->iGsmServiceCentre.iTelNumber.Copy(aAsciiScaAddr);
       
  1644 		}
       
  1645 	}
       
  1646 
       
  1647 
       
  1648 void CSimSmsMessaging::PopulateSmsTxAttrib(RMobileSmsMessaging::TMobileSmsAttributesV1* aAttrib)
       
  1649 /**
       
  1650  * Populate the SMS Tx Attributes for SMS from an ASCII respresentation, such as that stored in the configuration file.
       
  1651  * - Message Identifier
       
  1652  * - TL Ack
       
  1653  */
       
  1654 	{
       
  1655 	if (iSmsModeCaps == RMobileSmsMessaging::KCapsGsmSms)
       
  1656 		{
       
  1657 		RMobileSmsMessaging::TMobileSmsSendAttributesV1* attrib = static_cast<RMobileSmsMessaging::TMobileSmsSendAttributesV1*>(aAttrib);
       
  1658 		attrib->iMsgRef = TUint16(iSmsTxParametersListGsm->At(iSmsTxCnt).iRef);	
       
  1659 
       
  1660 		attrib->iFlags = RMobileSmsMessaging::KMessageReference;
       
  1661 		
       
  1662 		if (iSmsControlCaps & RMobileSmsMessaging::KCapsSendWithAck)
       
  1663 			{			
       
  1664 			attrib->iSubmitReport=iSmsTxParametersListGsm->At(iSmsTxCnt).iSubmitReport;
       
  1665 			attrib->iFlags |= RMobileSmsMessaging::KGsmSubmitReport;
       
  1666 			}
       
  1667 		}
       
  1668 	}
       
  1669 
       
  1670 void CSimSmsMessaging::PopulateSmsTxAttrib(RMobileSmsMessaging::TMobileSmsSendAttributesV1* aAttrib)
       
  1671 /**
       
  1672  * Populate the SMS Tx Attributes from an ASCII respresentation, such as that stored in the configuration file.
       
  1673  * -Message Reference
       
  1674  * -SUBMIT_REPORT_TPDU
       
  1675  */
       
  1676 	{
       
  1677 	 aAttrib->iMsgRef = TUint16(iSmsTxParametersListGsm->At(iSmsTxCnt).iRef);
       
  1678 	 aAttrib->iFlags = RMobileSmsMessaging::KMessageReference;
       
  1679 	
       
  1680 	 if (iSmsControlCaps & RMobileSmsMessaging::KCapsSendWithAck)
       
  1681 		{
       
  1682 		aAttrib->iSubmitReport=iSmsTxParametersListGsm->At(iSmsTxCnt).iSubmitReport;
       
  1683 		aAttrib->iFlags |= RMobileSmsMessaging::KGsmSubmitReport;
       
  1684 		}
       
  1685 	}
       
  1686 
       
  1687 TInt CSimSmsMessaging::GetCaps(const TTsyReqHandle aReqHandle,TDes8* aPckg)
       
  1688 /**
       
  1689  * Process a request to retrieve the caps.  Currently, only the KCapsReceiveUnstoredClientAck
       
  1690  * mode is supported.
       
  1691  */
       
  1692 	{
       
  1693 	RMobileSmsMessaging::TMobileSmsCapsV1Pckg* capsPckg=(RMobileSmsMessaging::TMobileSmsCapsV1Pckg*)aPckg;
       
  1694 	RMobileSmsMessaging::TMobileSmsCapsV1& caps=(*capsPckg)();
       
  1695 
       
  1696 	// Check that the data structure is supported by the simulated TSY version
       
  1697 	TInt err = iPhone->CheckSimTsyVersion(caps);
       
  1698 	if(err != KErrNone)
       
  1699 		{
       
  1700 		iPhone->ReqCompleted(aReqHandle, err);
       
  1701 		return KErrNone;
       
  1702 		}
       
  1703 
       
  1704 	 	caps.iSmsMode = RMobileSmsMessaging::KCapsGsmSms;
       
  1705 		
       
  1706 	caps.iSmsControl=iSmsControlCaps;
       
  1707 	ReqCompleted(aReqHandle,KErrNone);
       
  1708 	return KErrNone;
       
  1709 	}
       
  1710 
       
  1711 TInt CSimSmsMessaging::GetReceiveMode(const TTsyReqHandle aReqHandle,TDes8* aPckg)
       
  1712 /**
       
  1713  * Process a request to retrieve the current SMS receive mode.  Only the
       
  1714  * KCapsReceiveUnstoredClientAck mode is supported.
       
  1715  */
       
  1716 	{
       
  1717 	TPckg<RMobileSmsMessaging::TMobileSmsReceiveMode>* modePckg=(TPckg<RMobileSmsMessaging::TMobileSmsReceiveMode>*)aPckg;
       
  1718 	RMobileSmsMessaging::TMobileSmsReceiveMode& mode=(*modePckg)();
       
  1719 	mode=iSmsReceiveMode;
       
  1720 	ReqCompleted(aReqHandle,KErrNone);
       
  1721 	return KErrNone;
       
  1722 	}
       
  1723 
       
  1724 TInt CSimSmsMessaging::SetReceiveMode(const TTsyReqHandle aReqHandle,TDes8* aPckg)
       
  1725 /**
       
  1726  * Process a request to set the current SMS receive mode.  Only the
       
  1727  * KCapsReceiveUnstoredClientAck mode is supported.
       
  1728  */
       
  1729 	{
       
  1730 	TPckg<RMobileSmsMessaging::TMobileSmsReceiveMode>* modePckg=(TPckg<RMobileSmsMessaging::TMobileSmsReceiveMode>*)aPckg;
       
  1731 	RMobileSmsMessaging:: TMobileSmsReceiveMode& mode=(*modePckg)();
       
  1732 
       
  1733 	TInt result(KErrNone);
       
  1734 
       
  1735 	switch (mode)
       
  1736 		{
       
  1737 		case RMobileSmsMessaging::EReceiveUnstoredClientAck:
       
  1738 			{
       
  1739 			if(iSmsControlCaps & RMobileSmsMessaging::KCapsReceiveUnstoredClientAck)
       
  1740 				{
       
  1741 				if ((iRxState==ESmsRxStateIdle) || (iRxState==ESmsRxStateWaitingForSmsRx))//can only change mode in these states
       
  1742 					{
       
  1743 					iSmsReceiveMode=RMobileSmsMessaging::EReceiveUnstoredClientAck;
       
  1744 					ReqCompleted(aReqHandle,KErrNone);
       
  1745 					}
       
  1746 				else 
       
  1747 					{
       
  1748 					if(iSmsReceiveMode==RMobileSmsMessaging::EReceiveUnstoredClientAck)//already in this state
       
  1749 						ReqCompleted(aReqHandle,KErrNone);
       
  1750 					else
       
  1751 						ReqCompleted(aReqHandle,KErrNotSupported);
       
  1752 					}
       
  1753 				}
       
  1754 			else ReqCompleted(aReqHandle,KErrNotSupported); 
       
  1755 			break;
       
  1756 			}
       
  1757 
       
  1758 		case RMobileSmsMessaging::EReceiveUnstoredPhoneAck:
       
  1759 			{
       
  1760 			if(iSmsControlCaps & RMobileSmsMessaging:: KCapsReceiveUnstoredPhoneAck)
       
  1761 				{
       
  1762 				if ((iRxState==ESmsRxStateIdle) || (iRxState==ESmsRxStateWaitingForSmsRx))//can only change mode in these states
       
  1763 					{
       
  1764 					iSmsReceiveMode=RMobileSmsMessaging::EReceiveUnstoredPhoneAck;
       
  1765 					ReqCompleted(aReqHandle,KErrNone);
       
  1766 					}
       
  1767 				else
       
  1768 					{
       
  1769 					if (iSmsReceiveMode==RMobileSmsMessaging::EReceiveUnstoredPhoneAck)//already in this state
       
  1770 						ReqCompleted(aReqHandle,KErrNone);
       
  1771 					else
       
  1772 						ReqCompleted(aReqHandle,KErrNotSupported);
       
  1773 					}
       
  1774 				}
       
  1775 			else
       
  1776 				ReqCompleted(aReqHandle,KErrNotSupported); 	
       
  1777 			break;
       
  1778 			}
       
  1779 
       
  1780 		case RMobileSmsMessaging::EReceiveStored:
       
  1781 			{
       
  1782 			if(iSmsControlCaps & RMobileSmsMessaging:: KCapsReceiveStored)
       
  1783 				{
       
  1784 				if ((iRxState==ESmsRxStateIdle) || (iRxState==ESmsRxStateWaitingForSmsRx))//can only change mode in these states
       
  1785 					{
       
  1786 					iSmsReceiveMode=RMobileSmsMessaging::EReceiveStored;
       
  1787 					ReqCompleted(aReqHandle,KErrNone);
       
  1788 					}
       
  1789 				else
       
  1790 					{
       
  1791 					if((iSmsReceiveMode==RMobileSmsMessaging::EReceiveStored))//already in this state
       
  1792 						ReqCompleted(aReqHandle,KErrNone);
       
  1793 					else
       
  1794 						ReqCompleted(aReqHandle,KErrNotSupported);
       
  1795 					}
       
  1796 				}
       
  1797 			else ReqCompleted(aReqHandle,KErrNotSupported); 
       
  1798 			break;
       
  1799 			}
       
  1800 		default:
       
  1801 			result = KErrNotSupported;
       
  1802 		}
       
  1803 	
       
  1804 	return result;
       
  1805 	}
       
  1806 
       
  1807 TInt CSimSmsMessaging::EnumerateMessagingStores(TTsyReqHandle aReqHandle,TDes8* aPckg)
       
  1808 /**
       
  1809  * Process a request to retrieve the number of message stores supported.
       
  1810  * @param aReqHandle	The TSY request handle associated with this request.
       
  1811  * @param aPckg			The parameter package containing the count variable to be populated and
       
  1812  *						returned.
       
  1813  * @return TInt			Standard error value.
       
  1814  */
       
  1815 	{
       
  1816 	TPckg<TInt>* countPckg=(TPckg<TInt>*)aPckg;
       
  1817 	TInt& count=(*countPckg)();
       
  1818 	count=iSmsStores->Count();
       
  1819 	ReqCompleted(aReqHandle,KErrNone);
       
  1820 	return KErrNone;
       
  1821 	}
       
  1822 
       
  1823 TInt CSimSmsMessaging::GetMessageStoreInfo(TTsyReqHandle aReqHandle,TDes8* aPckg1, TDes8* aPckg2)
       
  1824 /**
       
  1825  * Retrieve information about an indexed SMS Message Store.
       
  1826  * @param aReqHandle	The TSY request handle associated with this request.
       
  1827  * @param aPckg1		The parameter package containing the index of the SMS Store for which
       
  1828  *						information is going to be retrieved.
       
  1829  * @param aPckg2		The parameter package in which the retrieved SMS Store information will
       
  1830  *						be passed back to the client.
       
  1831  * @return TInt			Standard error value.
       
  1832  */
       
  1833 	{
       
  1834 	TPckg<TInt>* indexPckg=(TPckg<TInt>*)aPckg1;
       
  1835 	TInt& index=(*indexPckg)();
       
  1836 	TPckg<RMobilePhoneStore::TMobilePhoneStoreInfoV1>* infoPckg=(TPckg<RMobilePhoneStore::TMobilePhoneStoreInfoV1>*)aPckg2;
       
  1837 	RMobilePhoneStore::TMobilePhoneStoreInfoV1& info=(*infoPckg)();
       
  1838 
       
  1839 	// Check that the data structure is supported by the simulated TSY version
       
  1840 	TInt err = iPhone->CheckSimTsyVersion(info);
       
  1841 	if(err != KErrNone)
       
  1842 		{
       
  1843 		iPhone->ReqCompleted(aReqHandle, err);
       
  1844 		return KErrNone;
       
  1845 		}
       
  1846 
       
  1847 	if((index<0) || (index>=iSmsStores->Count()))
       
  1848 		{
       
  1849 		ReqCompleted(aReqHandle,KErrArgument);
       
  1850 		return KErrNone;
       
  1851 		}
       
  1852 
       
  1853 	info.iType=RMobilePhoneStore::EShortMessageStore;
       
  1854 	info.iTotalEntries=iSmsStores->At(index)->MaxSlots();
       
  1855 	info.iUsedEntries=iSmsStores->At(index)->UsedEntries();
       
  1856 	info.iCaps= iSmsStores->At(index)->StoreCaps();
       
  1857 	info.iName.Copy(iSmsStores->At(index)->Name());
       
  1858 	ReqCompleted(aReqHandle,KErrNone);
       
  1859 	return KErrNone;
       
  1860 	}
       
  1861 
       
  1862 TInt CSimSmsMessaging::GetSmspListPhase1(const TTsyReqHandle aTsyReqHandle,
       
  1863                                             TDes8* aParam1,TDes8* aParam2)
       
  1864 /** Get SMSP List Phase 1 
       
  1865  *
       
  1866  * If the GetSmspListPhase1L should leave this method takes care of that and 
       
  1867  * makes a premature ReqCompleted to the client.
       
  1868  *
       
  1869  * @param aTsyReqHandle the request ID 
       
  1870  * @param aClient The client sends down a handle that is saved together with the 
       
  1871  *				  list so the list can be returned to the right client in phase 2.
       
  1872  * @param aBufSiz The size of the retrieved network list. The size is set in 
       
  1873  * @return error code. 
       
  1874  */
       
  1875 	{
       
  1876 	if(iSmspBusy==EFalse)
       
  1877 		{
       
  1878 		iSmspBusy=ETrue;
       
  1879 		UNPACK_PCKG(clientId,aParam1,RMobilePhone::TClientId);
       
  1880 		UNPACK_PCKG(bufSize,aParam2,TInt);
       
  1881 		TRAPD(leaveCode,GetSmspListPhase1L(aTsyReqHandle,clientId,bufSize));
       
  1882 		if (leaveCode)
       
  1883 			return leaveCode;
       
  1884 		return KErrNone;
       
  1885 		}
       
  1886 	else
       
  1887 		return KErrInUse;
       
  1888 
       
  1889 	}
       
  1890 
       
  1891 void CSimSmsMessaging::GetSmspListPhase1L(TTsyReqHandle aTsyReqHandle, 
       
  1892 											 RMobilePhone::TClientId& aClientId, 
       
  1893 											 TInt& aBufSize)
       
  1894 /** Get SMSP List Phase 1 
       
  1895  *
       
  1896  * @param aTsyReqHandle the request ID 
       
  1897  * @param aClient The client sends down a handle that is saved together with the 
       
  1898  *				  list so the list can be returned to the right client in phase 2.
       
  1899  * @param aBufSiz The size of the smsp list. The size is set in 
       
  1900  * @return error code. 
       
  1901  */
       
  1902 	{
       
  1903 	// just check and remove if there are already existing entries from the 
       
  1904 	// same client
       
  1905 	TInt numberOfLists = iSmspReadAll->Count();
       
  1906 	// Find the get smsplists attempts from this client, starting from end.  
       
  1907 	for (TInt i = numberOfLists-1; i >= 0; --i)
       
  1908 		{
       
  1909 		CListReadAllAttempt* readOld=iSmspReadAll->At(i);
       
  1910 		if ((readOld->iClient.iSessionHandle==aClientId.iSessionHandle) &&
       
  1911 		    (readOld->iClient.iSubSessionHandle==aClientId.iSubSessionHandle))
       
  1912 			{
       
  1913 			iSmspReadAll->Delete(i);
       
  1914 			}
       
  1915 		}
       
  1916     // once we have cleaned all then we can proceed...
       
  1917 	iSmspReqHandle=aTsyReqHandle;
       
  1918 	// Store the streamed list and the client ID
       
  1919 	
       
  1920 	CListReadAllAttempt* read=CListReadAllAttempt::NewL(aClientId, aTsyReqHandle);
       
  1921 	CleanupStack::PushL(read);
       
  1922 	
       
  1923 	read->iListBuf = iSmspEntries->StoreLC();
       
  1924 	CleanupStack::Pop(read->iListBuf); // pop the CBufFlat allocated by StoreLC
       
  1925 
       
  1926 	iSmspReadAll->AppendL(read);
       
  1927 	CleanupStack::Pop(read); // pop the CListReadAllAttempt
       
  1928 
       
  1929 // return the CBufFlat's size to client
       
  1930 	aBufSize=(read->iListBuf)->Size();
       
  1931 
       
  1932 //	CleanupStack::PopAndDestroy(); // pop&destroy list
       
  1933 
       
  1934 	iSmspTimer->Start(iSmspBatchPause,this, ETimerIdSmsMessSmsp);
       
  1935 	}
       
  1936 
       
  1937 TInt CSimSmsMessaging::GetSmspListPhase2(const TTsyReqHandle aTsyReqHandle,
       
  1938                                             TDes8* aParam1,TDes8* aParam2)
       
  1939 /** Get SMSP List phase 2 
       
  1940  *
       
  1941  * In this metod the list which was retrieved during phase 1 is copied to 
       
  1942  * the memory which the client has allocated for this purose.
       
  1943  * @param aTsyReqHandle		Const pointer to the request ID 
       
  1944  * @param aClient			Handle to the client which list we are looking for.
       
  1945  * @param aBuf				Pointer to the memory that the etelmm has allocated. 
       
  1946  * @return error code. 
       
  1947  */
       
  1948 	{	
       
  1949 	UNPACK_PCKG(clientId,aParam1,RMobilePhone::TClientId);
       
  1950 	TInt numberOfLists = iSmspReadAll->Count();
       
  1951 	// Find the get smsplists attempts from this client  
       
  1952 	for (TInt i = 0; i < numberOfLists; ++i)
       
  1953 		{
       
  1954 		CListReadAllAttempt* read=iSmspReadAll->At(i);
       
  1955 		if ((read->iClient.iSessionHandle==clientId.iSessionHandle) &&
       
  1956 		    (read->iClient.iSubSessionHandle==clientId.iSubSessionHandle))
       
  1957 			{
       
  1958 			TPtr8 bufPtr((read->iListBuf)->Ptr(0));
       
  1959 			aParam2->Copy(bufPtr);						// Copy the streamed list to the client
       
  1960 			delete read;
       
  1961 			iSmspReadAll->Delete(i);
       
  1962 			ReqCompleted(aTsyReqHandle,KErrNone);	// Completes the retrieval of a network list succesfully.
       
  1963 			return KErrNone;
       
  1964 			}
       
  1965 		}
       
  1966 	return(KErrNotFound);
       
  1967 	}
       
  1968 
       
  1969 TInt CSimSmsMessaging::StoreSmspList(const TTsyReqHandle aTsyReqHandle, TDes8* aBuffer)
       
  1970 /**
       
  1971  *	This function stores a new smsp list 
       
  1972  *  warning the new smsp list will only exist at run time. If the tsy is reloaded the smsp list 
       
  1973  *  will go back to the one defined in the configuration file
       
  1974  *  @param aBuffer Descriptor containing the new smsp list  
       
  1975  */
       
  1976 	{
       
  1977 	if (iSmspBusy==EFalse)
       
  1978 		{
       
  1979 		iSmspBusy=ETrue;
       
  1980 		TRAPD(leaveCode,iSmspEntries->RestoreL(*aBuffer));
       
  1981 		if (leaveCode)
       
  1982 			return leaveCode;
       
  1983 		iSmspReqHandle=aTsyReqHandle;
       
  1984 		iSmspTimer->Start(iSmspBatchPause,this, ETimerIdSmsMessSmsp);
       
  1985 		LOGSMS1("<<StoreSmsList,Exit function");
       
  1986 		return KErrNone;
       
  1987 		}
       
  1988 	else
       
  1989 		LOGSMS1("<<StoreSmsList,Exit function");
       
  1990 		return KErrInUse;
       
  1991 	
       
  1992 	}
       
  1993 
       
  1994 void CSimSmsMessaging::StoreSmspListCancel()
       
  1995 /*
       
  1996  * Cancel an outstanding store smspList request
       
  1997  * as iSmspBusy mutexes get and store, only 1 request handle wil exist at a time 
       
  1998  */
       
  1999 	{
       
  2000 	if(iSmspBusy != EFalse)
       
  2001 		{
       
  2002 		iSmspTimer->Cancel();
       
  2003 		iSmspBusy=EFalse;
       
  2004 		ReqCompleted(iSmspReqHandle,KErrNone);//The timer is cancelled but data has already been stored
       
  2005 		}
       
  2006 	}
       
  2007 
       
  2008 void CSimSmsMessaging::GetSmspListCancel()
       
  2009 /*
       
  2010  * Cancel an outstanding get smspList request.
       
  2011  * as iSmspBusy mutexes get and store, only 1 request handle wil exist at a time 
       
  2012  */
       
  2013 	{
       
  2014 	if(iSmspBusy != EFalse)
       
  2015 		{
       
  2016 		iSmspTimer->Cancel();
       
  2017 		iSmspBusy=EFalse;
       
  2018 		ReqCompleted(iSmspReqHandle,KErrCancel);
       
  2019 		}
       
  2020 	}
       
  2021 
       
  2022 void CSimSmsMessaging::TimerCallBack(TInt aId)
       
  2023 /**
       
  2024  * Process a timer call back event.  
       
  2025  * @param aId Contains the Id of the timer that triggered the event
       
  2026  * 
       
  2027  */
       
  2028 	{
       
  2029 	LOGSMS3(">>CSimSmsMesaging::TimerCallBack IN [aId=%d iSmsReceiveMode=%d]", aId, iSmsReceiveMode);
       
  2030 	switch(aId)
       
  2031 		{
       
  2032 		case ETimerIdSmsMessTx:
       
  2033 			{
       
  2034 			TInt ret=ActionTxEvent(ESmsEventSubmitReportReceived);
       
  2035 			__ASSERT_ALWAYS(ret==KErrNone,SimPanic(EIllegalSmsTxEvent));	// There should be no error from this action, but to check...
       
  2036 			break;
       
  2037 			}
       
  2038 		case ETimerIdSmsMessSmsp:
       
  2039 			{
       
  2040 			iSmspBusy=EFalse;
       
  2041 			ReqCompleted(iSmspReqHandle, KErrNone);
       
  2042 			break;
       
  2043 			}
       
  2044 		case ETimerIdSmsMessRx:
       
  2045 			{
       
  2046 			TInt ret=0;
       
  2047 			
       
  2048 			switch (iSmsReceiveMode)//swich which state machine to enter
       
  2049 				{
       
  2050 			case RMobileSmsMessaging::EReceiveUnstoredClientAck:
       
  2051 				ret=ActionRxEventUnstoredClientAck(ESmsEventRxTimer);
       
  2052 				break;
       
  2053 			case RMobileSmsMessaging::EReceiveUnstoredPhoneAck:
       
  2054 				ret=ActionRxEventUnstoredPhoneAck(ESmsEventRxTimer);
       
  2055 				break;
       
  2056 			case RMobileSmsMessaging::EReceiveStored:
       
  2057 				LOGSMS1("Recieve Stored SMS Rx Event.");
       
  2058 				ret=ActionRxEventStored(ESmsEventRxTimer);
       
  2059 				break;
       
  2060 			default://other receive modes cannot be set
       
  2061 				break;
       
  2062 				}//end switch
       
  2063 
       
  2064 			if (ret != KErrNone)
       
  2065 				{
       
  2066 				LOGSMS2("ERROR: Unexpected ret code %d", ret);
       
  2067 				__ASSERT_ALWAYS(ret==KErrNone,SimPanic(EIllegalSmsRxEvent, __LINE__));	// There should be no error from this action, but to check...
       
  2068 				}
       
  2069 
       
  2070 			break;
       
  2071 			}
       
  2072 
       
  2073 		case ETimerIdSmsMessResumeReception:
       
  2074 			{
       
  2075 			if (iSmsRxReqOutstanding)
       
  2076 				{
       
  2077 				iRxState = ESmsRxStateWaitingForSmsRx;
       
  2078 				}
       
  2079 			else
       
  2080 				{
       
  2081 				iRxState = ESmsRxStateIdle;
       
  2082 				}
       
  2083 			StartSmsMtTimer();
       
  2084 			CompletePendingReq();
       
  2085 			break;
       
  2086 			}
       
  2087 
       
  2088 		default:
       
  2089 			break;
       
  2090 		}
       
  2091 	LOGSMS1(">>CSimSmsMesaging::TimerCallBack OUT");
       
  2092 	}
       
  2093 
       
  2094 const CTestConfigSection* CSimSmsMessaging::CfgFileSection()
       
  2095 /**
       
  2096 * Returns a pointer to the config file section
       
  2097 *
       
  2098 * @return CTestConfigSection a pointer to the configuration file data section
       
  2099 */
       
  2100 	{
       
  2101 	LOGSMS1(">>CSimSmsMessaging::CfgFileSection");
       
  2102 	return iPhone->CfgFile();
       
  2103 	}
       
  2104 
       
  2105 
       
  2106 TInt CSimSmsMessaging::ReloadConfigL(const TTsyReqHandle aReqHandle)
       
  2107 /**
       
  2108  * This function reloads the Rx, Tx and constraint parameters from the config file
       
  2109  * @param aReqHandle Handle to notify when operation completed
       
  2110  * @return KErrNone
       
  2111  */
       
  2112 	{
       
  2113 	LOGSMS1("Reloading configuration");
       
  2114 	//Tell SimPhone to reread the test number property
       
  2115 	iPhone->ResetTestNumber();
       
  2116 	//Delete current configuration
       
  2117 	iSmsRxParameterListGsm->Reset();	
       
  2118 	iSmsTxParametersListGsm->Reset();
       
  2119 	
       
  2120 	iSmsTxCnt = 0;
       
  2121 	iSmsRxCnt = 0;
       
  2122 	iConstraints.Reset();
       
  2123 	iCurrentConstraint = 0;
       
  2124 	iConstraintRxCnt = 0;
       
  2125 	//Reread the configuration
       
  2126 	TInt err;
       
  2127 	TRAP(err, FindAndCreateRxAttributesL());
       
  2128 	if (err != KErrNone) return err;
       
  2129 	TRAP(err, FindAndCreateTxAttributesL());
       
  2130 	if (err != KErrNone) return err;
       
  2131 	FindAndCreateConstraints();
       
  2132 	
       
  2133 	TInt count;
       
  2134 	count = iSmsRxParameterListGsm->Count();
       
  2135 		
       
  2136 	if((count>0)&&(iConstraints.Count()==0))	// If there are messages to receive & no constraints, then
       
  2137 		{
       
  2138 		if (iRxTimer->Running())
       
  2139 			{
       
  2140 			iRxTimer->Cancel();
       
  2141 			}
       
  2142 		LOGSMS1("Starting Rx Timer");
       
  2143 		iRxStatePrevious = iRxState;
       
  2144 		iRxState = ESmsRxStateWaitingToStart;
       
  2145 		iRxTimer->Start(iSmsRxStartDelay,this, ETimerIdSmsMessRx);
       
  2146 		}
       
  2147 	else if (iRxTimer->Running())
       
  2148 		{
       
  2149 		LOGSMS1("Stopping Rx Timer");
       
  2150 		iRxTimer->Cancel();
       
  2151 		}
       
  2152 		
       
  2153 	LOGSMS1("Finished reloading configuration");
       
  2154 	ReqCompleted(aReqHandle,KErrNone);
       
  2155 	return KErrNone;
       
  2156 	}
       
  2157 	
       
  2158 HBufC8* CSimSmsMessaging::PduToAscii(TDesC8& aSmsPdu)
       
  2159 /**
       
  2160  * Converts the contents of a TDes8 to their Hex representation
       
  2161  * @param aSmsPdu Reference to the descriptor to convert
       
  2162  * @return A pointer to an HBufC8 containing the Hex representation of aSmsPdu. The caller is responsible for freeing the object.
       
  2163  * @return Null if the HBufC8 was not successfuly created.
       
  2164  */
       
  2165 	{
       
  2166 	HBufC8* hexBuf = HBufC8::New(aSmsPdu.Length()*2+1);
       
  2167 	if (hexBuf == NULL) return NULL;
       
  2168 	TPtr8 des = hexBuf->Des();
       
  2169 	des.FillZ();
       
  2170 	des.Zero();
       
  2171 	if (hexBuf != NULL)
       
  2172 		{
       
  2173 		for (TInt i = 0; i < aSmsPdu.Length(); i++)
       
  2174 			{
       
  2175 			TInt left = (aSmsPdu[i] & 0xF0) >> 4;
       
  2176 			TInt right = aSmsPdu[i] & 0x0F;
       
  2177 			if (left < 10)
       
  2178 				{
       
  2179 				des.Append(0x30 + left);
       
  2180 				}
       
  2181 			else
       
  2182 				{
       
  2183 				des.Append(0x41 + (left - 10));
       
  2184 				}
       
  2185 			if (right < 10)
       
  2186 				{
       
  2187 				des.Append(0x30 + right);
       
  2188 				}
       
  2189 			else
       
  2190 				{
       
  2191 				des.Append(0x41 + (right - 10));
       
  2192 				}
       
  2193 			}
       
  2194 		}
       
  2195 	des.Append(0);
       
  2196 	return hexBuf;
       
  2197 	}
       
  2198 
       
  2199 #ifdef _DEBUG // to prevent UREL build warnings
       
  2200 void CSimSmsMessaging::DumpPdu(const TDesC8& aText, TDesC8& aSmsPdu, HBufC8* aPduInAscii)
       
  2201 #else
       
  2202 void CSimSmsMessaging::DumpPdu(const TDesC8& /*aText*/, TDesC8& aSmsPdu, HBufC8* aPduInAscii)
       
  2203 #endif
       
  2204 /**
       
  2205 Print PDU in a loop, 150 chars per line
       
  2206 @param aText - a header line about the PDU.
       
  2207 @param aSmsPdu - PDU to log.
       
  2208 @param aPduInAscii - aSmsPdu in ASCII format (default NULL).
       
  2209 */
       
  2210     {
       
  2211 	LOGSMS3("%S pdu length=%d", &aText, aSmsPdu.Length());
       
  2212 
       
  2213     if( !aSmsPdu.Length() )
       
  2214         return;
       
  2215 
       
  2216 	// In sendPdu case, caller needs to call PduToAscii for comparison.
       
  2217 	// Then aPduInAscii is non-zero.
       
  2218 	HBufC8* hexBuf = (aPduInAscii) ? aPduInAscii : PduToAscii(aSmsPdu);
       
  2219 	if (! hexBuf)
       
  2220 	    return;
       
  2221 
       
  2222 	//Print the pdu in a loop because LOGTEXT can only print up to 150 characters
       
  2223 	for (TInt i = 0; i < hexBuf->Length(); i+=100)
       
  2224 	    {
       
  2225 		TInt len = Min(100, hexBuf->Mid(i).Length());
       
  2226         TPtrC8 pduChunk(hexBuf->Mid(i).Left(len).Ptr(), len);
       
  2227 		LOGSMS2("PDU Chunk: %S:", &pduChunk);
       
  2228 		}
       
  2229 
       
  2230 	if (0 == aPduInAscii)
       
  2231 	  delete hexBuf;
       
  2232     }
       
  2233 
       
  2234 #ifdef _DEBUG
       
  2235 
       
  2236 /**
       
  2237 Appends Type of number and Numbering plan identification to TBuf8 buffer.
       
  2238 
       
  2239 @param aBuffer Name of aTon will be appended to this buffer.
       
  2240 @param aTon TMobileTON whose name will be appended to aBuffer.
       
  2241 */
       
  2242 void CSimSmsMessaging::AppendTonToBuffer(TDes8& aBuffer,const RMobilePhone::TMobileTON& aTon)
       
  2243 	{
       
  2244 	switch(aTon)
       
  2245 		{
       
  2246 	case (RMobilePhone::EUnknownNumber):
       
  2247 		{
       
  2248 		aBuffer.Append(_L("EUnknownNumber"));
       
  2249 		break;
       
  2250 		}
       
  2251 	case (RMobilePhone::EInternationalNumber):
       
  2252 		{
       
  2253 		aBuffer.Append(_L("EInternationalNumber"));
       
  2254 		break;
       
  2255 		}
       
  2256 	case (RMobilePhone::ENationalNumber):
       
  2257 		{
       
  2258 		aBuffer.Append(_L("ENationalNumber"));
       
  2259 		break;
       
  2260 		}
       
  2261 	case (RMobilePhone::ENetworkSpecificNumber):
       
  2262 		{
       
  2263 		aBuffer.Append(_L("ENetworkSpecificNumber"));
       
  2264 		break;
       
  2265 		}
       
  2266 	case (RMobilePhone::ESubscriberNumber):
       
  2267 		{
       
  2268 		aBuffer.Append(_L("ESubscriberNumber"));
       
  2269 		break;
       
  2270 		}
       
  2271 	case (RMobilePhone::EAlphanumericNumber):
       
  2272 		{
       
  2273 		aBuffer.Append(_L("EAlphanumericNumber"));
       
  2274 		break;
       
  2275 		}
       
  2276 	case (RMobilePhone::EAbbreviatedNumber):
       
  2277 		{
       
  2278 		aBuffer.Append(_L("EAbbreviatedNumber"));
       
  2279 		break;
       
  2280 		}
       
  2281 	default:
       
  2282 		aBuffer.Append(_L("Wrong Ton Type"));
       
  2283 		}
       
  2284 	}
       
  2285 
       
  2286 void CSimSmsMessaging::AppendNpiToBuffer(TDes8& aBuffer,const RMobilePhone::TMobileNPI& aNpi)
       
  2287 /**
       
  2288  *	Appends Numbering plan identification to TBuf8 buffer.
       
  2289  */
       
  2290 	{
       
  2291 	switch(aNpi)
       
  2292 		{
       
  2293 	case (RMobilePhone::EUnknownNumberingPlan):
       
  2294 		{
       
  2295 		aBuffer.Append(_L("EUnknownNumberingPlan"));
       
  2296 		break;
       
  2297 		}
       
  2298 	case (RMobilePhone::EIsdnNumberPlan):
       
  2299 		{
       
  2300 		aBuffer.Append(_L("EIsdnNumberPlan"));
       
  2301 		break;
       
  2302 		}
       
  2303 	case (RMobilePhone::EDataNumberPlan):
       
  2304 		{
       
  2305 		aBuffer.Append(_L("EDataNumberPlan"));
       
  2306 		break;
       
  2307 		}
       
  2308 	case (RMobilePhone::ETelexNumberPlan):
       
  2309 		{
       
  2310 		aBuffer.Append(_L("ETelexNumberPlan"));
       
  2311 		break;
       
  2312 		}
       
  2313 	case (RMobilePhone::EServiceCentreSpecificPlan1):
       
  2314 		{
       
  2315 		aBuffer.Append(_L("EServiceCentreSpecificPlan1"));
       
  2316 		break;
       
  2317 		}
       
  2318 	case (RMobilePhone::EServiceCentreSpecificPlan2):
       
  2319 		{
       
  2320 		aBuffer.Append(_L("EServiceCentreSpecificPlan2"));
       
  2321 		break;
       
  2322 		}
       
  2323 	case (RMobilePhone::ENationalNumberPlan):
       
  2324 		{
       
  2325 		aBuffer.Append(_L("ENationalNumberPlan"));
       
  2326 		break;
       
  2327 		}
       
  2328 	case (RMobilePhone::EPrivateNumberPlan):
       
  2329 		{
       
  2330 		aBuffer.Append(_L("EPrivateNumberPlan"));
       
  2331 		break;
       
  2332 		}
       
  2333 	case (RMobilePhone::EERMESNumberPlan):
       
  2334 		{
       
  2335 		aBuffer.Append(_L("EERMESNumberPlan"));
       
  2336 		break;
       
  2337 		}
       
  2338 	default:
       
  2339 		aBuffer.Append(_L("Wrong Npi Type"));
       
  2340 		}
       
  2341 	}
       
  2342 
       
  2343 void CSimSmsMessaging::LogTMobileSmsAttributesV1(const RMobileSmsMessaging::TMobileSmsAttributesV1& aSmsAttributesV1)
       
  2344 	{
       
  2345 	const TInt KTextWidth = 100;
       
  2346 	_LIT8(KFLAGS,		"   iFlags:      ");
       
  2347 	_LIT8(KSCADDR,		"   SC Address:  ");
       
  2348 	_LIT8(KSCADDRTON,	"   SC Addr TON: ");
       
  2349 	_LIT8(KSCADDRNPI,	"   SC Addr NPI: ");
       
  2350 	_LIT8(KDATAFORMAT,	"   iDataFormat: ");
       
  2351 	_LIT8(KDEADDR,		"   DE Address:  ");
       
  2352 	_LIT8(KDEADDRTON,	"   DE Addr TON: ");
       
  2353 	_LIT8(KDEADDRNPI,	"   DE Addr NPI: ");
       
  2354 	_LIT8(KMORETOSEND,	"   iMore:       ");
       
  2355 	_LIT8(KMSGREF,		"   iMsgRef:     ");
       
  2356 	_LIT8(KSUBMITREP,	"   iSubmitRep:  ");
       
  2357 
       
  2358 	TBuf8<KTextWidth> buffer;
       
  2359 
       
  2360 	LOGSMS1("Send Sms Attributes:");
       
  2361 	
       
  2362 	buffer.Zero();
       
  2363 	buffer.Copy(KFLAGS);
       
  2364 	buffer.Append(_L8("0x"));
       
  2365 	buffer.AppendFormat(_L8("%08X") , ((TInt)(aSmsAttributesV1.iFlags)));
       
  2366 	LOGSMS2("Buffer: %S", &buffer);
       
  2367 
       
  2368 	if(aSmsAttributesV1.iFlags & RMobileSmsMessaging::KGsmServiceCentre)
       
  2369 		{
       
  2370 		buffer.Zero();
       
  2371 		buffer.Copy(KSCADDR);
       
  2372 		buffer.Append(aSmsAttributesV1.iGsmServiceCentre.iTelNumber);
       
  2373 		LOGSMS2("buffer: %S", &buffer);
       
  2374 
       
  2375 		buffer.Zero();
       
  2376 		buffer.Copy(KSCADDRTON);
       
  2377 		AppendTonToBuffer(buffer,(aSmsAttributesV1.iGsmServiceCentre.iTypeOfNumber));
       
  2378 		LOGSMS2("buffer: %S", &buffer);
       
  2379 
       
  2380 		buffer.Zero();
       
  2381 		buffer.Copy(KSCADDRNPI);
       
  2382 		AppendNpiToBuffer(buffer,(aSmsAttributesV1.iGsmServiceCentre.iNumberPlan));		   
       
  2383 		LOGSMS2("buffer: %S", &buffer);
       
  2384 		}
       
  2385 	if(aSmsAttributesV1.iFlags & RMobileSmsMessaging::KSmsDataFormat)
       
  2386 		{
       
  2387 		buffer.Zero();
       
  2388 		buffer.Copy(KDATAFORMAT);
       
  2389 		if(aSmsAttributesV1.iDataFormat == RMobileSmsMessaging::EFormatUnspecified)
       
  2390 			{
       
  2391 			buffer.Append(_L("EFormatUnspecified"));
       
  2392 			}
       
  2393 		else if(aSmsAttributesV1.iDataFormat == RMobileSmsMessaging::EFormatGsmTpdu)
       
  2394 			{
       
  2395 			buffer.Append(_L("EFormatGsmTpdu"));
       
  2396 			}		
       
  2397 		LOGSMS2("buffer: %S", &buffer);
       
  2398 		}
       
  2399 	if(aSmsAttributesV1.iFlags & RMobileSmsMessaging::KRemotePartyInfo)
       
  2400 		{
       
  2401 		const RMobileSmsMessaging::TMobileSmsSendAttributesV1& smsSendAttributesV1 = static_cast<const RMobileSmsMessaging::TMobileSmsSendAttributesV1&> (aSmsAttributesV1);
       
  2402 
       
  2403 		buffer.Zero();
       
  2404 		buffer.Copy(KDEADDR);
       
  2405 		buffer.Append(smsSendAttributesV1.iDestination.iTelNumber);
       
  2406 		LOGSMS2("buffer: %S", &buffer);
       
  2407 
       
  2408 		buffer.Zero();
       
  2409 		buffer.Copy(KDEADDRTON);
       
  2410 		AppendTonToBuffer(buffer,(smsSendAttributesV1.iDestination.iTypeOfNumber));
       
  2411 		LOGSMS2("buffer: %S", &buffer);
       
  2412 
       
  2413 		buffer.Zero();
       
  2414 		buffer.Copy(KDEADDRNPI);
       
  2415 		AppendNpiToBuffer(buffer,(smsSendAttributesV1.iDestination.iNumberPlan)); 
       
  2416 		LOGSMS2("buffer: %S", &buffer);
       
  2417 		}
       
  2418 	if(aSmsAttributesV1.iFlags & RMobileSmsMessaging::KMoreToSend)
       
  2419 		{
       
  2420 		const RMobileSmsMessaging::TMobileSmsSendAttributesV1& smsSendAttributesV1 = static_cast<const RMobileSmsMessaging::TMobileSmsSendAttributesV1&> (aSmsAttributesV1);
       
  2421 
       
  2422 		buffer.Zero();
       
  2423 		buffer.Copy(KMORETOSEND);
       
  2424 
       
  2425 		if(smsSendAttributesV1.iMore)
       
  2426 			{
       
  2427 			buffer.Append(_L8("ETrue"));
       
  2428 			}
       
  2429 		else
       
  2430 			{
       
  2431 			buffer.Append(_L8("EFalse"));
       
  2432 			}
       
  2433 		LOGSMS2("buffer: %S", &buffer);
       
  2434 		}
       
  2435 	if(aSmsAttributesV1.iFlags & RMobileSmsMessaging::KMessageReference)
       
  2436 		{
       
  2437 		const RMobileSmsMessaging::TMobileSmsSendAttributesV1& smsSendAttributesV1 = static_cast<const RMobileSmsMessaging::TMobileSmsSendAttributesV1&> (aSmsAttributesV1);
       
  2438 
       
  2439 		buffer.Zero();
       
  2440 		buffer.Copy(KMSGREF);
       
  2441 		buffer.Append(_L("0x"));
       
  2442 		buffer.AppendFormat(_L8("%08X") , smsSendAttributesV1.iMsgRef);
       
  2443 		LOGSMS2("buffer: %S", &buffer);
       
  2444 		}
       
  2445 
       
  2446 	if(aSmsAttributesV1.iFlags & RMobileSmsMessaging::KGsmSubmitReport)
       
  2447 		{
       
  2448 		const RMobileSmsMessaging::TMobileSmsSendAttributesV1& smsSendAttributesV1 = static_cast<const RMobileSmsMessaging::TMobileSmsSendAttributesV1&> (aSmsAttributesV1);
       
  2449 
       
  2450 		buffer.Zero();
       
  2451 		buffer.Copy(KSUBMITREP);
       
  2452 
       
  2453 		TInt i = buffer.Length(); 
       
  2454 		TInt j(0);
       
  2455 		TInt k = (smsSendAttributesV1.iSubmitReport.Length() * 2) + buffer.Length();
       
  2456 
       
  2457 		TInt l = 0;
       
  2458 		do
       
  2459 			{
       
  2460 			for(;i<=(KTextWidth-2);i+=2)
       
  2461 				{
       
  2462 				if(j==smsSendAttributesV1.iSubmitReport.Length())
       
  2463 					{
       
  2464 					break;
       
  2465 					}
       
  2466 				buffer.AppendFormat(_L8("%X") , smsSendAttributesV1.iSubmitReport[j]);
       
  2467 				j++;
       
  2468 				}
       
  2469 			LOGSMS2("buffer: %S", &buffer);
       
  2470 			buffer.Zero();
       
  2471 			i=0;
       
  2472 			l+=KTextWidth;
       
  2473 			}
       
  2474 		while(l < k);
       
  2475 		}
       
  2476 	}
       
  2477 
       
  2478 #endif // _DEBUG