telephonyserverplugins/multimodetsy/Multimode/sms/mSMSMESS.CPP
changeset 0 3553901f7fa8
child 24 6638e7f4bd8f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyserverplugins/multimodetsy/Multimode/sms/mSMSMESS.CPP	Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,837 @@
+// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implements Sms Extensions
+// 
+//
+
+#include <etelmm.h>
+#include <etelmmerr.h>		// for Multimode specific error codes
+
+#include "ATINIT.H"
+#include "mSMSMESS.H"
+#include "mSLOGGER.H"
+#include "mSMSSEND.H"
+#include "mSMSCSCA.H"
+#include "mSSETSC.H"
+#include "set_cmti_mode.h"		// for CATSetPhoneToCMTIMode
+#include "set_cmt_mode.h"		// for CATSetPhoneToCMTMode
+#include "sms_rx_queue.h"       // for CReceiveSmsQueue
+#include "cmti_stored.h"		// for CATSmsWaitForAndHandleCMTIStored
+#include "cmt_unstored.h"		// for CATSmsWaitForAndHandleCMTUnstored
+#include "panic.h"			    // TSY panic codes and ::Panic function
+
+
+//
+// Macros
+//
+#define UNPACK_PCKG(target,source,datatype) datatype& target=(*(TPckg<datatype>*)source)()
+
+#ifdef __LOGDEB__
+_LIT8(KLogEntry,"CMobileSmsMessaging::%S\t%S");
+#define LOCAL_LOGTEXT(function,text) {_LIT8(F,function);_LIT8(T,text);LOGTEXT3(KLogEntry,&F,&T);}
+#else
+#define LOCAL_LOGTEXT(function,text)
+#endif
+
+
+//
+// Class Implementation
+// 
+CMobileSmsMessaging* CMobileSmsMessaging::NewL(CATIO* aATIO,CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
+/**
+ * Standard NewL constructor.
+ */
+	{
+	CMobileSmsMessaging* subsession=new(ELeave) CMobileSmsMessaging(aATIO,aInit,aPhoneGlobals);
+	CleanupStack::PushL(subsession);
+	subsession->ConstructL();
+	CleanupStack::Pop();
+	return subsession;
+	}
+
+
+CMobileSmsMessaging::CMobileSmsMessaging(CATIO* aIo,CATInit* aInit,CPhoneGlobals* aGlobals)
+	:iIo(aIo)
+	,iInit(aInit)
+	,iGlobals(aGlobals)
+	,iCurrentRxMode(RMobileSmsMessaging::EReceiveModeUnspecified)
+/**
+ * C++ constructor
+ */
+	{
+	}
+
+void CMobileSmsMessaging::ConstructL()
+/**
+ * Standard 2nd phase constructor.
+ * Creates the AT objects which are used to communicate with phone.
+ */
+	{
+	iATSmsMessagingSend = CATSmsMessagingSend::NewL(iIo,this,iInit,iGlobals);
+	iATSmsMemoryStorage = CATSmsMemoryStorage::NewL(iIo,this,iInit,iGlobals);
+	iATSmsGetSCAddress = CATSmsGetSCAddress::NewL(iIo,this,iInit,iGlobals);
+	iATSmsSetSCAddress = CATSmsSetSCAddress::NewL(iIo,this,iInit,iGlobals);
+	iGetSmspList = new(ELeave) CArrayPtrFlat<CListReadAllAttempt>(1); 
+
+	// Create the object which we will use to set the phone to use CMTI mode
+	iATSetPhoneToCMTIMode=CATSetPhoneToCMTIMode::NewL(iIo,this,iInit,iGlobals,iCurrentRxMode);
+
+	// Create the object which we will use to set the phone to use CMT mode
+	iATSetPhoneToCMTMode=CATSetPhoneToCMTMode::NewL(iIo,this,iInit,iGlobals,iCurrentRxMode);
+
+	// Create queue for received SMS messages
+	iReceiveSmsQueue=CReceiveSmsQueue::NewL(iIo,this,iInit,iGlobals,*this);
+
+	// Store pointer to our CReceiveSmsQueue object in CPhoneGlobals
+	// so that the CATCommands::Complete method can prod the object when 
+	// the serial port is not being used. This is to allow the CRececiveSmsQueu
+	// object to read any PDUs from the phones memory that it needs to.
+	// Ownership of the iReceiveSmsQueue stays with this class.
+	iGlobals->iReceiveSmsQueuePtr=iReceiveSmsQueue;
+
+	// Create the object that will listen for CMTI commands from the phone
+	// and will populate our received SMS queue
+	iWaitForCMTIStored=CATSmsWaitForAndHandleCMTIStored::NewL(iIo,this,iGlobals,*iReceiveSmsQueue);
+
+	// Create the object that will listen for CMT commands from the phone
+	// and will populate our received SMS queue
+	iWaitForCMTUnstored=CATSmsWaitForAndHandleCMTUnstored::NewL(iIo,this,iGlobals,*iReceiveSmsQueue);
+	}
+
+CMobileSmsMessaging::~CMobileSmsMessaging()
+/**
+ * C++ destructor
+ * Destroys the AT objects created during construction
+ */
+	{
+	delete iWaitForCMTUnstored;
+	delete iWaitForCMTIStored;
+
+	// We gave CPhoneGlobals a copy of the pointer to iReceiveSmsQueue.
+	// So we have to null that copy before we destory the one and only
+	// CReceiveSmsQueue object which this class owns.
+	if(iGlobals)
+		iGlobals->iReceiveSmsQueuePtr=NULL;
+	delete iReceiveSmsQueue;
+
+	delete iATSetPhoneToCMTMode;
+	delete iATSetPhoneToCMTIMode;
+
+	if (iGlobals)
+		iGlobals->iNotificationStore->RemoveClientFromLastEvents(this);
+	delete iATSmsMessagingSend;
+	delete iATSmsMemoryStorage;
+	delete iATSmsGetSCAddress;
+	delete iATSmsSetSCAddress;
+	if(iGetSmspList)		// This prevents an Access Violation when CommDB is missing
+		{
+		iGetSmspList->ResetAndDestroy();	
+		delete iGetSmspList;
+		}
+	}
+
+
+TInt CMobileSmsMessaging::CancelService(const TInt aIpc,const TTsyReqHandle aTsyReqHandle)
+/**
+ * Attempts to cancel a service.
+ * @param aIpc The number of the IPC to be cancelled
+ * @param aTsyReHandle The handle of the request which started the IPC
+ * @return Standard KErr... codes
+ */	{
+	TInt ret(KErrNone);
+	switch (aIpc)
+		{
+	case EMobileSmsMessagingGetMessageStoreInfo:
+		iATSmsMemoryStorage->CancelCommand(aTsyReqHandle);
+		break;
+			
+	case EMobileSmsMessagingSendMessage:
+		iATSmsMessagingSend->CancelCommand(aTsyReqHandle);
+		break;
+
+	case EMobileSmsMessagingReceiveMessage:
+		CancelReceiveMessage();
+		break;
+
+	case EMobileSmsMessagingGetSmspListPhase1:
+		iATSmsGetSCAddress->CancelCommand(aTsyReqHandle);
+		break;
+
+	case EMobileSmsMessagingStoreSmspList:
+		iATSmsSetSCAddress->CancelCommand(aTsyReqHandle);
+		break;
+
+	case EMobileSmsMessagingSetReceiveMode:
+	case EMobileSmsMessagingGetSmspListPhase2:
+	default:
+		// can't do anything to cancel these requests
+		break;
+
+		}
+	return ret;	
+	}
+
+void CMobileSmsMessaging::Init()
+/**
+ * TSY Intialization
+ * This method has to be implemented as it is pure virtual in MTelObjectTSY.
+ * In this case there is no intialization that needs to be done.
+ */
+	{}
+
+
+CTelObject* CMobileSmsMessaging::OpenNewObjectByNameL(const TDesC& aName)
+/**
+ * This method responds to request made by a client of Etel to create a new object of some kind.
+ * Known names are defined in ETELMM.H with the following identifiers...
+ *   KETelMeSmsStore 
+ *   KETelCombinedSmsStore
+ *   KETelIccSmsStore
+ * @param aName Descriptor holding the name of the new object to be created
+ * @return A pointer to the newly created object or NULL if aName was not recognised
+ */
+	{
+	if (aName.Compare(KETelMeSmsStore)==0)
+		{
+		TStorageType storeType(KMEStorage);
+		return CMobileSmsStore::NewL(iIo,iInit,iGlobals,storeType);
+		}
+
+	if (aName.Compare(KETelIccSmsStore)==0)
+		{
+		TStorageType storeType(KSMStorage);
+		return CMobileSmsStore::NewL(iIo,iInit,iGlobals,storeType);
+		}
+
+	if (aName.Compare(KETelCombinedSmsStore)==0)
+		{
+		TStorageType storeType(KMTStorage);
+		return CMobileSmsStore::NewL(iIo,iInit,iGlobals,storeType);
+		}
+
+	// Store not supported
+	User::Leave(KErrNotFound);
+	return NULL;
+	}
+
+
+CTelObject* CMobileSmsMessaging::OpenNewObjectL(TDes& /*aNewName*/)
+/**
+ * The use of this method is not supported in the MMTSY.
+ * @leave This method always leaves with KErrNotSupported
+ */
+	{
+	User::Leave(KErrNotSupported);
+	return NULL;
+	}
+
+
+CTelObject::TReqMode CMobileSmsMessaging::ReqModeL(const TInt aIpc)
+/**
+ * This method returns the KReq... mode(s) for a given IPC.
+ * @leave This method will leave with KErrNotSupported if aIpc is not recognized.
+ * @param aIpc The number of the IPC which is being queried
+ * @return The request mode to use for aIpc
+ */
+	{
+	// Check the IPC number is valid
+	if(!IsSupportedIPC(aIpc))
+		User::Leave(KErrNotSupported);
+	
+	CTelObject::TReqMode ret=0;	
+	switch (aIpc)
+		{
+		// TSYs wishing to implement their own buffering algorithm will place all requests in this category.  
+		// For SMS - ReceiveMessage is in this category because incoming SMS are queued in TSY
+	case EMobileSmsMessagingReceiveMessage:
+	case EMobileSmsMessagingGetReceiveMode:
+	case EMobileSmsMessagingGetCaps:		
+	case EMobileSmsMessagingGetSmspListPhase2:
+		ret=0;
+		break;
+
+		// KReqModeFlowControlObeyed
+		// Commands that change the state of the modem, e.g. setting the monitor volume level; in other words,
+		// those commands that the TSY should only deal with one at a time.
+	case EMobileSmsMessagingSetReceiveMode:		
+	case EMobileSmsMessagingSendMessage:
+	case EMobileSmsMessagingEnumerateMessageStores:
+	case EMobileSmsMessagingGetMessageStoreInfo:
+	case EMobileSmsMessagingGetSmspListPhase1:
+	case EMobileSmsMessagingStoreSmspList:
+		ret=KReqModeFlowControlObeyed;
+		break;
+
+		// KReqModeRePostImmediately
+		// Requests that notify a client about a change of state, where the TSY needs to distinguish between
+		// different clients.
+
+
+		// KReqModeMultipleCompletionEnabled
+		// Either (a) commands that may take some time, but which the TSY can handle more than one of concurrently, or 
+		// (b) notifications that the TSY does not wish to be re-posted immediately, so the server does no buffering.
+
+		// KReqModeMultipleCompletionEnabled | KReqModeFlowControlObeyed
+		// Commands that request information from the modem that is not cached, hence takes a finite amount of time.
+		// The TSY should only deal with one of these commands at a time.
+
+		// KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately
+		// Requests that notify a client about a change of state.  Since these requests do not require the issuing 
+		// of any modem commands, they do not have to obey flow control. The TSY never gets more than one of these
+		// outstanding per TelObject.
+	case EMobileSmsMessagingNotifySmspListChange:
+		ret=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately;
+		break;
+		}
+
+	// Check if the data port is currently loaned. If it is and the requested IPC
+	// is flow controlled then block Etel calling the IPC by leaving with KErrInUse
+	if((ret&KReqModeFlowControlObeyed) && iGlobals->iPhoneStatus.iDataPortLoaned)
+		{
+		LOGTEXT2(_L8("ReqModeL Leaving with KErrInUse as data port is loaned (aIpc=%d)"),aIpc);
+		User::Leave(KErrInUse);
+		}
+
+	return ret;
+	}
+
+TInt CMobileSmsMessaging::NumberOfSlotsL(const TInt /*aIpc*/)
+	{
+	// No SMS notifications are supported by this TSY
+	User::Leave(KErrNotSupported);
+	return 1;		// Execution should never get here
+	}
+
+TInt CMobileSmsMessaging::RegisterNotification(const TInt /*aIpc*/)
+	{
+	// No SMS notifications are supported by this TSY
+	return KErrNone;
+	}
+
+TInt CMobileSmsMessaging::DeregisterNotification(const TInt /*aIpc*/)
+	{
+	// No SMS notifications are supported by this TSY
+	return KErrNone;
+	}
+
+TInt CMobileSmsMessaging::ExtFunc(const TTsyReqHandle aTsyReqHandle,const TInt aIpc,const TDataPackage& aPackage)
+/**
+ * Sms Read/Send Dispatch Function.
+ *
+ * If this method returns with an KErr code apart from KErrNone then Etel will 
+ * complete and destory the clients request for us. 
+ *
+ * @param aTsyReqHandle The handle of the request which started the IPC
+ * @param aIpc The IPC being requested
+ * @param aPackage Package of parameters associated with the IPC
+ * @return Standard KErr... codes
+*/
+	{
+	if(!IsSupportedIPC(aIpc))
+		return KErrNotSupported;
+	
+	// Prior to dispatch check that we're not setting up or in the middle of a data or fax call
+	if((iGlobals->iPhoneStatus.iPortAccess==EPortAccessDenied) || (iGlobals->iPhoneStatus.iMode == RPhone::EModeOnlineData))
+		{
+		LOGTEXT2(_L8("CMobileSmsMessaging::ExtFunc (aIpc=%d)"),aIpc);		
+		LOCAL_LOGTEXT("ExtFunc","Port Access Denied/Mode Online flag detected");
+		switch(aIpc)
+			{
+		// These may interfere with Fax or Data call, so error the request now...
+		case EMobileSmsMessagingSendMessage:
+		case EMobileSmsMessagingSetReceiveMode:
+		case EMobileSmsMessagingStoreSmspList:
+		case EMobileSmsMessagingEnumerateMessageStores:
+		case EMobileSmsMessagingGetSmspListPhase1:
+		case EMobileSmsMessagingGetMessageStoreInfo:
+			LOCAL_LOGTEXT("ExtFunc","Returning KErrAccessDenied as request may intefere with fax");
+			return KErrAccessDenied;
+			}
+		}
+
+	//
+	// Handle IPC which use one parameter
+	__ASSERT_DEBUG(aPackage.Des1n(),Panic(EMobileSmsMessagingNullParameter));
+	switch(aIpc)
+		{
+	case EMobileSmsMessagingSetReceiveMode:
+		return SetReceiveMode(aTsyReqHandle,aPackage.Des1n());
+	
+	case EMobileSmsMessagingGetReceiveMode:
+		return GetReceiveMode(aTsyReqHandle,aPackage.Des1n());
+	
+	case EMobileSmsMessagingGetCaps:
+		return GetCaps(aTsyReqHandle,aPackage.Des1n());
+
+	case EMobileSmsMessagingStoreSmspList:
+		return StoreSmspList(aTsyReqHandle,aPackage.Des1n());
+
+	case EMobileSmsMessagingEnumerateMessageStores:
+		return EnumerateMessageStores(aTsyReqHandle, aPackage.Des1n());
+		}
+
+	//
+	// Handle IPC which use two parameters
+	__ASSERT_DEBUG(aPackage.Des2n(),Panic(EMobileSmsMessagingNullParameter));
+
+	switch (aIpc)
+		{
+	case EMobileSmsMessagingGetSmspListPhase1:
+		return GetSmspListPhase1(aTsyReqHandle,aPackage.Des1n(),aPackage.Des2n());
+
+	case EMobileSmsMessagingGetSmspListPhase2:
+		return GetSmspListPhase2(aTsyReqHandle,aPackage.Des1n(),aPackage.Des2n());
+
+	case EMobileSmsMessagingSendMessage:	
+		return SendMessage(aTsyReqHandle,aPackage.Des1n(),aPackage.Des2n());
+
+	case EMobileSmsMessagingReceiveMessage:
+		return ReceiveMessage(aTsyReqHandle,aPackage.Des1n(),aPackage.Des2n());
+
+	case EMobileSmsMessagingGetMessageStoreInfo:
+		return GetMessageStoreInfo(aTsyReqHandle,aPackage.Des1n(),aPackage.Des2n());
+		}
+
+	// Never expect code to execute this far
+	__ASSERT_DEBUG(EFalse,Panic(EMobileSmsMessagingUnexpectedState));
+	return KErrNotSupported;		
+	}
+
+
+//
+// Methods called by ExtFunc...
+//
+TInt CMobileSmsMessaging::SetReceiveMode(const TTsyReqHandle aTsyReqHandle,TDes8* aParam1)
+/**
+ * Called by ExtFunc. 
+ */
+	{
+	// Unpack parameters to lowest usable data type and then process them
+	UNPACK_PCKG(mode,aParam1,RMobileSmsMessaging::TMobileSmsReceiveMode);
+	TInt ret(KErrNone);
+
+	switch(mode)
+		{
+	case RMobileSmsMessaging::EReceiveUnstoredPhoneAck:
+		LOCAL_LOGTEXT("SetReceiveMode","Client has requested EReceiveUnstoredPhoneAck mode");
+		iATSetPhoneToCMTMode->ExecuteCommand(aTsyReqHandle,NULL);
+		break;
+			
+	case RMobileSmsMessaging::EReceiveStored:
+		LOCAL_LOGTEXT("SetReceiveMode","Client has requested EReceiveStored mode");
+		iATSetPhoneToCMTIMode->ExecuteCommand(aTsyReqHandle,NULL);
+		break;
+	
+	default:
+		ret=KErrNotSupported;
+		}
+
+	return ret;
+	}
+
+TInt CMobileSmsMessaging::GetReceiveMode(const TTsyReqHandle aTsyReqHandle,TDes8* aParam1)
+/**
+ * Return the current SMS Reception Mode.
+ */
+	{
+	LOCAL_LOGTEXT("GetReceiveMode","Enter function");
+
+	// Unpack parameters to lowest usable data type and then process them
+	UNPACK_PCKG(recMode,aParam1,RMobileSmsMessaging::TMobileSmsReceiveMode);
+	
+	//
+	// Pass current rx mode to client
+	recMode=iCurrentRxMode;
+	
+	//
+	// Complete clients request
+	ReqCompleted(aTsyReqHandle,KErrNone);
+
+	LOCAL_LOGTEXT("GetReceiveMode","Exit function");
+	return KErrNone;
+	}
+
+TInt CMobileSmsMessaging::ReceiveMessage(const TTsyReqHandle aReqHandle,TDes8* aParam1,TDes8* aParam2)
+/**
+ * Called by ExtFunc to process a client request to receive an incoming SMS message.
+ */
+	{
+	LOCAL_LOGTEXT("ReceiveMessage","Enter function");
+
+	if (iCurrentRxMode == RMobileSmsMessaging::EReceiveModeUnspecified)
+		{
+		return(KErrNotSupported);
+		}
+
+	// Validate that phone has been put into a known receive mode
+	__ASSERT_DEBUG(iCurrentRxMode==RMobileSmsMessaging::EReceiveStored || 
+			       iCurrentRxMode==RMobileSmsMessaging::EReceiveUnstoredPhoneAck,Panic(EMobileSmsMessagingPhoneNotSetToASupportedReceiveMode));
+
+	if (iReceiveSmsQueue->ClientReqOutstanding())
+		{
+		// Client request already posted
+		// TSY only supports one client at a time waiting for an SMS
+		return KErrInUse;
+		}
+
+	// Ensure our CMT or CMTI listener has been enabled (as appropriate)
+	if (iCurrentRxMode == RMobileSmsMessaging::EReceiveStored)
+		{
+		iWaitForCMTIStored->Enable();
+		}
+	else if (iCurrentRxMode == RMobileSmsMessaging::EReceiveUnstoredPhoneAck)
+		{
+		iWaitForCMTUnstored->Enable();
+
+		if (iGlobals->iModemSupportsCMTIMode)  
+		// CTMI parsing should be enabled if supported for receive unstored, 
+		// phone ack mode. See GSM 07.05 section 3.4.1 and defect SHY-54GFHD
+			{
+			iWaitForCMTIStored->Enable();
+			}
+		}
+					
+	// Unpack parameters to lowest usable data type and then process them
+	RMobileSmsMessaging::TMobileSmsGsmTpdu* pdu=STATIC_CAST(RMobileSmsMessaging::TMobileSmsGsmTpdu*,aParam1);
+	UNPACK_PCKG(attr,aParam2,RMobileSmsMessaging::TMobileSmsReceiveAttributesV1);
+
+ 	iReceiveSmsQueue->PopAndCompleteClientWhenPossible(aReqHandle,pdu,&attr);
+	return KErrNone;
+	}
+
+void CMobileSmsMessaging::CancelReceiveMessage()
+/**
+ * Called by ExtFunc to cancel a ReceiveMessage request
+ */
+	{
+	LOCAL_LOGTEXT("CancelReceiveMessage","Enter function");
+	iWaitForCMTIStored->Disable();
+	iWaitForCMTUnstored->Disable();
+	iReceiveSmsQueue->PopAndCompleteClientWhenPossibleCancel();
+	}
+
+
+TInt CMobileSmsMessaging::GetCaps(const TTsyReqHandle aTsyReqHandle,TDes8* aParam1)
+/**
+ * Called by ExtFunc. 
+ */
+	{
+	// Unpack parameters to lowest usable data type and then process them
+	UNPACK_PCKG(caps,aParam1,RMobileSmsMessaging::TMobileSmsCapsV1);
+	switch(caps.ExtensionId())
+		{
+	case KETelExtMultimodeV1:		
+		//
+		// We are rely on the phone having been intiialised for the SMS receive caps
+		// If the phone is not initialised complete with KErrNotReady
+		if(iGlobals->iPhoneStatus.iInitStatus != EPhoneInitialised)
+			{
+			// Phone is not yet initialised
+			ReqCompleted(aTsyReqHandle,KErrNotReady);
+			}
+		else
+			{
+			// Phone is initialised
+			caps.iSmsMode=RMobileSmsMessaging::KCapsGsmSms;	// This TSY only supports GSM
+			caps.iSmsControl=0;
+			// Supports sending 
+			caps.iSmsControl|=RMobileSmsMessaging::KCapsSendNoAck;	
+
+			// If Phone supports AT+CSCA so say TSY supports SMSP list
+			if(iGlobals->iModemSupportsCSCAMode)
+				{
+				caps.iSmsControl|=RMobileSmsMessaging::KCapsGetSmspList;
+				caps.iSmsControl|=RMobileSmsMessaging::KCapsSetSmspList;
+				}
+
+			// The receive SMS mode capabiltiies were got during the initialisation of the TSY
+			if(iGlobals->iModemSupportsCMTIMode)
+				caps.iSmsControl|=RMobileSmsMessaging::KCapsReceiveStored;
+			if(iGlobals->iModemSupportsCMTMode)
+				caps.iSmsControl|=RMobileSmsMessaging::KCapsReceiveUnstoredPhoneAck;
+		
+			ReqCompleted(aTsyReqHandle, KErrNone);
+			}
+		break;
+
+	default:
+		LOCAL_LOGTEXT("GetCaps","Unknown parameters version");
+		__ASSERT_DEBUG(EFalse,Panic(EMobileSmsMessagingUnknownParamVersion));	
+		return KErrUnknown;
+		}
+    return KErrNone;
+	}
+
+
+
+
+TInt CMobileSmsMessaging::SendMessage(const TTsyReqHandle aTsyReqHandle,TDes8* aParam1,TDes8* aParam2)
+/**
+ * Called by ExtFunc to process EMobileSmsMessagingSendMessage IPC.
+ */
+  	{
+	// Unpack parameters
+	UNPACK_PCKG(msgAttr,aParam2,RMobileSmsMessaging::TMobileSmsSendAttributesV1);
+
+	// Check if we can handle format of message
+	// Try to be optomistic, only reject message if we know we can't handle it
+	if(msgAttr.iFlags&RMobileSmsMessaging::KSmsDataFormat && 
+	   msgAttr.iDataFormat!=RMobileSmsMessaging::EFormatUnspecified && 
+       msgAttr.iDataFormat!=RMobileSmsMessaging::EFormatGsmTpdu)
+		{
+		LOCAL_LOGTEXT("SendMessage","Format of given message not supported");
+		// Put extended error in upper 8-bits and core error in lower 8-bits
+		TInt error = (KErrMMEtelSmsFormatNotSupported << 8) | KErrNotSupported;
+		return error;
+		}
+	else
+		{	
+		// Start active object that will do the sending for us
+		LOCAL_LOGTEXT("SendMessage","Starting CATSmsMessagingSend state machine");
+		iATSmsMessagingSend->SetMsgAttributes(&msgAttr);
+		iATSmsMessagingSend->ExecuteCommand(aTsyReqHandle,aParam1);
+		}
+
+	return KErrNone;
+	}
+
+//*********************************************************
+//*		Enumerate Message Stores & Get Message Store Info
+//***********************************************************
+
+TInt CMobileSmsMessaging::EnumerateMessageStores(const TTsyReqHandle aTsyReqHandle,
+												 TDes8* aParam1)
+	{
+	LOCAL_LOGTEXT("EnumerateMessageStores","Enter function");
+
+	if (iGlobals->iPhoneStatus.iInitStatus != EPhoneInitialised)
+	{
+		ReqCompleted(aTsyReqHandle,KErrNotReady);
+
+	return KErrNone;
+	}
+
+	UNPACK_PCKG(storeCount,aParam1,TInt);
+	iATSmsMemoryStorage->CopyDataFromCATInit(iInit);
+	storeCount = iATSmsMemoryStorage->GetNumberOfMessageStores();
+
+	ReqCompleted(aTsyReqHandle,KErrNone);
+	return KErrNone;
+	}
+
+TInt CMobileSmsMessaging::GetMessageStoreInfo(const TTsyReqHandle aTsyReqHandle,
+											  TDes8* aParam1, TDes8* aParam2)
+	{
+	LOCAL_LOGTEXT("GetMessageStoreInfo","Enter function");
+
+	if (iGlobals->iPhoneStatus.iInitStatus != EPhoneInitialised)
+	{
+		ReqCompleted(aTsyReqHandle,KErrNotReady);
+
+	return KErrNone;
+	}
+
+	UNPACK_PCKG(storeIndex,aParam1,TInt);
+	
+	TInt ret(KErrNone);
+	ret=iATSmsMemoryStorage->WhichPreferredMem(storeIndex);
+	if(ret==KErrNone)
+		iATSmsMemoryStorage->Start(aTsyReqHandle,aParam2);
+
+	return ret;
+	}
+
+//*******************************************
+//*		Get SMSP List
+//*******************************************
+TInt CMobileSmsMessaging::GetSmspListPhase1(const TTsyReqHandle aTsyReqHandle,
+                                            TDes8* aParam1,TDes8* aParam2)
+/** Get SMSP List Phase 1 
+ *
+ * If the GetSmspListPhase1L should leave this method takes care of that and 
+ * makes a premature ReqCompleted to the client.
+ *
+ * @param aTsyReqHandle the request ID 
+ * @param aClient The client sends down a handle that is saved together with the 
+ *				  list so the list can be returned to the right client in phase 2.
+ * @param aBufSiz The size of the retrieved network list. The size is set in 
+ * @return error code. 
+ */
+	{
+	LOCAL_LOGTEXT("GetSmspListPhase1","Enter function");
+
+	UNPACK_PCKG(clientId,aParam1,RMobilePhone::TClientId);
+	UNPACK_PCKG(bufSize,aParam2,TInt);
+
+	TRAPD(leaveCode,GetSmspListPhase1L(aTsyReqHandle,clientId,bufSize));
+	return leaveCode;
+	}
+
+																		
+void CMobileSmsMessaging::GetSmspListPhase1L(TTsyReqHandle aTsyReqHandle, 
+											 RMobilePhone::TClientId& aClient, 
+											 TInt& aBufSize)
+/** Get SMSP List Phase 1 
+ *
+ * Phase 1 retrieves the only parameter support - the service centre addess 
+ * with help of AT+CSCA?, 
+ * The memory space needed to store the list is then calculated 
+ * and returned to the client.The returned list is saved to be 
+ * copied to the client in phase 2, when the client has alocated memory for it.	
+ * The actual execution of the AT command (AT+CSCA) is done in the CATSmsGetSCAddress class.
+ *
+ * @param aTsyReqHandle const pointer to the request ID 
+ * @param aClient		The client sends down a handle that is saved together with the 
+ *						list so the list can be returned to the right client in phase 2.
+ * @param aBufSize		The size of the retrieved network. The size is set in CATSmsGetSCAddress::ParseResponseL().
+ * @return error code. 
+ */
+	{
+	LOCAL_LOGTEXT("GetSmspListPhase1L","Enter function");
+
+	CListReadAllAttempt* read=CListReadAllAttempt::NewL(&aClient,aTsyReqHandle);
+	CleanupStack::PushL(read);
+
+	iSmspListInfo.iBufSize = &aBufSize;
+	iSmspListInfo.iBufPtr = &(read->iListBuf);
+	iGetSmspList->AppendL(read);
+
+	iATSmsGetSCAddress->ExecuteCommand(aTsyReqHandle, &iSmspListInfo); 
+
+	CleanupStack::Pop(read);
+	}
+
+TInt CMobileSmsMessaging::GetSmspListPhase2(const TTsyReqHandle aTsyReqHandle,
+                                            TDes8* aParam1,TDes8* aParam2)
+/** Get SMSP List phase 2 
+ *
+ * In this metod the list which was retrieved during phase 1 is copied to 
+ * the memory which the client has allocated for this purose.
+ * @param aTsyReqHandle		Const pointer to the request ID 
+ * @param aClient			Handle to the client which list we are looking for.
+ * @param aBuf				Pointer to the memory that the etelmm has allocated. 
+ * @return error code. 
+ */
+	{	
+	LOCAL_LOGTEXT("GetSmspListPhase2","Enter function");
+
+	UNPACK_PCKG(clientId,aParam1,RMobilePhone::TClientId);
+	
+	CListReadAllAttempt* read=NULL;
+	const TInt numberOfLists = iGetSmspList->Count();
+
+	// Find the get SMSP attempt from this client  
+	for (TInt i = 0; i < numberOfLists; ++i)
+		{
+		read = iGetSmspList->At(i);
+		if ((read->iClient.iSessionHandle==clientId.iSessionHandle) &&
+		    (read->iClient.iSubSessionHandle==clientId.iSubSessionHandle))
+			{
+
+			//
+			// We have to check that the listPtr is not NULL as if the phone/modem
+			// responds with a blank service centre listPtr==NULL.
+			CBufBase* listPtr=read->iListBuf;
+			if(listPtr)
+				{
+				TPtr8 bufPtr(listPtr->Ptr(0));
+				aParam2->Copy(bufPtr);						// Copy the streamed list to the client
+				}
+
+			delete read;
+			iGetSmspList->Delete(i);
+			ReqCompleted(aTsyReqHandle,KErrNone);	// Completes the retrieval of a network list succesfully.
+			return KErrNone;
+			}
+		}
+
+	Panic(EIllegalEvent); 
+	return(KErrNotFound);
+	}
+
+TInt CMobileSmsMessaging::CompleteSmspListCancel(const TTsyReqHandle aTsyReqHandle)
+/** CompleteSmspListCancel
+ *
+ * This method is called from the CATSmsGetSCAddress class if a cancel is succesful
+ * It cleans-up the client's stored request data
+ * @param aTsyReqHandle		Const pointer to the request ID 
+ * @return error code. 
+ */
+	{
+	LOGTEXT(_L8("CMobileSmsMessaging::GetSmspListCancel called"));
+	// Remove the read all attempt from iGetSmspList
+	CListReadAllAttempt* read=NULL;
+	for (TInt i=0; i<iGetSmspList->Count(); ++i)
+		{
+		read = iGetSmspList->At(i);
+		if (read->iReqHandle == aTsyReqHandle)
+			{
+			delete read;
+			iGetSmspList->Delete(i);
+			break;
+			}
+		}
+	ReqCompleted(aTsyReqHandle,KErrCancel);
+	return KErrNone;
+	}
+
+TInt CMobileSmsMessaging::StoreSmspList(const TTsyReqHandle aTsyReqHandle, TDes8* aBuffer)
+	{
+	LOGTEXT(_L8("CMobileSmsMessaging::StoreSmspList called"));
+	TInt leaveCode=KErrNone;
+	TRAP(leaveCode, (void)ProcessStoreSmspListL(aTsyReqHandle, aBuffer););
+	return leaveCode;
+	};
+
+TInt CMobileSmsMessaging::ProcessStoreSmspListL(TTsyReqHandle aTsyReqHandle, TDes8* aBuffer)
+	{
+	CMobilePhoneSmspList* smspList=CMobilePhoneSmspList::NewL();
+	CleanupStack::PushL(smspList);
+	
+	smspList->RestoreL(*aBuffer);
+
+	// We only support one entry (the default entry)
+	if (smspList->Enumerate() != 1)
+		ReqCompleted(aTsyReqHandle, KErrNotSupported);
+
+	// Just get first entry - this is default entry contain SC address
+	iSCEntry=smspList->GetEntryL(0);
+
+	iATSmsSetSCAddress->ExecuteCommand(aTsyReqHandle,&(iSCEntry.iServiceCentre));
+
+	CleanupStack::PopAndDestroy(); // smspList
+	return KErrNone;
+	}
+
+
+TBool CMobileSmsMessaging::IsSupportedIPC(const TInt aIpc) const
+	{
+	switch(aIpc)
+		{
+	case EMobileSmsMessagingGetCaps:
+	case EMobileSmsMessagingSetReceiveMode:
+	case EMobileSmsMessagingGetReceiveMode:
+	case EMobileSmsMessagingSendMessage:
+	case EMobileSmsMessagingReceiveMessage:
+	case EMobileSmsMessagingEnumerateMessageStores:
+	case EMobileSmsMessagingGetMessageStoreInfo:
+	case EMobileSmsMessagingGetSmspListPhase1:
+	case EMobileSmsMessagingGetSmspListPhase2:
+	case EMobileSmsMessagingStoreSmspList:
+		return ETrue;
+
+	default:
+		return EFalse;
+		}
+	}