telephonyserverplugins/multimodetsy/Multimode/sms/mSMSMESS.CPP
changeset 0 3553901f7fa8
child 24 6638e7f4bd8f
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 // Implements Sms Extensions
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <etelmm.h>
       
    19 #include <etelmmerr.h>		// for Multimode specific error codes
       
    20 
       
    21 #include "ATINIT.H"
       
    22 #include "mSMSMESS.H"
       
    23 #include "mSLOGGER.H"
       
    24 #include "mSMSSEND.H"
       
    25 #include "mSMSCSCA.H"
       
    26 #include "mSSETSC.H"
       
    27 #include "set_cmti_mode.h"		// for CATSetPhoneToCMTIMode
       
    28 #include "set_cmt_mode.h"		// for CATSetPhoneToCMTMode
       
    29 #include "sms_rx_queue.h"       // for CReceiveSmsQueue
       
    30 #include "cmti_stored.h"		// for CATSmsWaitForAndHandleCMTIStored
       
    31 #include "cmt_unstored.h"		// for CATSmsWaitForAndHandleCMTUnstored
       
    32 #include "panic.h"			    // TSY panic codes and ::Panic function
       
    33 
       
    34 
       
    35 //
       
    36 // Macros
       
    37 //
       
    38 #define UNPACK_PCKG(target,source,datatype) datatype& target=(*(TPckg<datatype>*)source)()
       
    39 
       
    40 #ifdef __LOGDEB__
       
    41 _LIT8(KLogEntry,"CMobileSmsMessaging::%S\t%S");
       
    42 #define LOCAL_LOGTEXT(function,text) {_LIT8(F,function);_LIT8(T,text);LOGTEXT3(KLogEntry,&F,&T);}
       
    43 #else
       
    44 #define LOCAL_LOGTEXT(function,text)
       
    45 #endif
       
    46 
       
    47 
       
    48 //
       
    49 // Class Implementation
       
    50 // 
       
    51 CMobileSmsMessaging* CMobileSmsMessaging::NewL(CATIO* aATIO,CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
       
    52 /**
       
    53  * Standard NewL constructor.
       
    54  */
       
    55 	{
       
    56 	CMobileSmsMessaging* subsession=new(ELeave) CMobileSmsMessaging(aATIO,aInit,aPhoneGlobals);
       
    57 	CleanupStack::PushL(subsession);
       
    58 	subsession->ConstructL();
       
    59 	CleanupStack::Pop();
       
    60 	return subsession;
       
    61 	}
       
    62 
       
    63 
       
    64 CMobileSmsMessaging::CMobileSmsMessaging(CATIO* aIo,CATInit* aInit,CPhoneGlobals* aGlobals)
       
    65 	:iIo(aIo)
       
    66 	,iInit(aInit)
       
    67 	,iGlobals(aGlobals)
       
    68 	,iCurrentRxMode(RMobileSmsMessaging::EReceiveModeUnspecified)
       
    69 /**
       
    70  * C++ constructor
       
    71  */
       
    72 	{
       
    73 	}
       
    74 
       
    75 void CMobileSmsMessaging::ConstructL()
       
    76 /**
       
    77  * Standard 2nd phase constructor.
       
    78  * Creates the AT objects which are used to communicate with phone.
       
    79  */
       
    80 	{
       
    81 	iATSmsMessagingSend = CATSmsMessagingSend::NewL(iIo,this,iInit,iGlobals);
       
    82 	iATSmsMemoryStorage = CATSmsMemoryStorage::NewL(iIo,this,iInit,iGlobals);
       
    83 	iATSmsGetSCAddress = CATSmsGetSCAddress::NewL(iIo,this,iInit,iGlobals);
       
    84 	iATSmsSetSCAddress = CATSmsSetSCAddress::NewL(iIo,this,iInit,iGlobals);
       
    85 	iGetSmspList = new(ELeave) CArrayPtrFlat<CListReadAllAttempt>(1); 
       
    86 
       
    87 	// Create the object which we will use to set the phone to use CMTI mode
       
    88 	iATSetPhoneToCMTIMode=CATSetPhoneToCMTIMode::NewL(iIo,this,iInit,iGlobals,iCurrentRxMode);
       
    89 
       
    90 	// Create the object which we will use to set the phone to use CMT mode
       
    91 	iATSetPhoneToCMTMode=CATSetPhoneToCMTMode::NewL(iIo,this,iInit,iGlobals,iCurrentRxMode);
       
    92 
       
    93 	// Create queue for received SMS messages
       
    94 	iReceiveSmsQueue=CReceiveSmsQueue::NewL(iIo,this,iInit,iGlobals,*this);
       
    95 
       
    96 	// Store pointer to our CReceiveSmsQueue object in CPhoneGlobals
       
    97 	// so that the CATCommands::Complete method can prod the object when 
       
    98 	// the serial port is not being used. This is to allow the CRececiveSmsQueu
       
    99 	// object to read any PDUs from the phones memory that it needs to.
       
   100 	// Ownership of the iReceiveSmsQueue stays with this class.
       
   101 	iGlobals->iReceiveSmsQueuePtr=iReceiveSmsQueue;
       
   102 
       
   103 	// Create the object that will listen for CMTI commands from the phone
       
   104 	// and will populate our received SMS queue
       
   105 	iWaitForCMTIStored=CATSmsWaitForAndHandleCMTIStored::NewL(iIo,this,iGlobals,*iReceiveSmsQueue);
       
   106 
       
   107 	// Create the object that will listen for CMT commands from the phone
       
   108 	// and will populate our received SMS queue
       
   109 	iWaitForCMTUnstored=CATSmsWaitForAndHandleCMTUnstored::NewL(iIo,this,iGlobals,*iReceiveSmsQueue);
       
   110 	}
       
   111 
       
   112 CMobileSmsMessaging::~CMobileSmsMessaging()
       
   113 /**
       
   114  * C++ destructor
       
   115  * Destroys the AT objects created during construction
       
   116  */
       
   117 	{
       
   118 	delete iWaitForCMTUnstored;
       
   119 	delete iWaitForCMTIStored;
       
   120 
       
   121 	// We gave CPhoneGlobals a copy of the pointer to iReceiveSmsQueue.
       
   122 	// So we have to null that copy before we destory the one and only
       
   123 	// CReceiveSmsQueue object which this class owns.
       
   124 	if(iGlobals)
       
   125 		iGlobals->iReceiveSmsQueuePtr=NULL;
       
   126 	delete iReceiveSmsQueue;
       
   127 
       
   128 	delete iATSetPhoneToCMTMode;
       
   129 	delete iATSetPhoneToCMTIMode;
       
   130 
       
   131 	if (iGlobals)
       
   132 		iGlobals->iNotificationStore->RemoveClientFromLastEvents(this);
       
   133 	delete iATSmsMessagingSend;
       
   134 	delete iATSmsMemoryStorage;
       
   135 	delete iATSmsGetSCAddress;
       
   136 	delete iATSmsSetSCAddress;
       
   137 	if(iGetSmspList)		// This prevents an Access Violation when CommDB is missing
       
   138 		{
       
   139 		iGetSmspList->ResetAndDestroy();	
       
   140 		delete iGetSmspList;
       
   141 		}
       
   142 	}
       
   143 
       
   144 
       
   145 TInt CMobileSmsMessaging::CancelService(const TInt aIpc,const TTsyReqHandle aTsyReqHandle)
       
   146 /**
       
   147  * Attempts to cancel a service.
       
   148  * @param aIpc The number of the IPC to be cancelled
       
   149  * @param aTsyReHandle The handle of the request which started the IPC
       
   150  * @return Standard KErr... codes
       
   151  */	{
       
   152 	TInt ret(KErrNone);
       
   153 	switch (aIpc)
       
   154 		{
       
   155 	case EMobileSmsMessagingGetMessageStoreInfo:
       
   156 		iATSmsMemoryStorage->CancelCommand(aTsyReqHandle);
       
   157 		break;
       
   158 			
       
   159 	case EMobileSmsMessagingSendMessage:
       
   160 		iATSmsMessagingSend->CancelCommand(aTsyReqHandle);
       
   161 		break;
       
   162 
       
   163 	case EMobileSmsMessagingReceiveMessage:
       
   164 		CancelReceiveMessage();
       
   165 		break;
       
   166 
       
   167 	case EMobileSmsMessagingGetSmspListPhase1:
       
   168 		iATSmsGetSCAddress->CancelCommand(aTsyReqHandle);
       
   169 		break;
       
   170 
       
   171 	case EMobileSmsMessagingStoreSmspList:
       
   172 		iATSmsSetSCAddress->CancelCommand(aTsyReqHandle);
       
   173 		break;
       
   174 
       
   175 	case EMobileSmsMessagingSetReceiveMode:
       
   176 	case EMobileSmsMessagingGetSmspListPhase2:
       
   177 	default:
       
   178 		// can't do anything to cancel these requests
       
   179 		break;
       
   180 
       
   181 		}
       
   182 	return ret;	
       
   183 	}
       
   184 
       
   185 void CMobileSmsMessaging::Init()
       
   186 /**
       
   187  * TSY Intialization
       
   188  * This method has to be implemented as it is pure virtual in MTelObjectTSY.
       
   189  * In this case there is no intialization that needs to be done.
       
   190  */
       
   191 	{}
       
   192 
       
   193 
       
   194 CTelObject* CMobileSmsMessaging::OpenNewObjectByNameL(const TDesC& aName)
       
   195 /**
       
   196  * This method responds to request made by a client of Etel to create a new object of some kind.
       
   197  * Known names are defined in ETELMM.H with the following identifiers...
       
   198  *   KETelMeSmsStore 
       
   199  *   KETelCombinedSmsStore
       
   200  *   KETelIccSmsStore
       
   201  * @param aName Descriptor holding the name of the new object to be created
       
   202  * @return A pointer to the newly created object or NULL if aName was not recognised
       
   203  */
       
   204 	{
       
   205 	if (aName.Compare(KETelMeSmsStore)==0)
       
   206 		{
       
   207 		TStorageType storeType(KMEStorage);
       
   208 		return CMobileSmsStore::NewL(iIo,iInit,iGlobals,storeType);
       
   209 		}
       
   210 
       
   211 	if (aName.Compare(KETelIccSmsStore)==0)
       
   212 		{
       
   213 		TStorageType storeType(KSMStorage);
       
   214 		return CMobileSmsStore::NewL(iIo,iInit,iGlobals,storeType);
       
   215 		}
       
   216 
       
   217 	if (aName.Compare(KETelCombinedSmsStore)==0)
       
   218 		{
       
   219 		TStorageType storeType(KMTStorage);
       
   220 		return CMobileSmsStore::NewL(iIo,iInit,iGlobals,storeType);
       
   221 		}
       
   222 
       
   223 	// Store not supported
       
   224 	User::Leave(KErrNotFound);
       
   225 	return NULL;
       
   226 	}
       
   227 
       
   228 
       
   229 CTelObject* CMobileSmsMessaging::OpenNewObjectL(TDes& /*aNewName*/)
       
   230 /**
       
   231  * The use of this method is not supported in the MMTSY.
       
   232  * @leave This method always leaves with KErrNotSupported
       
   233  */
       
   234 	{
       
   235 	User::Leave(KErrNotSupported);
       
   236 	return NULL;
       
   237 	}
       
   238 
       
   239 
       
   240 CTelObject::TReqMode CMobileSmsMessaging::ReqModeL(const TInt aIpc)
       
   241 /**
       
   242  * This method returns the KReq... mode(s) for a given IPC.
       
   243  * @leave This method will leave with KErrNotSupported if aIpc is not recognized.
       
   244  * @param aIpc The number of the IPC which is being queried
       
   245  * @return The request mode to use for aIpc
       
   246  */
       
   247 	{
       
   248 	// Check the IPC number is valid
       
   249 	if(!IsSupportedIPC(aIpc))
       
   250 		User::Leave(KErrNotSupported);
       
   251 	
       
   252 	CTelObject::TReqMode ret=0;	
       
   253 	switch (aIpc)
       
   254 		{
       
   255 		// TSYs wishing to implement their own buffering algorithm will place all requests in this category.  
       
   256 		// For SMS - ReceiveMessage is in this category because incoming SMS are queued in TSY
       
   257 	case EMobileSmsMessagingReceiveMessage:
       
   258 	case EMobileSmsMessagingGetReceiveMode:
       
   259 	case EMobileSmsMessagingGetCaps:		
       
   260 	case EMobileSmsMessagingGetSmspListPhase2:
       
   261 		ret=0;
       
   262 		break;
       
   263 
       
   264 		// KReqModeFlowControlObeyed
       
   265 		// Commands that change the state of the modem, e.g. setting the monitor volume level; in other words,
       
   266 		// those commands that the TSY should only deal with one at a time.
       
   267 	case EMobileSmsMessagingSetReceiveMode:		
       
   268 	case EMobileSmsMessagingSendMessage:
       
   269 	case EMobileSmsMessagingEnumerateMessageStores:
       
   270 	case EMobileSmsMessagingGetMessageStoreInfo:
       
   271 	case EMobileSmsMessagingGetSmspListPhase1:
       
   272 	case EMobileSmsMessagingStoreSmspList:
       
   273 		ret=KReqModeFlowControlObeyed;
       
   274 		break;
       
   275 
       
   276 		// KReqModeRePostImmediately
       
   277 		// Requests that notify a client about a change of state, where the TSY needs to distinguish between
       
   278 		// different clients.
       
   279 
       
   280 
       
   281 		// KReqModeMultipleCompletionEnabled
       
   282 		// Either (a) commands that may take some time, but which the TSY can handle more than one of concurrently, or 
       
   283 		// (b) notifications that the TSY does not wish to be re-posted immediately, so the server does no buffering.
       
   284 
       
   285 		// KReqModeMultipleCompletionEnabled | KReqModeFlowControlObeyed
       
   286 		// Commands that request information from the modem that is not cached, hence takes a finite amount of time.
       
   287 		// The TSY should only deal with one of these commands at a time.
       
   288 
       
   289 		// KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately
       
   290 		// Requests that notify a client about a change of state.  Since these requests do not require the issuing 
       
   291 		// of any modem commands, they do not have to obey flow control. The TSY never gets more than one of these
       
   292 		// outstanding per TelObject.
       
   293 	case EMobileSmsMessagingNotifySmspListChange:
       
   294 		ret=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately;
       
   295 		break;
       
   296 		}
       
   297 
       
   298 	// Check if the data port is currently loaned. If it is and the requested IPC
       
   299 	// is flow controlled then block Etel calling the IPC by leaving with KErrInUse
       
   300 	if((ret&KReqModeFlowControlObeyed) && iGlobals->iPhoneStatus.iDataPortLoaned)
       
   301 		{
       
   302 		LOGTEXT2(_L8("ReqModeL Leaving with KErrInUse as data port is loaned (aIpc=%d)"),aIpc);
       
   303 		User::Leave(KErrInUse);
       
   304 		}
       
   305 
       
   306 	return ret;
       
   307 	}
       
   308 
       
   309 TInt CMobileSmsMessaging::NumberOfSlotsL(const TInt /*aIpc*/)
       
   310 	{
       
   311 	// No SMS notifications are supported by this TSY
       
   312 	User::Leave(KErrNotSupported);
       
   313 	return 1;		// Execution should never get here
       
   314 	}
       
   315 
       
   316 TInt CMobileSmsMessaging::RegisterNotification(const TInt /*aIpc*/)
       
   317 	{
       
   318 	// No SMS notifications are supported by this TSY
       
   319 	return KErrNone;
       
   320 	}
       
   321 
       
   322 TInt CMobileSmsMessaging::DeregisterNotification(const TInt /*aIpc*/)
       
   323 	{
       
   324 	// No SMS notifications are supported by this TSY
       
   325 	return KErrNone;
       
   326 	}
       
   327 
       
   328 TInt CMobileSmsMessaging::ExtFunc(const TTsyReqHandle aTsyReqHandle,const TInt aIpc,const TDataPackage& aPackage)
       
   329 /**
       
   330  * Sms Read/Send Dispatch Function.
       
   331  *
       
   332  * If this method returns with an KErr code apart from KErrNone then Etel will 
       
   333  * complete and destory the clients request for us. 
       
   334  *
       
   335  * @param aTsyReqHandle The handle of the request which started the IPC
       
   336  * @param aIpc The IPC being requested
       
   337  * @param aPackage Package of parameters associated with the IPC
       
   338  * @return Standard KErr... codes
       
   339 */
       
   340 	{
       
   341 	if(!IsSupportedIPC(aIpc))
       
   342 		return KErrNotSupported;
       
   343 	
       
   344 	// Prior to dispatch check that we're not setting up or in the middle of a data or fax call
       
   345 	if((iGlobals->iPhoneStatus.iPortAccess==EPortAccessDenied) || (iGlobals->iPhoneStatus.iMode == RPhone::EModeOnlineData))
       
   346 		{
       
   347 		LOGTEXT2(_L8("CMobileSmsMessaging::ExtFunc (aIpc=%d)"),aIpc);		
       
   348 		LOCAL_LOGTEXT("ExtFunc","Port Access Denied/Mode Online flag detected");
       
   349 		switch(aIpc)
       
   350 			{
       
   351 		// These may interfere with Fax or Data call, so error the request now...
       
   352 		case EMobileSmsMessagingSendMessage:
       
   353 		case EMobileSmsMessagingSetReceiveMode:
       
   354 		case EMobileSmsMessagingStoreSmspList:
       
   355 		case EMobileSmsMessagingEnumerateMessageStores:
       
   356 		case EMobileSmsMessagingGetSmspListPhase1:
       
   357 		case EMobileSmsMessagingGetMessageStoreInfo:
       
   358 			LOCAL_LOGTEXT("ExtFunc","Returning KErrAccessDenied as request may intefere with fax");
       
   359 			return KErrAccessDenied;
       
   360 			}
       
   361 		}
       
   362 
       
   363 	//
       
   364 	// Handle IPC which use one parameter
       
   365 	__ASSERT_DEBUG(aPackage.Des1n(),Panic(EMobileSmsMessagingNullParameter));
       
   366 	switch(aIpc)
       
   367 		{
       
   368 	case EMobileSmsMessagingSetReceiveMode:
       
   369 		return SetReceiveMode(aTsyReqHandle,aPackage.Des1n());
       
   370 	
       
   371 	case EMobileSmsMessagingGetReceiveMode:
       
   372 		return GetReceiveMode(aTsyReqHandle,aPackage.Des1n());
       
   373 	
       
   374 	case EMobileSmsMessagingGetCaps:
       
   375 		return GetCaps(aTsyReqHandle,aPackage.Des1n());
       
   376 
       
   377 	case EMobileSmsMessagingStoreSmspList:
       
   378 		return StoreSmspList(aTsyReqHandle,aPackage.Des1n());
       
   379 
       
   380 	case EMobileSmsMessagingEnumerateMessageStores:
       
   381 		return EnumerateMessageStores(aTsyReqHandle, aPackage.Des1n());
       
   382 		}
       
   383 
       
   384 	//
       
   385 	// Handle IPC which use two parameters
       
   386 	__ASSERT_DEBUG(aPackage.Des2n(),Panic(EMobileSmsMessagingNullParameter));
       
   387 
       
   388 	switch (aIpc)
       
   389 		{
       
   390 	case EMobileSmsMessagingGetSmspListPhase1:
       
   391 		return GetSmspListPhase1(aTsyReqHandle,aPackage.Des1n(),aPackage.Des2n());
       
   392 
       
   393 	case EMobileSmsMessagingGetSmspListPhase2:
       
   394 		return GetSmspListPhase2(aTsyReqHandle,aPackage.Des1n(),aPackage.Des2n());
       
   395 
       
   396 	case EMobileSmsMessagingSendMessage:	
       
   397 		return SendMessage(aTsyReqHandle,aPackage.Des1n(),aPackage.Des2n());
       
   398 
       
   399 	case EMobileSmsMessagingReceiveMessage:
       
   400 		return ReceiveMessage(aTsyReqHandle,aPackage.Des1n(),aPackage.Des2n());
       
   401 
       
   402 	case EMobileSmsMessagingGetMessageStoreInfo:
       
   403 		return GetMessageStoreInfo(aTsyReqHandle,aPackage.Des1n(),aPackage.Des2n());
       
   404 		}
       
   405 
       
   406 	// Never expect code to execute this far
       
   407 	__ASSERT_DEBUG(EFalse,Panic(EMobileSmsMessagingUnexpectedState));
       
   408 	return KErrNotSupported;		
       
   409 	}
       
   410 
       
   411 
       
   412 //
       
   413 // Methods called by ExtFunc...
       
   414 //
       
   415 TInt CMobileSmsMessaging::SetReceiveMode(const TTsyReqHandle aTsyReqHandle,TDes8* aParam1)
       
   416 /**
       
   417  * Called by ExtFunc. 
       
   418  */
       
   419 	{
       
   420 	// Unpack parameters to lowest usable data type and then process them
       
   421 	UNPACK_PCKG(mode,aParam1,RMobileSmsMessaging::TMobileSmsReceiveMode);
       
   422 	TInt ret(KErrNone);
       
   423 
       
   424 	switch(mode)
       
   425 		{
       
   426 	case RMobileSmsMessaging::EReceiveUnstoredPhoneAck:
       
   427 		LOCAL_LOGTEXT("SetReceiveMode","Client has requested EReceiveUnstoredPhoneAck mode");
       
   428 		iATSetPhoneToCMTMode->ExecuteCommand(aTsyReqHandle,NULL);
       
   429 		break;
       
   430 			
       
   431 	case RMobileSmsMessaging::EReceiveStored:
       
   432 		LOCAL_LOGTEXT("SetReceiveMode","Client has requested EReceiveStored mode");
       
   433 		iATSetPhoneToCMTIMode->ExecuteCommand(aTsyReqHandle,NULL);
       
   434 		break;
       
   435 	
       
   436 	default:
       
   437 		ret=KErrNotSupported;
       
   438 		}
       
   439 
       
   440 	return ret;
       
   441 	}
       
   442 
       
   443 TInt CMobileSmsMessaging::GetReceiveMode(const TTsyReqHandle aTsyReqHandle,TDes8* aParam1)
       
   444 /**
       
   445  * Return the current SMS Reception Mode.
       
   446  */
       
   447 	{
       
   448 	LOCAL_LOGTEXT("GetReceiveMode","Enter function");
       
   449 
       
   450 	// Unpack parameters to lowest usable data type and then process them
       
   451 	UNPACK_PCKG(recMode,aParam1,RMobileSmsMessaging::TMobileSmsReceiveMode);
       
   452 	
       
   453 	//
       
   454 	// Pass current rx mode to client
       
   455 	recMode=iCurrentRxMode;
       
   456 	
       
   457 	//
       
   458 	// Complete clients request
       
   459 	ReqCompleted(aTsyReqHandle,KErrNone);
       
   460 
       
   461 	LOCAL_LOGTEXT("GetReceiveMode","Exit function");
       
   462 	return KErrNone;
       
   463 	}
       
   464 
       
   465 TInt CMobileSmsMessaging::ReceiveMessage(const TTsyReqHandle aReqHandle,TDes8* aParam1,TDes8* aParam2)
       
   466 /**
       
   467  * Called by ExtFunc to process a client request to receive an incoming SMS message.
       
   468  */
       
   469 	{
       
   470 	LOCAL_LOGTEXT("ReceiveMessage","Enter function");
       
   471 
       
   472 	if (iCurrentRxMode == RMobileSmsMessaging::EReceiveModeUnspecified)
       
   473 		{
       
   474 		return(KErrNotSupported);
       
   475 		}
       
   476 
       
   477 	// Validate that phone has been put into a known receive mode
       
   478 	__ASSERT_DEBUG(iCurrentRxMode==RMobileSmsMessaging::EReceiveStored || 
       
   479 			       iCurrentRxMode==RMobileSmsMessaging::EReceiveUnstoredPhoneAck,Panic(EMobileSmsMessagingPhoneNotSetToASupportedReceiveMode));
       
   480 
       
   481 	if (iReceiveSmsQueue->ClientReqOutstanding())
       
   482 		{
       
   483 		// Client request already posted
       
   484 		// TSY only supports one client at a time waiting for an SMS
       
   485 		return KErrInUse;
       
   486 		}
       
   487 
       
   488 	// Ensure our CMT or CMTI listener has been enabled (as appropriate)
       
   489 	if (iCurrentRxMode == RMobileSmsMessaging::EReceiveStored)
       
   490 		{
       
   491 		iWaitForCMTIStored->Enable();
       
   492 		}
       
   493 	else if (iCurrentRxMode == RMobileSmsMessaging::EReceiveUnstoredPhoneAck)
       
   494 		{
       
   495 		iWaitForCMTUnstored->Enable();
       
   496 
       
   497 		if (iGlobals->iModemSupportsCMTIMode)  
       
   498 		// CTMI parsing should be enabled if supported for receive unstored, 
       
   499 		// phone ack mode. See GSM 07.05 section 3.4.1 and defect SHY-54GFHD
       
   500 			{
       
   501 			iWaitForCMTIStored->Enable();
       
   502 			}
       
   503 		}
       
   504 					
       
   505 	// Unpack parameters to lowest usable data type and then process them
       
   506 	RMobileSmsMessaging::TMobileSmsGsmTpdu* pdu=STATIC_CAST(RMobileSmsMessaging::TMobileSmsGsmTpdu*,aParam1);
       
   507 	UNPACK_PCKG(attr,aParam2,RMobileSmsMessaging::TMobileSmsReceiveAttributesV1);
       
   508 
       
   509  	iReceiveSmsQueue->PopAndCompleteClientWhenPossible(aReqHandle,pdu,&attr);
       
   510 	return KErrNone;
       
   511 	}
       
   512 
       
   513 void CMobileSmsMessaging::CancelReceiveMessage()
       
   514 /**
       
   515  * Called by ExtFunc to cancel a ReceiveMessage request
       
   516  */
       
   517 	{
       
   518 	LOCAL_LOGTEXT("CancelReceiveMessage","Enter function");
       
   519 	iWaitForCMTIStored->Disable();
       
   520 	iWaitForCMTUnstored->Disable();
       
   521 	iReceiveSmsQueue->PopAndCompleteClientWhenPossibleCancel();
       
   522 	}
       
   523 
       
   524 
       
   525 TInt CMobileSmsMessaging::GetCaps(const TTsyReqHandle aTsyReqHandle,TDes8* aParam1)
       
   526 /**
       
   527  * Called by ExtFunc. 
       
   528  */
       
   529 	{
       
   530 	// Unpack parameters to lowest usable data type and then process them
       
   531 	UNPACK_PCKG(caps,aParam1,RMobileSmsMessaging::TMobileSmsCapsV1);
       
   532 	switch(caps.ExtensionId())
       
   533 		{
       
   534 	case KETelExtMultimodeV1:		
       
   535 		//
       
   536 		// We are rely on the phone having been intiialised for the SMS receive caps
       
   537 		// If the phone is not initialised complete with KErrNotReady
       
   538 		if(iGlobals->iPhoneStatus.iInitStatus != EPhoneInitialised)
       
   539 			{
       
   540 			// Phone is not yet initialised
       
   541 			ReqCompleted(aTsyReqHandle,KErrNotReady);
       
   542 			}
       
   543 		else
       
   544 			{
       
   545 			// Phone is initialised
       
   546 			caps.iSmsMode=RMobileSmsMessaging::KCapsGsmSms;	// This TSY only supports GSM
       
   547 			caps.iSmsControl=0;
       
   548 			// Supports sending 
       
   549 			caps.iSmsControl|=RMobileSmsMessaging::KCapsSendNoAck;	
       
   550 
       
   551 			// If Phone supports AT+CSCA so say TSY supports SMSP list
       
   552 			if(iGlobals->iModemSupportsCSCAMode)
       
   553 				{
       
   554 				caps.iSmsControl|=RMobileSmsMessaging::KCapsGetSmspList;
       
   555 				caps.iSmsControl|=RMobileSmsMessaging::KCapsSetSmspList;
       
   556 				}
       
   557 
       
   558 			// The receive SMS mode capabiltiies were got during the initialisation of the TSY
       
   559 			if(iGlobals->iModemSupportsCMTIMode)
       
   560 				caps.iSmsControl|=RMobileSmsMessaging::KCapsReceiveStored;
       
   561 			if(iGlobals->iModemSupportsCMTMode)
       
   562 				caps.iSmsControl|=RMobileSmsMessaging::KCapsReceiveUnstoredPhoneAck;
       
   563 		
       
   564 			ReqCompleted(aTsyReqHandle, KErrNone);
       
   565 			}
       
   566 		break;
       
   567 
       
   568 	default:
       
   569 		LOCAL_LOGTEXT("GetCaps","Unknown parameters version");
       
   570 		__ASSERT_DEBUG(EFalse,Panic(EMobileSmsMessagingUnknownParamVersion));	
       
   571 		return KErrUnknown;
       
   572 		}
       
   573     return KErrNone;
       
   574 	}
       
   575 
       
   576 
       
   577 
       
   578 
       
   579 TInt CMobileSmsMessaging::SendMessage(const TTsyReqHandle aTsyReqHandle,TDes8* aParam1,TDes8* aParam2)
       
   580 /**
       
   581  * Called by ExtFunc to process EMobileSmsMessagingSendMessage IPC.
       
   582  */
       
   583   	{
       
   584 	// Unpack parameters
       
   585 	UNPACK_PCKG(msgAttr,aParam2,RMobileSmsMessaging::TMobileSmsSendAttributesV1);
       
   586 
       
   587 	// Check if we can handle format of message
       
   588 	// Try to be optomistic, only reject message if we know we can't handle it
       
   589 	if(msgAttr.iFlags&RMobileSmsMessaging::KSmsDataFormat && 
       
   590 	   msgAttr.iDataFormat!=RMobileSmsMessaging::EFormatUnspecified && 
       
   591        msgAttr.iDataFormat!=RMobileSmsMessaging::EFormatGsmTpdu)
       
   592 		{
       
   593 		LOCAL_LOGTEXT("SendMessage","Format of given message not supported");
       
   594 		// Put extended error in upper 8-bits and core error in lower 8-bits
       
   595 		TInt error = (KErrMMEtelSmsFormatNotSupported << 8) | KErrNotSupported;
       
   596 		return error;
       
   597 		}
       
   598 	else
       
   599 		{	
       
   600 		// Start active object that will do the sending for us
       
   601 		LOCAL_LOGTEXT("SendMessage","Starting CATSmsMessagingSend state machine");
       
   602 		iATSmsMessagingSend->SetMsgAttributes(&msgAttr);
       
   603 		iATSmsMessagingSend->ExecuteCommand(aTsyReqHandle,aParam1);
       
   604 		}
       
   605 
       
   606 	return KErrNone;
       
   607 	}
       
   608 
       
   609 //*********************************************************
       
   610 //*		Enumerate Message Stores & Get Message Store Info
       
   611 //***********************************************************
       
   612 
       
   613 TInt CMobileSmsMessaging::EnumerateMessageStores(const TTsyReqHandle aTsyReqHandle,
       
   614 												 TDes8* aParam1)
       
   615 	{
       
   616 	LOCAL_LOGTEXT("EnumerateMessageStores","Enter function");
       
   617 
       
   618 	if (iGlobals->iPhoneStatus.iInitStatus != EPhoneInitialised)
       
   619 	{
       
   620 		ReqCompleted(aTsyReqHandle,KErrNotReady);
       
   621 
       
   622 	return KErrNone;
       
   623 	}
       
   624 
       
   625 	UNPACK_PCKG(storeCount,aParam1,TInt);
       
   626 	iATSmsMemoryStorage->CopyDataFromCATInit(iInit);
       
   627 	storeCount = iATSmsMemoryStorage->GetNumberOfMessageStores();
       
   628 
       
   629 	ReqCompleted(aTsyReqHandle,KErrNone);
       
   630 	return KErrNone;
       
   631 	}
       
   632 
       
   633 TInt CMobileSmsMessaging::GetMessageStoreInfo(const TTsyReqHandle aTsyReqHandle,
       
   634 											  TDes8* aParam1, TDes8* aParam2)
       
   635 	{
       
   636 	LOCAL_LOGTEXT("GetMessageStoreInfo","Enter function");
       
   637 
       
   638 	if (iGlobals->iPhoneStatus.iInitStatus != EPhoneInitialised)
       
   639 	{
       
   640 		ReqCompleted(aTsyReqHandle,KErrNotReady);
       
   641 
       
   642 	return KErrNone;
       
   643 	}
       
   644 
       
   645 	UNPACK_PCKG(storeIndex,aParam1,TInt);
       
   646 	
       
   647 	TInt ret(KErrNone);
       
   648 	ret=iATSmsMemoryStorage->WhichPreferredMem(storeIndex);
       
   649 	if(ret==KErrNone)
       
   650 		iATSmsMemoryStorage->Start(aTsyReqHandle,aParam2);
       
   651 
       
   652 	return ret;
       
   653 	}
       
   654 
       
   655 //*******************************************
       
   656 //*		Get SMSP List
       
   657 //*******************************************
       
   658 TInt CMobileSmsMessaging::GetSmspListPhase1(const TTsyReqHandle aTsyReqHandle,
       
   659                                             TDes8* aParam1,TDes8* aParam2)
       
   660 /** Get SMSP List Phase 1 
       
   661  *
       
   662  * If the GetSmspListPhase1L should leave this method takes care of that and 
       
   663  * makes a premature ReqCompleted to the client.
       
   664  *
       
   665  * @param aTsyReqHandle the request ID 
       
   666  * @param aClient The client sends down a handle that is saved together with the 
       
   667  *				  list so the list can be returned to the right client in phase 2.
       
   668  * @param aBufSiz The size of the retrieved network list. The size is set in 
       
   669  * @return error code. 
       
   670  */
       
   671 	{
       
   672 	LOCAL_LOGTEXT("GetSmspListPhase1","Enter function");
       
   673 
       
   674 	UNPACK_PCKG(clientId,aParam1,RMobilePhone::TClientId);
       
   675 	UNPACK_PCKG(bufSize,aParam2,TInt);
       
   676 
       
   677 	TRAPD(leaveCode,GetSmspListPhase1L(aTsyReqHandle,clientId,bufSize));
       
   678 	return leaveCode;
       
   679 	}
       
   680 
       
   681 																		
       
   682 void CMobileSmsMessaging::GetSmspListPhase1L(TTsyReqHandle aTsyReqHandle, 
       
   683 											 RMobilePhone::TClientId& aClient, 
       
   684 											 TInt& aBufSize)
       
   685 /** Get SMSP List Phase 1 
       
   686  *
       
   687  * Phase 1 retrieves the only parameter support - the service centre addess 
       
   688  * with help of AT+CSCA?, 
       
   689  * The memory space needed to store the list is then calculated 
       
   690  * and returned to the client.The returned list is saved to be 
       
   691  * copied to the client in phase 2, when the client has alocated memory for it.	
       
   692  * The actual execution of the AT command (AT+CSCA) is done in the CATSmsGetSCAddress class.
       
   693  *
       
   694  * @param aTsyReqHandle const pointer to the request ID 
       
   695  * @param aClient		The client sends down a handle that is saved together with the 
       
   696  *						list so the list can be returned to the right client in phase 2.
       
   697  * @param aBufSize		The size of the retrieved network. The size is set in CATSmsGetSCAddress::ParseResponseL().
       
   698  * @return error code. 
       
   699  */
       
   700 	{
       
   701 	LOCAL_LOGTEXT("GetSmspListPhase1L","Enter function");
       
   702 
       
   703 	CListReadAllAttempt* read=CListReadAllAttempt::NewL(&aClient,aTsyReqHandle);
       
   704 	CleanupStack::PushL(read);
       
   705 
       
   706 	iSmspListInfo.iBufSize = &aBufSize;
       
   707 	iSmspListInfo.iBufPtr = &(read->iListBuf);
       
   708 	iGetSmspList->AppendL(read);
       
   709 
       
   710 	iATSmsGetSCAddress->ExecuteCommand(aTsyReqHandle, &iSmspListInfo); 
       
   711 
       
   712 	CleanupStack::Pop(read);
       
   713 	}
       
   714 
       
   715 TInt CMobileSmsMessaging::GetSmspListPhase2(const TTsyReqHandle aTsyReqHandle,
       
   716                                             TDes8* aParam1,TDes8* aParam2)
       
   717 /** Get SMSP List phase 2 
       
   718  *
       
   719  * In this metod the list which was retrieved during phase 1 is copied to 
       
   720  * the memory which the client has allocated for this purose.
       
   721  * @param aTsyReqHandle		Const pointer to the request ID 
       
   722  * @param aClient			Handle to the client which list we are looking for.
       
   723  * @param aBuf				Pointer to the memory that the etelmm has allocated. 
       
   724  * @return error code. 
       
   725  */
       
   726 	{	
       
   727 	LOCAL_LOGTEXT("GetSmspListPhase2","Enter function");
       
   728 
       
   729 	UNPACK_PCKG(clientId,aParam1,RMobilePhone::TClientId);
       
   730 	
       
   731 	CListReadAllAttempt* read=NULL;
       
   732 	const TInt numberOfLists = iGetSmspList->Count();
       
   733 
       
   734 	// Find the get SMSP attempt from this client  
       
   735 	for (TInt i = 0; i < numberOfLists; ++i)
       
   736 		{
       
   737 		read = iGetSmspList->At(i);
       
   738 		if ((read->iClient.iSessionHandle==clientId.iSessionHandle) &&
       
   739 		    (read->iClient.iSubSessionHandle==clientId.iSubSessionHandle))
       
   740 			{
       
   741 
       
   742 			//
       
   743 			// We have to check that the listPtr is not NULL as if the phone/modem
       
   744 			// responds with a blank service centre listPtr==NULL.
       
   745 			CBufBase* listPtr=read->iListBuf;
       
   746 			if(listPtr)
       
   747 				{
       
   748 				TPtr8 bufPtr(listPtr->Ptr(0));
       
   749 				aParam2->Copy(bufPtr);						// Copy the streamed list to the client
       
   750 				}
       
   751 
       
   752 			delete read;
       
   753 			iGetSmspList->Delete(i);
       
   754 			ReqCompleted(aTsyReqHandle,KErrNone);	// Completes the retrieval of a network list succesfully.
       
   755 			return KErrNone;
       
   756 			}
       
   757 		}
       
   758 
       
   759 	Panic(EIllegalEvent); 
       
   760 	return(KErrNotFound);
       
   761 	}
       
   762 
       
   763 TInt CMobileSmsMessaging::CompleteSmspListCancel(const TTsyReqHandle aTsyReqHandle)
       
   764 /** CompleteSmspListCancel
       
   765  *
       
   766  * This method is called from the CATSmsGetSCAddress class if a cancel is succesful
       
   767  * It cleans-up the client's stored request data
       
   768  * @param aTsyReqHandle		Const pointer to the request ID 
       
   769  * @return error code. 
       
   770  */
       
   771 	{
       
   772 	LOGTEXT(_L8("CMobileSmsMessaging::GetSmspListCancel called"));
       
   773 	// Remove the read all attempt from iGetSmspList
       
   774 	CListReadAllAttempt* read=NULL;
       
   775 	for (TInt i=0; i<iGetSmspList->Count(); ++i)
       
   776 		{
       
   777 		read = iGetSmspList->At(i);
       
   778 		if (read->iReqHandle == aTsyReqHandle)
       
   779 			{
       
   780 			delete read;
       
   781 			iGetSmspList->Delete(i);
       
   782 			break;
       
   783 			}
       
   784 		}
       
   785 	ReqCompleted(aTsyReqHandle,KErrCancel);
       
   786 	return KErrNone;
       
   787 	}
       
   788 
       
   789 TInt CMobileSmsMessaging::StoreSmspList(const TTsyReqHandle aTsyReqHandle, TDes8* aBuffer)
       
   790 	{
       
   791 	LOGTEXT(_L8("CMobileSmsMessaging::StoreSmspList called"));
       
   792 	TInt leaveCode=KErrNone;
       
   793 	TRAP(leaveCode, (void)ProcessStoreSmspListL(aTsyReqHandle, aBuffer););
       
   794 	return leaveCode;
       
   795 	};
       
   796 
       
   797 TInt CMobileSmsMessaging::ProcessStoreSmspListL(TTsyReqHandle aTsyReqHandle, TDes8* aBuffer)
       
   798 	{
       
   799 	CMobilePhoneSmspList* smspList=CMobilePhoneSmspList::NewL();
       
   800 	CleanupStack::PushL(smspList);
       
   801 	
       
   802 	smspList->RestoreL(*aBuffer);
       
   803 
       
   804 	// We only support one entry (the default entry)
       
   805 	if (smspList->Enumerate() != 1)
       
   806 		ReqCompleted(aTsyReqHandle, KErrNotSupported);
       
   807 
       
   808 	// Just get first entry - this is default entry contain SC address
       
   809 	iSCEntry=smspList->GetEntryL(0);
       
   810 
       
   811 	iATSmsSetSCAddress->ExecuteCommand(aTsyReqHandle,&(iSCEntry.iServiceCentre));
       
   812 
       
   813 	CleanupStack::PopAndDestroy(); // smspList
       
   814 	return KErrNone;
       
   815 	}
       
   816 
       
   817 
       
   818 TBool CMobileSmsMessaging::IsSupportedIPC(const TInt aIpc) const
       
   819 	{
       
   820 	switch(aIpc)
       
   821 		{
       
   822 	case EMobileSmsMessagingGetCaps:
       
   823 	case EMobileSmsMessagingSetReceiveMode:
       
   824 	case EMobileSmsMessagingGetReceiveMode:
       
   825 	case EMobileSmsMessagingSendMessage:
       
   826 	case EMobileSmsMessagingReceiveMessage:
       
   827 	case EMobileSmsMessagingEnumerateMessageStores:
       
   828 	case EMobileSmsMessagingGetMessageStoreInfo:
       
   829 	case EMobileSmsMessagingGetSmspListPhase1:
       
   830 	case EMobileSmsMessagingGetSmspListPhase2:
       
   831 	case EMobileSmsMessagingStoreSmspList:
       
   832 		return ETrue;
       
   833 
       
   834 	default:
       
   835 		return EFalse;
       
   836 		}
       
   837 	}