--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smsprotocols/smsstack/smsprot/Src/smsprot.cpp Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,2140 @@
+// Copyright (c) 2003-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 the CSmsProtocol and its helper classes.
+//
+//
+
+/**
+ @file
+*/
+
+#include <commsdattypesv1_1.h>
+#include <logwrap.h>
+#include "Gsmumsg.h"
+#include "gsmubuf.h"
+#include "Gsmuelem.h"
+#include "gsmunonieoperations.h"
+
+#include "smsprot.h"
+#include "smspfacadestor.h"
+#include "smspmodm.h"
+#include "smspenum.h"
+#include "smspread.h"
+#include "smspdel.h"
+#include "smspproc.h"
+#include "smspmondsk.h"
+#include "smspmain.h"
+#include "smspver.h"
+#include "smsppara.h"
+#include "SmsuBackup.h"
+#include <es_prot_internal.h>
+
+using namespace CommsDat;
+
+//
+// Class implementations
+//
+
+// application port range according to 3GPP TS 23.040 v4.4.0
+// chapters 9.2.3.24.3 and 9.2.3.24.4
+
+const TInt KMin8BitPortNumber = 240;
+const TInt KMax8BitPortNumber = 255;
+
+const TInt KMin16BitPortNumber = 16000;
+const TInt KMax16BitPortNumber = 16999;
+
+
+/**
+ * 2 phase constructor
+ *
+ */
+CSmsProtocolFamily * CSmsProtocolFamily::NewL()
+ {
+ LOGSMSPROT4("CSmsProtocolFamily::NewL [version %d.%d.%d]",
+ KSmsPrtMajorVersionNumber,
+ KSmsPrtMinorVersionNumber,
+ KSmsPrtBuildVersionNumber
+ );
+ return new (ELeave)CSmsProtocolFamily;
+ } // CSmsProtocolFamily::NewL
+
+
+/**
+ * Implementation of the pure virtual CProtocolFamilyBase::Install().
+ * Called by the socket server after creation of this object.
+ * Does nothing.
+ *
+ */
+TInt CSmsProtocolFamily::Install()
+ {
+ LOGSMSPROT1("CSmsProtocolFamily::Install");
+ return KErrNone;
+ } // CProtocolFamilyBase::Install
+
+
+/**
+ * Implementation of the pure virtual CProtocolFamilyBase::Remove().
+ * Called by the socket server before unloading the library for the SMS
+ * protocol family.
+ * Does nothing.
+ *
+ */
+TInt CSmsProtocolFamily::Remove()
+ {
+ LOGSMSPROT1("CSmsProtocolFamily::Remove");
+ return KErrNone;
+ } // CProtocolFamilyBase::Remove
+
+
+/**
+ * Implementation of the pure virtual CProtocolFamilyBase::NewProtocolL().
+ * Called by the socket server to create the CSmsProtocol object.
+ *
+ * @param aSockType not used, assumes datagram.
+ * @param aProtocol not used, assumes KSmsDatagram, the only protocol provided.
+ * @return a new instance of the CSmsProtocol class.
+ *
+ */
+CProtocolBase * CSmsProtocolFamily::NewProtocolL(TUint /*aSockType*/,TUint /*aProtocol*/)
+ {
+ LOGSMSPROT1("CSmsProtocolFamily::NewProtocolL");
+ return CSmsProtocol::NewL();
+ } // CProtocolFamilyBase::NewProtocolL
+
+
+/**
+ * Implementation of the pure virtual CProtocolFamilyBase::ProtocolList().
+ * Called by the socket server during initialisation to retrieve a list
+ * of the protocols we support.
+ * Only KSmsDatagram is supported.
+ *
+ * @return aProtocolList a pointer to an array of protocol description objects
+ * that this function creates and fills in.
+ * @return the number of protocols supported (1).
+ *
+ */
+TUint CSmsProtocolFamily::ProtocolList(TServerProtocolDesc *& aProtocolList)
+ {
+ LOGSMSPROT1("CSmsProtocolFamily::ProtocolList");
+
+ TRAPD(ret, (aProtocolList=new(ELeave) TServerProtocolDesc[1]));
+ if(ret!=KErrNone)
+ {
+ LOGSMSPROT2("WARNING! new TServerProtocolDesc left with %d", ret);
+ return 0;
+ }
+
+ // Datagram protocol
+ aProtocolList[0].iName=KSmsDatagram;
+ aProtocolList[0].iAddrFamily=KSMSAddrFamily;
+ aProtocolList[0].iSockType=KSockDatagram;
+ aProtocolList[0].iProtocol=KSMSDatagramProtocol;
+ aProtocolList[0].iVersion=TVersion(KSmsPrtMajorVersionNumber,KSmsPrtMinorVersionNumber,KSmsPrtBuildVersionNumber);
+ aProtocolList[0].iByteOrder=ELittleEndian;
+ aProtocolList[0].iServiceInfo=KSMSDatagramServiceInfo;
+ aProtocolList[0].iNamingServices=0;
+ aProtocolList[0].iSecurity=KSocketNoSecurity;
+ aProtocolList[0].iMessageSize=KSMSMaxDatagramSize;
+ aProtocolList[0].iServiceTypeInfo=ESocketSupport;
+ aProtocolList[0].iNumSockets=KSMSNumberSockets;
+
+ return 1;
+ } // CProtocolFamilyBase::ProtocolList
+
+
+/**
+ * Constructor (empty)
+ */
+CSmsProtocolFamily::CSmsProtocolFamily()
+ {
+ } // CSmsProtocolFamily::CSmsProtocolFamily
+
+
+/**
+ * The single exported function, called by the socket server to create
+ * an instance of our CProtocolFamilyBase derived class.
+ *
+ */
+EXPORT_C CProtocolFamilyBase* InstallSMS()
+ {
+ LOGSMSPROT1("CSmsProtocolFamily::CSmsProtocolFamily()");
+
+ CSmsProtocolFamily* smsProtocolFamily(NULL);
+
+ TRAP_IGNORE(smsProtocolFamily = CSmsProtocolFamily::NewL());
+
+ return smsProtocolFamily;
+ } // CSmsProtocolFamily::CSmsProtocolFamily
+
+
+//
+// implementation of CSmsProtocol
+//
+
+
+/**
+ * 2 phase constructor.
+ *
+ */
+CSmsProtocol* CSmsProtocol::NewL()
+ {
+ LOGSMSPROT1("CSmsProtocol::NewL()");
+
+ return new (ELeave) CSmsProtocol();
+ } // CSmsProtocol::NewL
+
+
+/**
+ * Destructor, ensures all outstanding queues are empty,
+ * all resource handles are closed, and all allocated memory freed.
+ *
+ */
+CSmsProtocol::~CSmsProtocol()
+ {
+ delete iSmsPhoneInitialization;
+ delete iSmsModemNotification;
+
+ delete iSendQueue;
+ delete iSetBearer; // referenced by iSendQueue
+
+ delete iSmsPDURead;
+ delete iReceiveMode; // referenced by iSmsPDURead
+ delete iSmsPhoneEnumeration;
+ delete iWriteQueue;
+ delete iDeleteQueue;
+
+
+ delete iSmsReadParams;
+ delete iSmsWriteParams;
+ delete iSmsMonitorDiskSpace;
+
+ delete iReassemblyStore;
+
+ if(iSegmentationStore)
+ {
+ iSegmentationStore->Close();
+ delete iSegmentationStore;
+ }
+ iFs.Close();
+
+ iSmsMessaging.Close();
+ iGsmPhone.Close();
+ iEnumerationPhone.Close();
+ iWritePhone.Close();
+ iTelServer.Close();
+ delete iBackupRestoreSession;
+ delete iBootTimer;
+ } // CSmsProtocol::~CSmsProtocol
+
+
+
+/**
+ * Override of CProtocolBase::NewSAPL().
+ * Called by the server to create a new SMS service access point object.
+ *
+ * @param aSocketType the socket type
+ * @leave Leaves if aSocketType is not KSockDatagram.
+ * @leave Leaves if not enough memory is available.
+ * @return a new CSmsProvider object.
+ *
+ */
+CServProviderBase *CSmsProtocol::NewSAPL(TUint aSocketType)
+ {
+ LOGSMSPROT2("*CSmsProtocol::NewSAPL [sockettype=%d]", aSocketType);
+ if (aSocketType!=KSockDatagram)
+ User::Leave(KErrNotSupported);
+ return CSmsProvider::NewL(*this);
+ } // CProtocolBase::NewSAPL
+
+
+/**
+ * Override of CProtocolBase::InitL().
+ * Called by the socket server to allow any resource initialisation
+ * by the protocol.
+ *
+ * The following tasks are performed:
+ * - All member objects constructed (deferred from ConstructL() for efficiency reasons; see comment there)
+ * - TSY Name read from Comms Database
+ * - Event notification state machines started
+ * - Modem checked to see if it is already connected, and if so, a number of
+ * state machines started (otherwise wait until we receive notification of connection).
+ *
+ */
+void CSmsProtocol::InitL(TDesC& /*aTag*/)
+ {
+ LOGSMSPROT1("CSmsProtocol::InitL");
+
+ User::LeaveIfError(iFs.Connect());
+
+ iReassemblyStore=CFacadeSmsReassemblyStore::NewL(iFs, *this);
+ iReassemblyStore->InitL();
+
+ LOGSMSPROT1("CSmsProtocol::InitL Constructing members");
+
+ ReadConfigurableSettingsL();
+
+ iBootTimer = CSmsProtocolBootTimer::NewL(*this);
+ iBootTimer->Start(iSmsSettings.BootTimerTimeout().Int());
+
+ iSegmentationStore=CSmsSegmentationStore::NewL(iFs);
+
+ iSetBearer=CSmspSetBearer::NewL(iSmsSettings, iSmsMessaging, KSmsSessionPriority);
+
+ iReceiveMode = CSmspReceiveMode::NewL(iSmsSettings, iSmsMessaging, iMobileSmsCaps, KSmsSessionPriority);
+
+ iSmsModemNotification=CSmsModemNotification::NewL(*this);
+
+ iSendQueue = CSmspSendQueue::NewL(*this, *iSegmentationStore, iSmsSettings, iMobileSmsCaps, iSmsMessaging, KSmsSessionPriority, *iSetBearer);
+
+ iSmsMonitorDiskSpace=CSmsMonitorDiskSpace::NewL(*this, iSmsMessaging,iFs);
+
+ iSmsPDURead=CSmsPDURead::NewL(*this, iSmsSettings, iSmsMessaging,*iReassemblyStore,*iSegmentationStore, iMobileSmsCaps, KSmsSessionPriority, *iReceiveMode, *iSmsMonitorDiskSpace);
+
+ iSmsPhoneInitialization = new (ELeave) CSmsPhoneInitialization(iSmsMessaging, iGsmPhone, *iSmsPDURead, iMobileSmsCaps, KSmsSessionPriority, iSetBearer);
+
+ iBackupRestoreSession = CBackupAndRestore::NewL(*this);
+
+/* THIS CODE SHOULD NEVER BE NECESSARY - who could have called CProtocolBase::InitL() if not ESOCK, which means
+ * a running C32 already. However, if this is a wrong analysis then reinstate the code but with an explanatory comment
+#if defined (__WINS__)
+ // Make sure C32 is started under WINS
+ TInt ret=StartC32();
+ if (ret!=KErrAlreadyExists)
+ User::LeaveIfError(ret);
+#endif
+*/
+ LOGSMSPROT1("CSmsProtocol::InitL Querying CommDb");
+
+ // Read the global modem ID setting from Cooms Database
+ TUint32 modemId = 0;
+
+
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+ CMDBSession* sess = CMDBSession::NewL(KCDVersion1_2);
+#else
+ CMDBSession* sess = CMDBSession::NewL(KCDVersion1_1);
+#endif
+ CleanupStack::PushL(sess);
+
+ CMDBField<TUint32>* globalSettingField = new(ELeave) CMDBField<TUint32>(KCDTIdModemPhoneServicesSMS);
+ CleanupStack::PushL(globalSettingField);
+ globalSettingField->SetRecordId(1);
+ globalSettingField->LoadL(*sess);
+ modemId = *globalSettingField;
+ CleanupStack::PopAndDestroy(globalSettingField);
+
+ CMDBField<TDesC>* tsyField = new(ELeave) CMDBField<TDesC>(KCDTIdTsyName);
+ CleanupStack::PushL(tsyField);
+ tsyField->SetRecordId(modemId);
+ tsyField->LoadL(*sess);
+ iGsmTsyName = *tsyField;
+ CleanupStack::PopAndDestroy(tsyField);
+
+ CleanupStack::PopAndDestroy(sess);
+
+#ifdef _SMS_LOGGING_ENABLED
+ TBuf8<KCommsDbSvrMaxFieldLength> buf8;
+ buf8.Copy(iGsmTsyName);
+ LOGSMSPROT3("CSmsProtocol::InitL [modemId=%d tsy=%S]",
+ modemId, &buf8);
+#endif
+
+ // Start event notification state machines
+ iSmsModemNotification->Start();
+
+ // Intialise the SmsStack to the state that the phone has been found in
+ iModemDetection=iSmsModemNotification->ModemState();
+
+ if (iModemDetection == RPhone::EDetectedPresent && !iBackupRestoreSession->IsBackupOrRestoreInProgress())
+ {
+ DoPowerUpL(); //Call the leaving version because powering up must work here
+ }
+ else
+ {
+ PowerDown();
+ }
+
+ //
+ // Define the Disk Space Monitor P&S variable...
+ //
+ TInt ret;
+
+ TSecurityPolicy readPolicy(ECapabilityReadDeviceData);
+ TSecurityPolicy writePolicy(ECapabilityWriteDeviceData);
+
+ ret = RProperty::Define(KUidPSSMSStackCategory, KUidPSSMSStackDiskSpaceMonitorKey,
+ KUidPSSMSStackDiskSpaceMonitorKeyType, readPolicy, writePolicy);
+ if (ret != KErrNone && ret != KErrAlreadyExists)
+ {
+ User::Leave(ret);
+ }
+
+ User::LeaveIfError(RProperty::Set(KUidPSSMSStackCategory,
+ KUidPSSMSStackDiskSpaceMonitorKey, ESmsDiskSpaceAvailable));
+ } // CProtocolBase::InitL
+
+
+/**
+ * Override of CProtocolBase::StartL().
+ * Called by the socket server to indicate all bindings are complete
+ * and that datagram processing can begin.
+ *
+ * Binding is not supported so this indication is not important to us.
+ *
+ */
+void CSmsProtocol::StartL(void)
+ {
+ LOGSMSPROT1("CSmsProtocol::StartL");
+ } // CSmsProtocol::StartL
+
+
+/**
+ * Override of CProtocolBase::Identify().
+ * Called by the socket server to obtain a description of the SMS protocol.
+ *
+ */
+void CSmsProtocol::Identify(TServerProtocolDesc *aDesc)const
+ {
+ LOGSMSPROT1("CSmsProtocol::Identify");
+
+ aDesc->iName=KSmsDatagram;
+ aDesc->iAddrFamily=KSMSAddrFamily;
+ aDesc->iSockType=KSockDatagram;
+ aDesc->iProtocol=KSMSDatagramProtocol;
+ aDesc->iVersion=TVersion(KSmsPrtMajorVersionNumber,KSmsPrtMinorVersionNumber,KSmsPrtBuildVersionNumber);
+ aDesc->iByteOrder=ELittleEndian;
+ aDesc->iServiceInfo=KSMSDatagramServiceInfo;
+ aDesc->iNamingServices=0;
+ aDesc->iSecurity=KSocketNoSecurity;
+ aDesc->iMessageSize=KSMSMaxDatagramSize;
+ aDesc->iServiceTypeInfo=0;
+ aDesc->iNumSockets=KSMSNumberSockets;
+ } // CProtocolBase::Identify
+
+
+/**
+ * Override of CProtocolBase::NewHostResolverL().
+ * Called by socket server to create a host resolver.
+ * No host resolver service is provided by this SMS protocol.
+ *
+ * @leave Panics if called.
+ *
+ */
+CHostResolvProvdBase *CSmsProtocol::NewHostResolverL()
+ {
+ // Ignore in code coverage - not intended to be used
+ BULLSEYE_OFF
+ LOGSMSPROT1("CSmsProtocol::NewHostResolverL");
+ SmspPanic(ESmspCantCreateHostResolver);
+ return NULL;
+ BULLSEYE_RESTORE
+ }
+
+/**
+ * Override of CProtocolBase::NewServiceResolverL().
+ * Called by socket server to create a new service resolver.
+ * Not supported by this protocol.
+ *
+ * @leave Panics if called.
+ *
+ */
+CServiceResolvProvdBase *CSmsProtocol::NewServiceResolverL()
+ {
+ // Ignore in code coverage - not intended to be used
+ BULLSEYE_OFF
+ LOGSMSPROT1("*CSmsProtocol::NewServiceResolverL");
+ SmspPanic(ESmspCantCreateServiceResolver);
+ return NULL;
+ BULLSEYE_RESTORE
+ }
+
+/**
+ * Override of CProtocolBase::NewNetDatabaseL().
+ * Called by socket server to create a new network database.
+ * Not supported by this protocol.
+ *
+ * @leave Panics if called.
+ *
+ */
+CNetDBProvdBase* CSmsProtocol::NewNetDatabaseL()
+ {
+ // Ignore in code coverage - not intended to be used
+ BULLSEYE_OFF
+ LOGSMSPROT1("CSmsProtocol::NewNetDatabaseL");
+ SmspPanic(ESmspCantCreateNetDatabase);
+ return NULL;
+ BULLSEYE_RESTORE
+ }
+
+/**
+ * Override of CProtocolBase::BindL().
+ * Called by next protocol above wishing to bind to the SMS protocol.
+ * Not supported by this protocol.
+ *
+ * @leave Panics if called.
+ *
+ */
+void CSmsProtocol::BindL(CProtocolBase* /*aProtocol*/,TUint /*aId*/)
+ {
+ // Ignore in code coverage - not intended to be used
+ BULLSEYE_OFF
+ LOGSMSPROT1("CSmsProtocol::BindL");
+ SmspPanic(ESmspCantBind);
+ BULLSEYE_RESTORE
+ }
+
+/**
+ * Override of CProtocolBase::BindToL().
+ * Called by socket server when a lower protocol must bind to the
+ * SMS protocol.
+ * Not supported by this protocol.
+ *
+ * @leave Panics if called.
+ *
+ */
+void CSmsProtocol::BindToL(CProtocolBase* /*aProtocol*/)
+ {
+ // Ignore in code coverage - not intended to be used
+ BULLSEYE_OFF
+ LOGSMSPROT1("CSmsProtocol::BindToL");
+ SmspPanic(ESmspCantBindTo);
+ BULLSEYE_RESTORE
+ }
+
+/**
+ * Reads timeout value for send operation from configuration file
+ *
+ * @leave Leaves if configuration file cannot be read
+ * @leave Leaves if value not greater than zero
+ */
+void CSmsProtocol::ReadConfigurableSettingsL()
+ {
+ CESockIniData* ini = NULL;
+ TRAPD(ret, ini=CESockIniData::NewL(_L("smswap.sms.esk")));
+ if(ret!=KErrNone)
+ {
+ LOGSMSPROT2("esk read failed, error code = [%d]", ret);
+ User::Leave(ret);
+ }
+
+ CleanupStack::PushL(ini);
+
+ TInt var(0);
+ if(ini->FindVar(_L("customTimeoutSettings"),_L("sendTryTimeout"),var))
+ {
+ if (var > 0)
+ {
+ LOGSMSPROT2("sendTryTimeout [%d]", var);
+ iSmsSettings.SetSendTryTimeout(var);
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+ }
+
+ if(ini->FindVar(_L("customTimeoutSettings"),_L("bootTimerTimeout"),var))
+ {
+ if (var > 0)
+ {
+ LOGSMSPROT2("bootTimerTimeout [%d]", var);
+ iSmsSettings.SetBootTimerTimeout(var);
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+ }
+
+ CleanupStack::PopAndDestroy(ini);
+ } // CSmsProtocol::ReadConfigurableSettingsL
+
+
+/**
+ * Override of CProtocolBase::Send().
+ * A down call from a protocol bound above to send a datagram.
+ * Not supported by this protocol.
+ *
+ * @leave Panics if called.
+ *
+ */
+TInt CSmsProtocol::Send(TDes8& /*aDes*/,TSockAddr* /*aTo*/,TSockAddr* /*aFrom*/,CProtocolBase* /*aSourceProtocol*/)
+ {
+ // Ignore in code coverage - not intended to be used
+ BULLSEYE_OFF
+ LOGSMSPROT1("CSmsProtocol::Send");
+ SmspPanic(ESmspCantSend);
+ return KErrNotSupported;
+ BULLSEYE_RESTORE
+ }
+
+/**
+ * Override of CProtocolBase::Process().
+ * An up call from a protocol bound below to process a datagram.
+ * Not supported by this protocol.
+ *
+ * @leave Panics if called.
+ *
+ */
+void CSmsProtocol::Process(TDes8& /*aDes*/,TSockAddr* /*aFrom*/,TSockAddr* /*aTo*/,CProtocolBase* /*aSourceProtocol*/)
+ {
+ // Ignore in code coverage - not intended to be used
+ BULLSEYE_OFF
+ LOGSMSPROT1("CSmsProtocol::Process");
+ SmspPanic(ESmspCantProcess);
+ BULLSEYE_RESTORE
+ }
+
+/**
+ * Override of CProtocolBase::GetOption().
+ * A down call from a protocol bound above to get a protocol option.
+ * Not supported by this protocol.
+ *
+ * @leave Panics if called.
+ *
+ */
+TInt CSmsProtocol::GetOption(TUint /*aLevel*/,TUint /*aName*/,TDes8 & /*aOption*/,CProtocolBase* /*aSourceProtocol*/)
+ {
+ // Ignore in code coverage - not intended to be used
+ BULLSEYE_OFF
+ LOGSMSPROT1("CSmsProtocol::GetOption");
+ // SmspPanic(ESmspCantGetOption);
+ return KErrNotSupported;
+ BULLSEYE_RESTORE
+ }
+
+/**
+ * Override of CProtocolBase::SetOption().
+ * A down call from a protocol bound above to set a protocol option.
+ * Not supported by this protocol.
+ *
+ * @leave Panics if called.
+ *
+ */
+TInt CSmsProtocol::SetOption(TUint /*aLevel*/,TUint /*aName*/,const TDesC8& /*option*/,CProtocolBase* /*aSourceProtocol*/)
+ {
+ // Ignore in code coverage - not intended to be used
+ BULLSEYE_OFF
+ LOGSMSPROT1("CSmsProtocol::SetOption");
+ //SmspPanic(ESmspCantSetOption);
+ return KErrNotSupported;
+ BULLSEYE_RESTORE
+ }
+
+/**
+ * Override of CProtocolBase::Error().
+ * An up call from a protocol bound below to indicate an error.
+ * Not supported by this protocol.
+ *
+ * @leave Panics if called.
+ *
+ */
+void CSmsProtocol::Error(TInt /*aError*/,CProtocolBase* /*aSourceProtocol*/)
+ {
+ // Ignore in code coverage - not intended to be used
+ BULLSEYE_OFF
+ LOGSMSPROT1("CSmsProtocol::Error");
+ SmspPanic(ESmspCantError);
+ BULLSEYE_RESTORE
+ }
+
+/**
+ * Adds an observer to the protocol's observer list.
+ * Used by CSmsProvider and CWapSmsProtocol.
+ *
+ * @leave Leaves if not enough memory is available.
+ *
+ */
+void CSmsProtocol::AddSmsMessageObserverL(MSmsMessageObserver& aObserver)
+ {
+ LOGSMSPROT2("CSmsProtocol::AddSmsMessageObserverL [aObserver=0x%08x]", &aObserver);
+ iSmsMessageObserverList.AppendL(&aObserver);
+ SetClosingDown(EFalse);
+ }
+
+/**
+ * Binds an SMS observer to the protocol.
+ * The protocol ensures there are no providers with duplicate addresses.
+ * Used by CSmsProvider::SetLocalName(), and SMS WAP protocol.
+ *
+ * @param aObserver the observer.
+ * @param aSmsAddr the local address of the observer.
+ * @return KErrNone on success, or KErrAlreadyExists if a duplicate exists.
+ *
+ */
+TInt CSmsProtocol::BindSmsMessageObserver(MSmsMessageObserver& aObserver,const TSmsAddr& aSmsAddr)
+ {
+ LOGSMSPROT2("CSmsProtocol::BindSmsMessageObserver 0x%08x", &aObserver);
+ __ASSERT_DEBUG(ObserverIsPresent(aObserver),SmspPanic(ESmspMessageObserverNotFound));
+ TInt ret=KErrNone;
+
+ if (!SmsAddrIsAlreadyUsed(&aObserver,aSmsAddr))
+ {
+ aObserver.SetLocalAddress(aSmsAddr);
+ OrderSmsMessageObserver(aObserver);
+
+ // If not in the powered-up state then the SAR store is closed. When the phone does power-up
+ // then anything waiting in the store will get processed
+ if(CheckPoweredUp() == KErrNone)
+ {
+ //
+ // check the SAR store for any complete messages.
+ // if there are any, send them to the observer
+ //
+ TRAP(ret, ProcessCompleteSmsMessagesL());
+ if(ret != KErrNone)
+ {
+ LOGSMSPROT2("WARNING! CSmsProtocol::ProcessCompleteSmsMessagesL left with %d", ret);
+ }
+ }
+ }
+ else
+ {
+ ret=KErrAlreadyExists;
+ }
+ return ret;
+ } // CSmsProvider::SetLocalName
+
+
+/**
+ * Removes an observer from the observer list.
+ * Observers should at least call this method in their destructors.
+ *
+ */
+void CSmsProtocol::RemoveSmsMessageObserver(const MSmsMessageObserver& aObserver)
+ {
+ LOGSMSPROT2("CSmsProtocol::RemoveSmsMessageObserver 0x%08x", &aObserver);
+ __ASSERT_DEBUG(ObserverIsPresent(aObserver),SmspPanic(ESmspMessageObserverNotFound));
+ TInt index=ObserverIndex(aObserver);
+ iSmsMessageObserverList.Delete(index);
+ }
+
+/**
+ * Handles a request from a SAP to send a SMS message.
+ * Ensures there is a current connection to the modem and queues the message.
+ * Completes with an error immediately if CheckPoweredUp() returns an error code
+ */
+void CSmsProtocol::SendSmsMessage(CSmsMessage* aSmsMessage,MSmsMessageObserver& aObserver,TUint aOptions)
+ {
+ LOGSMSPROT2("CSmsProtocol::SendSmsMessage [aObserver=0x%X]", &aObserver);
+ __ASSERT_DEBUG(ObserverIsPresent(aObserver), SmspPanic(ESmspMessageObserverNotFound));
+
+ // Ensure the modem is connected and initialized
+ const TInt err = CheckPoweredUp();
+
+ if (err != KErrNone)
+ {
+ // Nope, complete immediately
+ aObserver.MessageSendCompleted(err);
+ delete aSmsMessage;
+ }
+ else
+ {
+ iSendQueue->Queue(aSmsMessage, aObserver, aOptions);
+ }
+ }
+
+TInt CSmsProtocol::CheckPoweredUp() const
+ {
+ TInt err = KErrNone;
+
+ if( iModemDetection == RPhone::EDetectedNotPresent || iState == EPoweredDown )
+ {
+ err = KErrDisconnected;
+ }
+ else if( iBackupRestoreSession->IsBackupOrRestoreInProgress() )
+ {
+ err = KErrAccessDenied;
+ }
+ else
+ {
+ err = iSmsPhoneInitialization->Initialized();
+ }
+ if( err != KErrNone )
+ {
+ LOGSMSPROT4("CSmsProtocol::CheckPoweredUp [err=%d, iModemDetection=%d, IsBackupOrRestoreInProgress=%d]", err, iModemDetection, iBackupRestoreSession->IsBackupOrRestoreInProgress());
+ }
+ return err;
+ }
+
+/**
+ * Cancels a previous request to send an SMS message.
+ * Searches the send queue for the message. If it is found at the
+ * head of the queue the sending state machine is cancelled, which
+ * in turn will callback to the protocol and delete the message.
+ * If the message is elsewhere in the queue, it is simply removed
+ * from the queue and the observer notified.
+ *
+ * @leave Panics in DEBUG if the message is not found in the queue.
+ *
+ */
+void CSmsProtocol::CancelSendSmsMessage(MSmsMessageObserver& aObserver,TBool)
+ {
+ LOGSMSPROT2("CSmsProtocol::CancelSendSmsMessage 0x%08x", &aObserver);
+
+ __ASSERT_DEBUG(ObserverIsPresent(aObserver),SmspPanic(ESmspMessageObserverNotFound));
+
+ iSendQueue->CancelObserver(aObserver);
+ } // CSmsProtocol::CancelSendSmsMessage
+
+
+/**
+ * Handles a request from a SAP to enumerate the SMS messages stored on the phone.
+ */
+void CSmsProtocol::EnumeratePhone(MSmsMessageObserver& aObserver)
+ {
+ LOGSMSPROT1("CSmsProtocol::EnumeratePhone");
+ __ASSERT_DEBUG(ObserverIsPresent(aObserver),SmspPanic(ESmspMessageObserverNotFound));
+
+ // Ensure the modem is connected and initialized
+ const TInt err = CheckPoweredUp();
+
+ if (err != KErrNone)
+ aObserver.EnumeratePhoneCompleted(err);
+ else
+ {
+ if (iPhoneEnumerationObserver!=NULL)
+ {
+ aObserver.EnumeratePhoneCompleted(KErrInUse);
+ }
+ else
+ {
+ iPhoneEnumerationObserver=&aObserver;
+ iSmsPhoneEnumeration->Start();
+ }
+ }
+ } // CSmsProtocol::EnumeratePhone
+
+
+/**
+ * Cancels a previous request to enumerate the message on the phone memory.
+ *
+ * @leave Panics in DEBUG if the SAP is invalid.
+ *
+ */
+void CSmsProtocol::CancelEnumeratePhone(MSmsMessageObserver& aObserver)
+ {
+ LOGSMSPROT1("CSmsProtocol::CancelEnumeratePhone");
+
+ __ASSERT_DEBUG(ObserverIsPresent(aObserver), SmspPanic(ESmspMessageObserverNotFound));
+ __ASSERT_DEBUG(iPhoneEnumerationObserver==NULL || &aObserver==iPhoneEnumerationObserver, SmspPanic(ESmspMessageWrongObserver));
+
+ if (iSmsPhoneEnumeration != NULL)
+ {
+ iSmsPhoneEnumeration->Cancel();
+ }
+
+ iReassemblyStore->DeleteEnumeratedSIMEntries();
+
+ (void) aObserver;
+ } // CSmsProtocol::CancelEnumeratePhone
+
+
+TInt CSmsProtocol::ExternalizeEnumeratedMessagesL(CSmsProvider& aProvider,TInt& aCount)
+ {
+ return iReassemblyStore->ExternalizeEnumeratedMessagesL(aProvider, aCount);
+ } // CSmsProtocol::ExternalizeEnumeratedMessagesL
+
+
+/**
+ * Handles a request to write an SMS message to the phone's memory.
+ * Completes with an error immediately if CheckPoweredUp() returns an error code
+ * Otherwise the message is added to the tail of the write queue.
+ */
+void CSmsProtocol::WriteSmsMessage(CSmsMessage* aSmsMessage,MSmsMessageObserver& aObserver)
+ {
+ LOGSMSPROT1("CSmsProtocol::WriteSmsMessage");
+ __ASSERT_DEBUG(ObserverIsPresent(aObserver),SmspPanic(ESmspMessageObserverNotFound));
+
+ const TInt err = CheckPoweredUp();
+
+ if (err != KErrNone)
+ {
+ aObserver.MessageWriteCompleted(err);
+ delete aSmsMessage;
+ }
+ else
+ {
+ iWriteQueue->Queue(aSmsMessage, aObserver, NULL);
+ }
+ } // CSmsProtocol::WriteSmsMessage
+
+
+void CSmsProtocol::CancelWriteSmsMessage(MSmsMessageObserver& aObserver)
+ {
+ LOGSMSPROT1("CSmsProtocol::CancelWriteSmsMessage()");
+
+ if (iWriteQueue != NULL)
+ iWriteQueue->CancelObserver(aObserver);
+ } // CSmsProtocol::CancelWriteSmsMessage
+
+
+/**
+ * Handles a request from a SAP to delete a message from the phone memory.
+ * Completes with an error immediately if CheckPoweredUp() returns an error code
+ * If the cached image of the phone's memory is not yet initialised, complete the
+ * request with KErrNotReady.
+ * Otherwise match the message in the phone image and queue the message for deletion.
+ *
+ * @note aSmsMessage is destroyed from memory on completion.
+ *
+ */
+void CSmsProtocol::DeleteSmsMessage(CSmsMessage* aSmsMessage,MSmsMessageObserver& aObserver)
+ {
+ LOGSMSPROT1("CSmsProtocol::DeleteSmsMessage");
+ __ASSERT_DEBUG(ObserverIsPresent(aObserver),SmspPanic(ESmspMessageObserverNotFound));
+
+ // Ensure the modem is connected and initialized
+ const TInt err = CheckPoweredUp();
+
+ if (err != KErrNone)
+ {
+ // Not connected or backup running
+ aObserver.MessageDeleteCompleted(err);
+ }
+ else if (aSmsMessage->iSlotArray.Count()==0)
+ aObserver.MessageDeleteCompleted(KErrArgument);
+ else
+ DeletePDUs(aSmsMessage->iSlotArray,&aObserver);
+
+ delete aSmsMessage;
+ } // CSmsProtocol::DeleteSmsMessage
+
+
+/**
+ * Cancels a previous request to delete a message from the phone memory.
+ *
+ * @leave Panics in DEBUG if the SAP is invalid.
+ *
+ */
+void CSmsProtocol::CancelDeleteSmsMessage(MSmsMessageObserver& aObserver)
+ {
+ LOGSMSPROT1("CSmsProtocol::CancelDeleteSmsMessage");
+
+ __ASSERT_DEBUG(ObserverIsPresent(aObserver),SmspPanic(ESmspMessageObserverNotFound));
+
+ iDeleteQueue->CancelObserver(aObserver);
+ } // CSmsProtocol::CancelDeleteSmsMessage
+
+
+/**
+ * Handles a request from a SAP to read the SMS parameters stored on the phone.
+ * Completes with an error immediately if CheckPoweredUp() returns an error code
+ * If TSY doesn't support retrieving of parameters, the request is completed
+ * immediately with KErrNotSupported.
+ * The request is completed with KErrNoMemory if creation of CSmsReadParams
+ * object fails.
+ * The request is completed with KErrInUse if another SAP is reading.
+ * Otherwise, the reading process is started.
+ *
+ */
+void CSmsProtocol::ReadSmsParameters(MSmsMessageObserver& aObserver)
+ {
+ LOGSMSPROT1("CSmsProtocol::ReadSmsParameters");
+ __ASSERT_DEBUG(ObserverIsPresent(aObserver),SmspPanic(ESmspMessageObserverNotFound));
+ TInt ret = CheckPoweredUp();
+
+ if (ret == KErrNone)
+ {
+ if(iMobileSmsCaps.iSmsControl & RMobileSmsMessaging::KCapsGetSmspList)
+ {
+ if (iSmsReadParams==NULL)
+ {
+ TRAP(ret,(iSmsReadParams=CSmsReadParams::NewL(*this,iSmsSettings,iSmsMessaging)));
+ }
+ else if (iSmsReadParams->IsActive())
+ {
+ ret = KErrInUse;
+ }
+ }
+ else
+ ret = KErrNotSupported;
+ }
+
+ if(ret != KErrNone)
+ aObserver.ReadSmsParamsCompleted(ret, NULL);
+ else
+ iSmsReadParams->Start(aObserver);
+ } // CSmsProtocol::ReadSmsParameters
+
+
+/**
+ * Cancels a previous request to read SMS parameters.
+ *
+ */
+void CSmsProtocol::CancelReadSmsParams()
+ {
+ LOGSMSPROT1("CSmsProtocol::CancelReadSmsParams");
+
+ if(iSmsReadParams != NULL)
+ iSmsReadParams->Cancel();
+ } // CSmsProtocol::CancelReadSmsParams
+
+
+/**
+ * Handles a request to write an SMS parameters to the phone's memory.
+ * Completes with an error immediately if CheckPoweredUp() returns an error code
+ * If TSY doesn't support retrieving and writing of parameters, the request is completed
+ * immediately with KErrNotSupported.
+ * The request is completed with KErrInUse if another SAP is reading or writing.
+ * The request is completed with KErrNoMemory if creation of CSmsReadParams or
+ * CSmsWriteParams object fails.
+ * Otherwise, the writing process is started.
+ *
+ */
+void CSmsProtocol::WriteSmsParameters(CMobilePhoneSmspList* aMobilePhoneSmspList,MSmsMessageObserver& aObserver)
+ {
+ LOGSMSPROT1("CSmsProtocol::WriteSmsParameters");
+ __ASSERT_DEBUG(ObserverIsPresent(aObserver),SmspPanic(ESmspMessageObserverNotFound));
+
+ TInt ret = CheckPoweredUp();
+
+ if (ret == KErrNone)
+ {
+ if(iMobileSmsCaps.iSmsControl & RMobileSmsMessaging::KCapsGetSmspList && iMobileSmsCaps.iSmsControl & RMobileSmsMessaging::KCapsSetSmspList)
+ {
+ if (iSmsReadParams==NULL)
+ {
+ TRAP(ret,(iSmsReadParams=CSmsReadParams::NewL(*this,iSmsSettings,iSmsMessaging)));
+ }
+ else if (iSmsReadParams->IsActive())
+ ret=KErrInUse;
+ }
+ else
+ ret=KErrNotSupported;
+ }
+
+ if (ret==KErrNone)
+ {
+ if (iSmsWriteParams==NULL)
+ {
+ TRAP(ret,(iSmsWriteParams=CSmsWriteParams::NewL(*this,iSmsSettings,iSmsMessaging,*iSmsReadParams)));
+ }
+ else if (iSmsWriteParams->IsActive())
+ ret=KErrInUse;
+ }
+
+ if (ret==KErrNone)
+ iSmsWriteParams->Start(aObserver,aMobilePhoneSmspList);
+ else
+ {
+ aObserver.WriteSmsParamsCompleted(ret);
+ delete aMobilePhoneSmspList;
+ }
+ } // CSmsProtocol::WriteSmsParameters
+
+
+/**
+ * Cancels a previous request to write SMS parameters.
+ *
+ */
+void CSmsProtocol::CancelWriteSmsParams()
+ {
+ LOGSMSPROT1("CSmsProtocol::CancelWriteSmsParams");
+
+ if(iSmsWriteParams != NULL)
+ iSmsWriteParams->Cancel();
+ } // CSmsProtocol::CancelWriteSmsParams
+
+
+/**
+ * Processes a received SMS message by matching it to an observer and
+ * notifying the observer of the new message.
+ *
+ * If the message has been matched to a message previously sent by the protocol
+ * (i.e. a status report from a previous submit), then the original message and address
+ * are supplied. Matching priority in this case is given to the original sender.
+ *
+ * If the message remains in phone or SIM memory, the message is sent to the "receive any"
+ * observer, otherwise the match based on the message and address of the observer.
+ *
+ * @param aSmsMessage the received message
+ * @param aOriginalSmsAddr pointer to the address of the sender of a previously sent
+ * message matched to the received one (e.g. status report). Null if not matched.
+ * @param aOriginalSmsMessage pointer to a message previously sent matched to the
+ * received one (e.g. status report). Null if not matched.
+ * @param aDes user data for the deliver report acknowledging this message to the SC.
+ * Filled in by the observer.
+ * @return KErrNone if the observer handled the message successfully, otherwise an error.
+ *
+ */
+TInt CSmsProtocol::ProcessMessageL(const CSmsMessage& aSmsMessage,const TSmsAddr* aOriginalSmsAddr,
+ const CSmsMessage* /*aOriginalSmsMessage*/,TDes& aDes)
+ {
+ LOGSMSPROT1("CSmsProtocol::ProcessMessage");
+
+ MSmsMessageObserver* observer=NULL;
+ if (aOriginalSmsAddr!=NULL)
+ {
+ // Status report and original message matched - send to original sender as priority
+ observer=MatchSmsAddressToObserver(*aOriginalSmsAddr);
+ if (observer==NULL)
+ {
+ // Sender no longer present or is read only - match on received message as usual
+ observer=MatchSmsMessageToObserver(aSmsMessage);
+ }
+ }
+ else if (iPhoneEnumerationObserver==NULL || IsAppPortSMS(aSmsMessage ))
+ {
+ // Only match if not currently enumerating or if it is meant for an app port.
+ observer = MatchSmsMessageToObserver(aSmsMessage);
+ }
+
+ LOGSMSPROT2("CSmsProtocol::ProcessMessage [observer=0x%08x]",observer);
+ TInt ret=KErrNone;
+
+ if (observer!=NULL)
+ {
+ TBool isAppPortSms = IsAppPortSMS(aSmsMessage );
+
+ if(isAppPortSms && iBootTimer !=NULL && iBootTimer->IsActive() && observer->GetLocalAddress().SmsAddrFamily() == ESmsAddrRecvAny)
+ {
+ ret = KErrNotReady;
+ }
+ else
+ {
+ ret=observer->MessageReceived(aSmsMessage,aDes);
+ }
+
+ if(ret == KErrNone && (observer->ClientConfirmsMessage() == EFalse) && observer->GetLocalAddress().SmsAddrFamily() != ESmsAddrRecvAny)
+ {
+ iReassemblyStore->DeleteMessageL(aSmsMessage, EFalse);
+ ret=KErrInUse;
+ // used to signal to client that there is nothing to be done on reassembly store
+ // and code different from KErrNone will do - won't be propagated
+ }
+ else if(ret == KErrNotFound && observer->GetLocalAddress().SmsAddrFamily() != ESmsAddrRecvAny)
+ {
+ if ( iBootTimer && !iBootTimer->IsActive() && (aOriginalSmsAddr==NULL || aOriginalSmsAddr->SmsAddrFamily() != ESmsAddrRecvAny))
+ {
+ TSmsAddr addr;
+ addr.SetSmsAddrFamily(ESmsAddrRecvAny);
+ ret = ProcessMessageL(aSmsMessage, &addr, NULL, aDes);
+ }
+ }
+ }
+ else
+ {
+ ret=KErrNotReady; // Observers are not ready
+ }
+ return ret;
+ } // CSmsProtocol::ProcessMessageL
+
+
+/**
+ * Deletes one or more PDUs from phone or SIM memory.
+ * The PDUs are added to the deletion queue. If this queue is empty, the deletion
+ * state machine is started.
+ *
+ * @param aSlotArray
+ */
+void CSmsProtocol::DeletePDUs(const CArrayFix<TGsmSmsSlotEntry>& aSlotArray, MSmsMessageObserver* aObserver)
+ {
+ LOGSMSPROT3("CSmsProtocol::DeletePDUs [count=%d aObserver=0x%08X", aSlotArray.Count(), aObserver);
+ __ASSERT_DEBUG(aSlotArray.Count() != 0, SmspPanic(KSmspSlotArrayEmpty));
+
+ for(TInt i=0; i< aSlotArray.Count() ;i++)
+ {
+ LOGSMSPROT3("CSmsProtocol::DeletePDUs index: %d store %S", aSlotArray[i].iIndex, &aSlotArray[i].iStore);
+ }
+
+ if (iDeleteQueue != NULL && aSlotArray.Count() != 0)
+ {
+ iDeleteQueue->Queue(aSlotArray, aObserver);
+ }
+ } // CSmsProtocol::DeletePDUs
+
+/**
+ * Called when the modem detection state has changed.
+ * If a modem has connection has just been made, a number of event monitoring
+ * state machines are restarted, and as is the bearer setting state machine.
+ * If the the modem connection was lost, outstanding operations are cancelled.
+ *
+ */
+void CSmsProtocol::ModemNotificationCompleted(TInt aStatus,
+ RPhone::TModemDetection aNewState)
+ {
+ LOGSMSPROT3("CSmsProtocol::ModemNotificationCompleted(): aStatus=%d, aNewState=%d",
+ aStatus, aNewState);
+
+ TBool stateChanged = EFalse;
+
+ if (aStatus==KErrNone)
+ {
+ switch (iModemDetection)
+ {
+ //
+ // it goes from OFF to ON
+ //
+ case RPhone::EDetectedNotPresent:
+ case RPhone::EDetectedUnknown:
+ {
+ LOGSMSPROT1("RPhone::EDetectedNotPresent: [OFF -> ON]");
+ if (aNewState==RPhone::EDetectedPresent)
+ {
+ // There is a new modem connection
+ iModemDetection=aNewState;
+ stateChanged = ETrue;
+ }
+ break;
+ }
+ //
+ // it goes from ON to OFF
+ //
+ case RPhone::EDetectedPresent:
+ {
+ LOGSMSPROT1("RPhone::EDetectedPresent: [ON -> OFF]");
+ if (aNewState!=RPhone::EDetectedPresent)
+ {
+ // Ah, lost our modem - cancel outstanding operations
+ iModemDetection=aNewState;
+ stateChanged = ETrue;
+ }
+ break;
+ }
+ default:
+ {
+ __ASSERT_DEBUG(EFalse,SmspPanic(KSmspPanicUnknownModemDetection));
+ }
+ }
+
+ if (iModemDetection == RPhone::EDetectedPresent && !iBackupRestoreSession->IsBackupOrRestoreInProgress())
+ {
+ if (stateChanged || iState == EPoweredDown)
+ {
+ PowerUp();
+ }
+ }
+ else if (stateChanged || iState != EPoweredDown)
+ {
+ PowerDown();
+ }
+ }
+ } // CSmsProtocol::ModemNotificationCompleted
+
+
+void CSmsProtocol::DiskSpaceMonitorStateChange(TSmsDiskSpaceMonitorStatus aStatus)
+/**
+ * Called when the Disk Space Monitor state has changed.
+ */
+ {
+ LOGSMSPROT2("CSmsProtocol::DiskSpaceMonitorStateChange(): aStatus=%d", aStatus);
+
+ RProperty::Set(KUidPSSMSStackCategory, KUidPSSMSStackDiskSpaceMonitorKey, aStatus);
+ } // CSmsProtocol::DiskSpaceMonitorStateChange
+
+
+/**
+ * Called when all message send requests have completed.
+ * Increments the number of segmentation store accesses and purges the store
+ * if it exceeds CSmsProtocol::KNumSARStoreAccessesBeforePurging.
+ */
+void CSmsProtocol::MessageSendCompleted(TInt aStatus)
+ {
+ LOGSMSPROT3("*** CSmsProtocol::MessageSendCompleted [aStatus=%d iNumSegmentationStoreAccesses=%d]", aStatus, iNumSegmentationStoreAccesses);
+ (void) aStatus;
+ iNumSegmentationStoreAccesses++;
+ if (iNumSegmentationStoreAccesses>=KNumSARStoreAccessesBeforePurging)
+ {
+ LOGSMSPROT1("iSegmentationStore->PurgeL Start");
+ TRAPD(ret, iSegmentationStore->PurgeL(iSmsSettings.KSegmentationLifetimeMultiplier(),EFalse));
+ if(ret!=KErrNone)
+ {
+ // we need to close the file because the function
+ // left with the file opened
+ // iSegmentationStore->CloseFile();
+ LOGSMSPROT2("WARNING! iSegmentationStore->PurgeL left with %d", ret);
+ }
+ iNumSegmentationStoreAccesses=0;
+ LOGSMSPROT2("iSegmentationStore->PurgeL End [ret=%d]", ret);
+ }
+ } // CSmsProtocol::KNumSARStoreAccessesBeforePurging
+
+
+/**
+ * Called when the state machine for enumerating messages on the
+ * phone has completed. Notifies the SAP that made the request.
+ *
+ */
+void CSmsProtocol::PhoneEnumerationCompleted(TInt aStatus)
+ {
+ LOGSMSPROT1("CSmsProtocol::PhoneEnumerationCompleted");
+ iPhoneEnumerationObserver->EnumeratePhoneCompleted(aStatus);
+ } // CSmsProtocol::PhoneEnumerationCompleted
+
+
+/**
+ * Called by CProtocolBase::Close() to handle any delayed shutdown.
+ * If there are messages in the deletion queue then the shut down flag
+ * is set, otherwise CProtocolBase::CanClose() is called to finish closing.
+ *
+ */
+void CSmsProtocol::CloseNow()
+ {
+ LOGSMSPROT1("CSmsProtocol::CloseNow");
+ if (iDeleteQueue != NULL && iDeleteQueue->IsActive())
+ SetClosingDown(ETrue);
+ else
+ CanClose();
+ } // CSmsProtocol::CloseNow
+
+
+/**
+ * Private constructor.
+ *
+ */
+CSmsProtocol::CSmsProtocol()
+ :iSmsMessageObserverList(8)
+ ,iModemDetection(RPhone::EDetectedUnknown)
+ {
+ iSmsSettings.SetDeletePDUsFromSIM(EFalse);
+ iSmsSettings.SetDeletePDUsFromPhoneStores(EFalse);
+ iSmsSettings.SetDeletePDUsFromCombinedStores(EFalse);
+ iNext8BitPort=KMin8BitPortNumber;
+ iNext16BitPort=KMin16BitPortNumber;
+ } // CSmsProtocol::CSmsProtocol
+
+
+/**
+ * Returns the index of an observer in the observer list.
+ *
+ */
+TInt CSmsProtocol::ObserverIndex(const MSmsMessageObserver& aObserver) const
+ {
+ LOGSMSPROT1("CSmsProtocol::ObserverIndex()");
+
+ TInt count=iSmsMessageObserverList.Count();
+ TInt index=0;
+ for (; index<count; index++)
+ if (iSmsMessageObserverList[index]==&aObserver)
+ break;
+ return index;
+ } // CSmsProtocol::ObserverIndex
+
+
+/**
+ * Checks if an SMS address type is a duplicate of an existing SAP / observer.
+ *
+ */
+TBool CSmsProtocol::SmsAddrIsAlreadyUsed(const MSmsMessageObserver* aObserver,const TSmsAddr& aSmsAddr)const
+ {
+ LOGSMSPROT1("CSmsProtocol::SmsAddrIsAlreadyUsed()");
+
+ TBool isduplicate=EFalse;
+ TInt count=iSmsMessageObserverList.Count();
+ for (TInt i=0; (i<count) && (!isduplicate); i++)
+ isduplicate=(iSmsMessageObserverList[i]->SmsAddrIsDuplicate(aObserver,aSmsAddr));
+ return isduplicate;
+ } // CSmsProtocol::SmsAddrIsAlreadyUsed
+
+
+/**
+ * A utility class for prioritizing the SMS protocol observers based
+ * on their SMS address type.
+ * A higher priority observer will be given the opportunity to
+ * accept a received messages before one of a lower priority.
+ */
+class TKeySmsObserver : public TKeyArrayFix
+ {
+public:
+ TKeySmsObserver();
+ virtual TInt Compare(TInt aLeft,TInt aRight) const;
+ static TInt SmsAddressPriority(const TSmsAddr& aAddr);
+ };
+
+
+/**
+ * Constructor
+ *
+ */
+TKeySmsObserver::TKeySmsObserver()
+ :TKeyArrayFix(0,ECmpTInt)
+ {
+ iKeyOffset = 0;
+ } // TKeySmsObserver::TKeySmsObserver
+
+
+/**
+ * Static method that returns the priority of a given SMS address.
+ *
+ * @leave Panics on an unknown address type.
+ *
+ */
+TInt TKeySmsObserver::SmsAddressPriority(const TSmsAddr& aAddr)
+ {
+ TSmsAddrFamily fam = aAddr.SmsAddrFamily();
+
+ switch (fam)
+ {
+ case ESmsAddrEmail:
+ return 11;
+ case ESmsAddrApplication8BitPort:
+ return 10;
+ case ESmsAddrApplication16BitPort:
+ return 9;
+ case ESmsAddrMessageIndication:
+ return 8;
+ case ESmsAddrStatusReport:
+ return 7;
+ case ESmsAddrMatchIEI:
+ return 6;
+ case ESmsAddrMatchText:
+ return 5;
+ case ESmsAddrRecvAny:
+ return 4;
+ case ESmsAddrSendOnly:
+ return 3;
+ case ESmsAddrLocalOperation:
+ return 2;
+ case ESmsAddrUnbound:
+ return 1;
+ default:
+ SmspPanic(ESmspUnknownSmsAddressFamily);
+ };
+ return KErrNotFound;
+ } // TKeySmsObserver::SmsAddressPriority
+
+
+/**
+ * Compares two observers.
+ * Override of TKeyArrayFix::Compare() called on to help sort
+ * the observer list based on their address types.
+ *
+ */
+TInt TKeySmsObserver::Compare(TInt aLeft, TInt aRight) const
+ {
+ LOGSMSPROT3("TKeySmsObserver::Compare [left=%d, right=%d]", aLeft, aRight);
+
+ const TInt lhptr = -1; // Left higher priority than right
+ const TInt rhptl = 1; // Right higher priority than left
+
+ MSmsMessageObserver* left = *(MSmsMessageObserver**)At(aLeft);
+ MSmsMessageObserver* right = *(MSmsMessageObserver**)At(aRight);
+
+ const TSmsAddr& leftAddr = left->GetLocalAddress();
+ const TSmsAddr& rightAddr = right->GetLocalAddress();
+
+ TSmsAddrFamily leftFamily = leftAddr.SmsAddrFamily();
+
+
+ TInt leftPriority = SmsAddressPriority(leftAddr);
+ TInt rightPriority = SmsAddressPriority(rightAddr);
+
+ if (leftPriority > rightPriority)
+ return lhptr;
+ if (rightPriority > leftPriority)
+ return rhptl;
+
+ if (leftFamily == ESmsAddrMatchText)
+ {
+ // Longer strings are higher priority than shorter ones
+ TInt rightLen = rightAddr.TextMatch().Length();
+ TInt leftLen = leftAddr.TextMatch().Length();
+ if (leftLen > rightLen)
+ return lhptr;
+ if (rightLen > leftLen)
+ return rhptl;
+ }
+
+ return 0;
+ } // TKeyArrayFix::Compare
+
+
+/**
+ * Re-orders the observer list using TKeySmsObserver to determine priorities.
+ *
+ */
+void CSmsProtocol::OrderSmsMessageObserver(const MSmsMessageObserver& /*aObserver*/)
+ {
+ LOGSMSPROT1("CSmsProtocol::OrderSmsMessageObserver()");
+
+ TKeySmsObserver smsObsKey;
+#ifdef _DEBUG
+ TInt ret=iSmsMessageObserverList.Sort(smsObsKey);
+ __ASSERT_DEBUG(ret==KErrNone,SmspPanic(ESmspCorruptObserverList));
+#else
+ iSmsMessageObserverList.Sort(smsObsKey);
+#endif
+ } // CSmsProtocol::OrderSmsMessageObserver
+
+
+/**
+ * Attempts to match an incoming message to a SAP / observer. Starts with the
+ * highest priority observer.
+ *
+ */
+MSmsMessageObserver* CSmsProtocol::MatchSmsMessageToObserver(const CSmsMessage& aSmsMessage)
+ {
+ LOGSMSPROT1("CSmsProtocol::MatchSmsMessageToObserver()");
+
+ TInt count=iSmsMessageObserverList.Count();
+ for (TInt i=0;i<count;i++)
+ {
+ MSmsMessageObserver* obs = iSmsMessageObserverList[i];
+ if (IsMatch(obs->GetLocalAddress(),aSmsMessage))
+ return obs;
+ }
+ return NULL;
+ } // CSmsProtocol::MatchSmsMessageToObserver
+
+
+/**
+ * Tries to match an SMS address to a SAP / observer. Starts with the highest
+ * priority observer.
+ *
+ */
+MSmsMessageObserver* CSmsProtocol::MatchSmsAddressToObserver(const TSmsAddr& aAddr)
+ {
+ LOGSMSPROT1("CSmsProtocol::MatchSmsAddressToObserver()");
+
+ TInt count=iSmsMessageObserverList.Count();
+ for (TInt i=0;i<count;i++)
+ {
+ MSmsMessageObserver* obs = iSmsMessageObserverList[i];
+ if (obs->GetLocalAddress()==aAddr)
+ return obs;
+ }
+ return NULL;
+ } // CSmsProtocol::MatchSmsAddressToObserver
+
+
+/**
+ * Static function checks if a message is matched to a given SMS address type. Used by
+ * MatchSmsMessageToObserver() to find a matching observer for the message.
+ *
+ */
+TBool CSmsProtocol::IsMatch(const TSmsAddr& aSmsAddr, const CSmsMessage& aSmsMessage)
+ {
+ LOGSMSPROT1("CSmsProtocol::IsMatch()");
+
+ TSmsAddrFamily family = aSmsAddr.SmsAddrFamily();
+
+ switch(family)
+ {
+ case (ESmsAddrUnbound):
+ case (ESmsAddrSendOnly):
+ case(ESmsAddrLocalOperation):
+ return EFalse;
+
+ case(ESmsAddrApplication8BitPort ):
+ {
+ return (MatchApplicationPort(aSmsMessage,aSmsAddr.Port(),EFalse));
+ }
+
+ case (ESmsAddrApplication16BitPort ):
+ {
+ return(MatchApplicationPort(aSmsMessage,aSmsAddr.Port(),ETrue));
+ }
+
+ case (ESmsAddrMessageIndication):
+ {
+ if (MatchInformationElement(aSmsMessage,CSmsInformationElement::ESmsIEISpecialSMSMessageIndication))
+ return ETrue;
+ if (aSmsMessage.SmsPDU().DataCodingSchemePresent())
+ {
+ TSmsDataCodingScheme::TSmsDCSBits7To4 bits7to4 = aSmsMessage.SmsPDU().Bits7To4();
+ switch (bits7to4)
+ {
+ case TSmsDataCodingScheme::ESmsDCSMessageWaitingIndicationDiscardMessage:
+ case TSmsDataCodingScheme::ESmsDCSMessageWaitingIndication7Bit:
+ case TSmsDataCodingScheme::ESmsDCSMessageWaitingIndicationUCS2:
+ return ETrue;
+ default:
+ break;
+ }
+ }
+ // CPHS Implementation of message waiting indicator (CPHS Phase 2)
+ TGsmSmsTelNumber address;
+ aSmsMessage.ParsedToFromAddress(address);
+
+ //as far as I can see you can't get the npi from the address. (==0?)
+ //might want to compare the content of the tel number with the spec to make sure
+ //that we are dealing with a cphs message !
+
+ if((address.iTypeOfAddress.TON() == EGsmSmsTONAlphaNumeric) &&
+ (address.iTelNumber.Length() == 4) &&
+ ((address.iTelNumber[2] & 0x7E) == 0x10) &&// x001 000x constant value
+ ((address.iTelNumber[3] & 0x7E) == 0x00) )// x000 000x constant value
+ return ETrue; // This means that the SMS received is a Message Waiting indication
+ return EFalse;
+ }
+
+ case (ESmsAddrStatusReport):
+ {
+ LOGSMSPROT1("TSmsDataCodingScheme::ESmsDCSMessageWaitingIndicationDiscardMessage:");
+ if (aSmsMessage.Type() == CSmsPDU::ESmsStatusReport)
+ return ETrue;
+ }
+ break;
+ case (ESmsAddrMatchIEI):
+ {
+ return (MatchInformationElement(aSmsMessage,CSmsInformationElement::TSmsInformationElementIdentifier(aSmsAddr.IdentifierMatch())));
+ }
+ case (ESmsAddrMatchText):
+ {
+ TBuf<TSmsAddr::EMaxTextMatchLength> textMatch;
+ textMatch.Copy(aSmsAddr.TextMatch());
+ TBuf<TSmsAddr::EMaxTextMatchLength> smsMsgBuf;
+ TInt bufferLen = aSmsMessage.Buffer().Length();
+ bufferLen = Min(bufferLen,textMatch.Length());
+ aSmsMessage.Buffer().Extract(smsMsgBuf,0,bufferLen);
+ if (textMatch.CompareF(smsMsgBuf)==KErrNone)
+ return ETrue;
+ return EFalse;
+ }
+ case (ESmsAddrEmail):
+ {
+ if(aSmsMessage.IsEmailHeader())
+ return ETrue;
+ break;
+ }
+ case (ESmsAddrRecvAny):
+ return ETrue;
+ default:
+ return EFalse;
+
+ }
+ return EFalse;
+ } // CSmsProtocol::IsMatch
+
+/**
+ * Static function checks if a message contains a given port. Used by IsMatch()
+ * to determine if an SMS address type matches an application port.
+ *
+ */
+TBool CSmsProtocol::MatchApplicationPort(const CSmsMessage& aSmsMessage,TUint aPort,TBool a16Bit)
+ {
+ LOGSMSPROT1("CSmsProtocol::MatchApplicationPort");
+
+ if (!aSmsMessage.SmsPDU().UserDataPresent())
+ return EFalse;
+
+ const CSmsPDU& Pdu = aSmsMessage.SmsPDU();
+ TInt ToPort = 0;
+ TInt FromPort = 0;
+ TBool Is16BitPorts = 0;
+
+ Pdu.ApplicationPortAddressing(ToPort,FromPort,&Is16BitPorts);
+ if((TInt)aPort == ToPort && Is16BitPorts == a16Bit) return ETrue;
+
+ return EFalse;
+ } // CSmsProtocol::MatchApplicationPort
+
+
+/**
+ * Static function checks if a message contains a given information element. Used by IsMatch()
+ * to determine if an SMS address type matches a message.
+ *
+ */
+TBool CSmsProtocol::MatchInformationElement(const CSmsMessage& aSmsMessage, CSmsInformationElement::TSmsInformationElementIdentifier aIeVal)
+ {
+ LOGSMSPROT1("CSmsProtocol::MatchInformationElement");
+
+ if (!aSmsMessage.SmsPDU().UserDataPresent())
+ return EFalse;
+
+ TInt count=aSmsMessage.SmsPDU().UserData().NumInformationElements();
+ for (TInt i=0; i<count; i++)
+ {
+ TInt identifier=aSmsMessage.SmsPDU().UserData().InformationElement(i).Identifier();
+ if (identifier==aIeVal)
+ return ETrue;
+ }
+ return EFalse;
+ } // CSmsProtocol::MatchInformationElement
+
+
+/**
+ * Searches the reassembly store for complete messages and tries to match
+ * them to an observer. If a match is found the message is passed to
+ * the observer and deleted from the store, otherwise it's left in store.
+ * Called when a new observer is added or a PDU has been received and
+ * successfully processed.
+ *
+ */
+void CSmsProtocol::ProcessCompleteSmsMessagesL()
+ {
+ LOGSMSPROT1("CSmsProtocol::ProcessCompleteSmsMessagesL");
+
+ if(iPhoneEnumerationObserver) return;
+
+ iReassemblyStore->ProcessCompleteSmsMessagesL(*this, iSmsPDURead->CurrentMessage());
+ } // CSmsProtocol::ProcessCompleteSmsMessagesL
+
+
+/**
+ * Called when the state machine for processing a received PDU has completed.
+ * The reassembly store access count is incremented and purged if it exceeds
+ * CSmsProtocol::KNumSARStoreAccessesBeforePurging.
+ * The completed entry is removed from the processing queue and if the queue is
+ * not empty, and the processing state machinery is started for the next entry.
+ *
+ */
+void CSmsProtocol::MessageReadedSuccessfully()
+ {
+ LOGSMSPROT1("CSmsProtocol::MessageReadedSuccessfully");
+ TRAPD(ret,ProcessCompleteSmsMessagesL());
+ if(ret!=KErrNone)
+ {
+ LOGSMSPROT2("WARNING! CSmsProtocol::ProcessCompleteSmsMessagesL left with %d", ret);
+ }
+
+ iNumReassemblyStoreAccesses++;
+ if(iNumReassemblyStoreAccesses>=KNumSARStoreAccessesBeforePurging)
+ {
+ TRAP(ret, iReassemblyStore->PurgeL(iSmsSettings.ReassemblyLifetime(),EFalse));
+
+ if(ret!=KErrNone)
+ {
+ LOGSMSPROT2("WARNING! iReassemblyStore->PurgeL left with %d", ret);
+ }
+
+ iNumReassemblyStoreAccesses=0;
+ }
+ if(CheckPoweredUp() == KErrNone )
+ iSmsPDURead->ResumeSmsReception();
+ } // CSmsProtocol::MessageReadedSuccessfully
+
+
+/**
+ * method to delete sms from the reastore
+ */
+void CSmsProtocol::DeleteSMSFromReaStoreL(const CSmsMessage& aSmsMessage)
+ {
+ LOGSMSPROT1("CSmsProtocol::DeleteSMSFromReaStoreL entry");
+ if (aSmsMessage.Type() == CSmsPDU::ESmsStatusReport)
+ {
+ LOGSMSPROT1("CSmsProtocol::DeleteSMSFromReaStoreL it's SR");
+ return;
+ }
+
+ TSmsDataCodingScheme::TSmsClass msgClass;
+
+ if (aSmsMessage.SmsPDU().DataCodingSchemePresent() && aSmsMessage.SmsPDU().Class(msgClass))
+ {
+ if (msgClass == TSmsDataCodingScheme::ESmsClass0)
+ {
+ if (!aSmsMessage.IsComplete())
+ {
+ CIncompleteClass0MessageInfo& incompleteClass0MsgInfo = (CIncompleteClass0MessageInfo &) aSmsMessage.GetOperationsForNonIEL(ESmsIncompleteClass0MessageParameter);
+ // Retrieve incomplete class 0 message information & process
+ TInt startPos, endPos;
+ TBool isLastMessage;
+ incompleteClass0MsgInfo.GetIncompleteMessageInfoL(startPos, endPos, isLastMessage);
+ if (!isLastMessage)
+ {
+ /*
+ Only in this condition set incomplete message as forwarded
+ which internally will remove the PDUs from pre-allocated file.
+ */
+ LOGSMSPROT1("CSmsProtocol::DeleteSMSFromReaStoreL Incomplete Message Not last segment");
+ iReassemblyStore->SetIncompleteMessageForwardedToClientL(aSmsMessage);
+ return;
+ }
+ }
+ }
+ }
+ iReassemblyStore->DeleteMessageL(aSmsMessage, ETrue);
+
+ LOGSMSPROT1("CSmsProtocol::DeleteSMSFromReaStoreL exit");
+ } // CSmsProtocol::DeleteSMSFromReaStoreL
+
+
+/**
+ * Used to notify observer of the change in state of the modem connection.
+ * Send only observers are not notified (why?).
+ */
+void CSmsProtocol::NotifyMessageObservers(TInt aStatus)
+ {
+ LOGSMSPROT1("CSmsProtocol::NotifyMessageObservers");
+
+ TInt count=iSmsMessageObserverList.Count();
+ LOGSMSPROT3("CSmsProtocol::NotifyMessageObservers [count=%d, aStatus=%d]",count, aStatus);
+ for (TInt index=0; index<count; index++)
+ {
+ MSmsMessageObserver* observer=iSmsMessageObserverList[index];
+ TSmsAddrFamily fam = observer->GetLocalAddress().SmsAddrFamily();
+ LOGSMSPROT2("CSmsProtocol::NotifyMessageObservers [family=%d]", fam);
+ switch (fam)
+ {
+ case ESmsAddrMessageIndication:
+ case ESmsAddrStatusReport:
+ case ESmsAddrMatchIEI:
+ case ESmsAddrMatchText:
+ case ESmsAddrEmail:
+ case ESmsAddrRecvAny:
+ case ESmsAddrLocalOperation:
+ case ESmsAddrApplication8BitPort:
+ case ESmsAddrApplication16BitPort:
+ {
+ observer->ModemNotificationCompleted(aStatus);
+ break;
+ }
+ case ESmsAddrSendOnly:
+ case ESmsAddrUnbound:
+ break;
+ default:
+ SmspPanic(ESmspPanicAddrFamilyNotAllowed);
+ }
+ }
+ } // CSmsProtocol::NotifyMessageObservers
+
+
+void CSmsProtocol::PowerUp()
+ {
+ LOGSMSPROT2("CSmsProtocol::PowerUp [iState=%d]", iState);
+ __ASSERT_DEBUG(iState == EPoweredDown, SmspPanic(KSmspPanicUnexpectedState));
+
+ if (iState == EPoweredDown)
+ {
+ TRAPD(err, DoPowerUpL());
+
+ if (err != KErrNone)
+ {
+ LOGSMSPROT3("WARNING: CSmsProtocol::DoPowerUpL left [err=%d iState=%d]", err, iState);
+ __ASSERT_DEBUG(iState == EPoweredDown, SmspPanic(KSmspPanicUnexpectedState));
+ PowerDown();
+ }
+ }
+ } // CSmsProtocol::PowerUp
+
+
+/**
+ * Handles the event of the modem powering on (when it had been powered off).
+ * Does the following...
+ * - The TSY loaded
+ * - ETEL resource handles initialised
+ * - ETEL parameters set and retrieved
+ * - A number of state machines started
+ *
+ */
+void CSmsProtocol::DoPowerUpL()
+ {
+ LOGSMSPROT1("CSmsProtocol::DoPowerUpL");
+ __ASSERT_DEBUG(iModemDetection==RPhone::EDetectedPresent,SmspPanic(KSmspPhoneHasNotTurnedOn));
+
+ //Open the segmentation and reassembly stores
+
+ iReassemblyStore->OpenStoreL();
+ iSegmentationStore->OpenStoreL();
+ LOGSMSPROT1("CSmsProtocol::DoPowerUpL->PurgeL Start");
+ iReassemblyStore->PurgeL(iSmsSettings.ReassemblyLifetime(), ETrue);
+ LOGSMSPROT1("CSmsProtocol::DoPowerUpL->PurgeL End");
+ LOGSMSPROT1("CSmsProtocol::DoPowerUpL->PurgeL Start");
+ iSegmentationStore->PurgeL(iSmsSettings.KSegmentationLifetimeMultiplier(),EFalse);
+ LOGSMSPROT1("CSmsProtocol::DoPowerUpL->PurgeL End");
+
+ // Connect to ETEL and load the TSY
+ User::LeaveIfError(iTelServer.Connect());
+ User::LeaveIfError(iTelServer.LoadPhoneModule(iGsmTsyName));
+ LOGSMSPROT1("CSmsProtocol::DoPowerUpL Connected to Etel");
+
+ // Find the phone corresponding to this TSY and open a number of handles on it
+ TInt numPhones;
+ User::LeaveIfError(iTelServer.EnumeratePhones(numPhones));
+ TInt i=0;
+ for (; i<numPhones; i++)
+ {
+ RTelServer::TPhoneInfo info;
+ User::LeaveIfError(iTelServer.GetPhoneInfo(i,info));
+ TName tsyName;
+ User::LeaveIfError(iTelServer.GetTsyName(i,tsyName));
+ if (tsyName.CompareF(iGsmTsyName)==KErrNone)
+ {
+ User::LeaveIfError(iGsmPhone.Open(iTelServer,info.iName));
+ User::LeaveIfError(iEnumerationPhone.Open(iTelServer,info.iName));
+ User::LeaveIfError(iWritePhone.Open(iTelServer,info.iName));
+ break;
+ }
+ }
+ __ASSERT_DEBUG(i<numPhones,SmspPanic(ESmspPhoneNotFound));
+ if (iTelServer.SetExtendedErrorGranularity(RTelServer::EErrorExtended)!=KErrNone)
+ User::LeaveIfError(iTelServer.SetExtendedErrorGranularity(RTelServer::EErrorBasic));
+ User::LeaveIfError(iSmsMessaging.Open(iGsmPhone));
+
+ LOGSMSPROT1("CSmsProtocol::DoPowerUpL Opened TSY handles");
+
+ if (iSmsPhoneEnumeration == NULL)
+ iSmsPhoneEnumeration=CSmsPhoneEnumeration::NewL(*this, iSmsSettings, *iReassemblyStore, *iSegmentationStore, iEnumerationPhone, KSmsSessionPriority, *iSmsMonitorDiskSpace);
+
+ if (iWriteQueue == NULL)
+ iWriteQueue = CSmspWriteQueue::NewL(*this, iSmsSettings, iWritePhone,*iSegmentationStore, KSmsSessionPriority);
+
+ if (iDeleteQueue == NULL)
+ iDeleteQueue = CSmspDeleteQueue::NewL(*this,iSmsSettings,iSmsMessaging, KSmsSessionPriority);
+
+ // Start state machines
+ iSmsPhoneInitialization->Start();
+
+ LOGSMSPROT1("CSmsProtocol::DoPowerUpL Started state machines");
+
+ NotifyMessageObservers(KIoctlSelectModemPresent);
+ LOGSMSPROT1("CSmsProtocol::DoPowerUpL Notified message observers");
+
+
+ // Process any waiting messages
+ ProcessCompleteSmsMessagesL();
+
+ iState = EPoweredUp;
+ } // CSmsProtocol::DoPowerUpL
+
+
+/**
+ * Handles the event of the modem powering off (when it had been powered on).
+ * Does the following...
+ * - State mechines cancelled
+ * - Close TSY handles
+ * - Disconnect from Etel
+ *
+ * This function will also be called if PowerUpL() leaves
+ */
+void CSmsProtocol::PowerDown()
+ {
+ LOGSMSPROT1("CSmsProtocol::PowerDown");
+
+ iSetBearer->Cancel();
+ iReceiveMode->Cancel();
+
+ iSendQueue->Cancel();
+
+ iSmsPDURead->Cancel();
+
+ iSmsMonitorDiskSpace->Cancel();
+
+ delete iSmsPhoneEnumeration; //must be deleted because uses iSmsMessaging which is soon closed
+ iSmsPhoneEnumeration = NULL;
+
+ iSmsPhoneInitialization->Cancel();
+
+ if( iSmsReadParams != NULL )
+ {
+ iSmsReadParams->Cancel();
+ }
+ if( iSmsWriteParams != NULL )
+ {
+ iSmsWriteParams->Cancel();
+ }
+
+ delete iWriteQueue; //must be deleted because uses iSmsMessaging which is soon closed
+ iWriteQueue = NULL;
+
+ delete iDeleteQueue; //must be deleted because uses iSmsMessaging which is soon closed
+ iDeleteQueue = NULL;
+
+ LOGSMSPROT1("CSmsProtocol::PowerDown Cancelled state machines");
+
+ NotifyMessageObservers(KIoctlSelectModemNotPresent);
+ LOGSMSPROT1("CSmsProtocol::PowerDown Notified message observers");
+
+ // Close TSY handles
+ iSmsMessaging.Close();
+ iGsmPhone.Close();
+ iEnumerationPhone.Close();
+ iWritePhone.Close();
+ LOGSMSPROT1("CSmsProtocol::PowerDown Closed TSY handles");
+
+ // Disconnect from Etel
+ iTelServer.Close();
+ LOGSMSPROT1("CSmsProtocol::PowerDown Disconnected from Etel");
+
+ iReassemblyStore->Close();
+ iSegmentationStore->Close();
+
+ iState = EPoweredDown;
+ }
+
+void CSmsProtocol::CloseNowWrap()
+ {
+ // Ignore in code coverage - called when PDU delete queue is not
+ // empty and SMS stack is closing down - can only get this situation
+ // when the PDU delete has been initiated by the SMS stack itself
+ // (rather than the client) and the PDUs are still being deleted
+ // when last client disconnects.
+ BULLSEYE_OFF
+ LOGSMSPROT1("CSmsProtocol::CloseNowWrap()");
+
+ if( iDeleteQueue == NULL || !iDeleteQueue->IsActive() )
+ {
+ CloseNow();
+ }
+ BULLSEYE_RESTORE
+ }
+
+void CSmsProtocol::HandleBackupOrRestoreStartingL()
+ {
+ LOGSMSPROT2("CSmsProtocol::HandleBackupOrRestoreStartingL [ModemState=%d]", iSmsModemNotification->ModemState());
+ PowerDown();
+ }
+
+void CSmsProtocol::HandleBackupOrRestoreCompleteL()
+ {
+ LOGSMSPROT2("CSmsProtocol::HandleBackupOrRestoreCompleteL [ModemState=%d]", iSmsModemNotification->ModemState());
+
+ if (iModemDetection == RPhone::EDetectedPresent)
+ {
+ PowerUp();
+ }
+ }
+
+/**
+ * Set the sap port number
+ */
+TBool CSmsProtocol::AllocateLocalAddress(TSmsAddr& aAddr)
+ {
+ LOGSMSPROT1("CSmsProtocol::AllocateLocalAddressL");
+
+ TBool found=EFalse;
+ TUint count=0,attempts=0;
+ TSmsAddr locAddr=aAddr;
+
+ if(locAddr.SmsAddrFamily() == ESmsAddrApplication8BitPort )
+ {
+ count =KMax8BitPortNumber-KMin8BitPortNumber+1;
+ }
+ else if(locAddr.SmsAddrFamily() == ESmsAddrApplication16BitPort )
+ {
+ count =KMax16BitPortNumber-KMin16BitPortNumber+1;
+ }
+
+ for(;!found && attempts < count; ++attempts)
+ {
+ if(locAddr.SmsAddrFamily() == ESmsAddrApplication8BitPort )
+ {
+ locAddr.SetPort(iNext8BitPort++);
+ if(iNext8BitPort > KMax8BitPortNumber)iNext8BitPort=KMin8BitPortNumber;
+ }
+ else if(locAddr.SmsAddrFamily() == ESmsAddrApplication16BitPort )
+ {
+ locAddr.SetPort(iNext16BitPort++);
+ if(iNext16BitPort > KMax16BitPortNumber)iNext8BitPort=KMin16BitPortNumber;
+ }
+ if(!SmsAddrIsAlreadyUsed(NULL,locAddr))found=ETrue;
+ }
+
+ if(found)
+ {
+ aAddr=locAddr;
+ }
+ return found;
+ } // CSmsProtocol::AllocateLocalAddress
+
+/**
+ * Static method that returns the boolean value indicating whether the given
+ * CSmsMessage is for application port.
+ * This function is an utility function which determines the passed sms message
+ * is for application port or not. This function is also used in CFacadeSmsReassemblyStore class.
+ *
+ * @param aSmsMessage reference to CSmsMessage object.
+ *
+ */
+TBool CSmsProtocol::IsAppPortSMS(const CSmsMessage& aSmsMessage)
+ {
+ LOGSMSPROT1("CSmsProtocol::IsAppPortSMS()");
+
+ TSmsAddr addr;
+ addr.SetSmsAddrFamily(ESmsAddrMatchIEI);
+ addr.SetIdentifierMatch(CSmsInformationElement::ESmsIEIApplicationPortAddressing8Bit);
+ if (IsMatch(addr,aSmsMessage))
+ {
+ return ETrue;
+ }
+
+ addr.SetSmsAddrFamily(ESmsAddrMatchIEI);
+ addr.SetIdentifierMatch(CSmsInformationElement::ESmsIEIApplicationPortAddressing16Bit);
+ if (IsMatch(addr,aSmsMessage))
+ {
+ return ETrue;
+ }
+
+ addr.SetSmsAddrFamily(ESmsAddrMatchText);
+ addr.SetTextMatch(_L8("//SCK"));
+ if (IsMatch(addr,aSmsMessage))
+ {
+ return ETrue;
+ }
+
+ return EFalse;
+ } // CSmsProtocol::IsAppPortSMS
+
+
+const RMobilePhone::TMobilePhoneNetworkInfoV1& CSmsProtocol::NetworkInfo() const
+ {
+ LOGSMSPROT1("CSmsProtocol::NetworkInfo()");
+
+ return iSmsPhoneInitialization->NetworkInfo();
+ } // CSmsProtocol::NetworkInfo
+
+
+TBool CSmsProtocol::NetworkInfoAvailable() const
+ {
+ LOGSMSPROT1("CSmsProtocol::NetworkInfoAvailable()");
+
+ return iSmsPhoneInitialization->NetworkInfoAvailable();
+ } // CSmsProtocol::NetworkInfoAvailable
+
+
+// implementation of CSmsProtocolBootTimer
+//
+
+/**
+ * 2 phase contructor
+ *
+ * @param aActive Reference to an CSmsProtocol object
+ */
+CSmsProtocolBootTimer* CSmsProtocolBootTimer::NewL(CSmsProtocol& aSmsProtocol)
+ {
+ LOGSMSPROT1("CSmsProtocolBootTimer::NewL");
+
+ CSmsProtocolBootTimer* self = new(ELeave) CSmsProtocolBootTimer(aSmsProtocol);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/**
+ * D'tor
+ */
+CSmsProtocolBootTimer::~CSmsProtocolBootTimer()
+ {
+ Cancel();
+ }
+
+/**
+ * Start a timeout specified in aTimeIntervalMicroSeconds32
+ */
+void CSmsProtocolBootTimer::Start(const TTimeIntervalMicroSeconds32& aTimeIntervalMicroSeconds32)
+ {
+ LOGSMSPROT1("CSmsProtocolBootTimer::Start");
+ After(aTimeIntervalMicroSeconds32);
+ }
+
+/**
+ * C'tor
+ */
+CSmsProtocolBootTimer::CSmsProtocolBootTimer(CSmsProtocol& aSmsProtocol)
+: CTimer(KSmsSessionPriority), iSmsProtocol(aSmsProtocol)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+/**
+ * Timer completed - cancel the observer
+ */
+void CSmsProtocolBootTimer::RunL()
+ {
+ LOGSMSPROT2("CSmsProtocolBootTimer::RunL [iStatus=%d]", iStatus.Int() );
+ iSmsProtocol.MessageReadedSuccessfully();
+ }