diff -r 6b1d113cdff3 -r 6638e7f4bd8f telephonyserverplugins/multimodetsy/Multimode/sms/mSMSMESS.CPP --- 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 -#include // 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*)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(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; iCount(); ++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 +#include // 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*)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(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; iCount(); ++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; + } + }