telephonyserverplugins/multimodetsy/Multimode/sms/mSMSMESS.CPP
branchopencode
changeset 24 6638e7f4bd8f
parent 0 3553901f7fa8
--- a/telephonyserverplugins/multimodetsy/Multimode/sms/mSMSMESS.CPP	Mon May 03 13:37:20 2010 +0300
+++ b/telephonyserverplugins/multimodetsy/Multimode/sms/mSMSMESS.CPP	Thu May 06 15:10:38 2010 +0100
@@ -1,837 +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;
-		}
-	}
+// 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;
+		}
+	}