--- 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;
+ }
+ }