telephonyprotocols/psdagt/src/psdagt.cpp
changeset 0 3553901f7fa8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyprotocols/psdagt/src/psdagt.cpp	Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,1017 @@
+// 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:
+//
+
+/**
+ @file PSDAgt.cpp
+*/
+
+#include <cdbcols.h>
+
+#include "psdagt.h"
+#include "psdstates.h"
+#include "psdlogger.h"
+
+CPsdOutSM* CPsdOutSM::NewL(MAgentNotify& aObserver, CDialogProcessor* aDlgPrc, CCommsDbAccess& aDbAccess)
+/**
+Function creates an outbound connection state machine
+
+@param MAgentObserver& aObserver an observer which will be called back to notify changes in the connection
+@param CDialogProcessor* aDlgPrc a pointer to a dialog processor object for use by the state machine
+@param CCommsDbAccess& aDbAccess a reference to the comm Db access object to allow the state machine to obtain details from CommDb
+@return CPsdOutSM* the newly created object (ownership of the object is passed to the function caller)
+*/
+	{
+	__ASSERT_DEBUG(aDlgPrc,User::Invariant());
+	CPsdOutSM* sm = new (ELeave) CPsdOutSM(aObserver,aDlgPrc,aDbAccess);
+	CleanupStack::PushL(sm);
+	sm->ConstructL();
+	CleanupStack::Pop();
+	return sm;
+	}
+
+CPsdOutSM::CPsdOutSM(MAgentNotify& aObserver, CDialogProcessor* aDlgPrc, CCommsDbAccess& aDbAccess)
+	: CPsdAgentSMBase(aObserver,aDlgPrc,aDbAccess)
+/**
+Constructor
+
+@param MAgentObserver& aObserver an observer which will be called back to notify changes in the connection
+@param CDialogProcessor* aDlgPrc a pointer to a dialog processor object for use by the state machine
+@param CCommsDbAccess& aDbAccess a reference to the comm Db access object to allow the state machine to obtain details from CommDb
+*/
+	{}
+
+CPsdOutSM::~CPsdOutSM()
+/**
+Destructor
+*/
+	{}
+
+void CPsdOutSM::ConstructL()
+/**
+2nd phase construction of the outgoing state machine
+creates the initial state of the state machine
+*/
+	{
+	CPsdAgentSMBase::ConstructL();
+	iState = new (ELeave) CPsdOutInit(this,this,this);
+	}
+
+TCommDbConnectionDirection CPsdOutSM::Direction()
+/**
+Function indicates the direction of the connection which is in progress
+
+@return TCommDbConnectionDirection the connection direction
+*/
+	{ return ECommDbConnectionDirectionOutgoing;}
+
+#ifndef INCOMING_NOT_SUPORTED
+
+CPsdInSM* CPsdInSM::NewL(MAgentObserver& aObserver, CDialogProcessor* aDlgPrc, CCommsDbAccess& aDbAccess)
+/**
+Function creates an inbound connection state machine
+
+@param MAgentObserver& aObserver an observer which will be called back to notify changes in the connection
+@param CDialogProcessor* aDlgPrc a pointer to a dialog processor object for use by the state machine
+@param CCommsDbAccess& aDbAccess a reference to the comm Db access object to allow the state machine to obtain details from CommDb
+@return CPsdInSM* the newly created object (ownership of the object is passed to the function caller)
+*/
+	{
+	__ASSERT_DEBUG(aDlgPrc,User::Invariant());
+	CPsdInSM* sm = new (ELeave) CPsdInSM(aObserver,aDlgPrc,aDbAccess);
+	CleanupStack::PushL(sm);
+	sm->ConstructL();
+	CleanupStack::Pop();
+	return sm;
+	}
+
+CPsdInSM::CPsdInSM(MAgentObserver& aObserver, CDialogProcessor* aDlgPrc, CCommsDbAccess& aDbAccess)
+	: CPsdAgentSMBase(aObserver,aDlgPrc,aDbAccess)
+/**
+Constructor
+
+@param MAgentObserver& aObserver an observer which will be called back to notify changes in the connection
+@param CDialogProcessor* aDlgPrc a pointer to a dialog processor object for use by the state machine
+@param CCommsDbAccess& aDbAccess a reference to the comm Db access object to allow the state machine to obtain details from CommDb
+*/
+	{}
+
+CPsdInSM::~CPsdInSM()
+/**
+Destructor
+*/
+	{}
+
+void CPsdInSM::ConstructL()
+/**
+2nd phase construction of the incoming state machine
+creates the initial state of the state machine
+*/
+	{
+	CPsdAgentSMBase::ConstructL();
+	iState = new (ELeave) CPsdInInit(this,this,this);
+	}
+
+TCommDbConnectionDirection CPsdInSM::Direction()
+/**
+Function indicates the direction of the connection which is in progress
+
+@return TCommDbConnectionDirection the connection direction
+*/
+	{ return ECommDbConnectionDirectionIncoming;}
+#endif // #ifndef INCOMING_NOT_SUPORTED
+
+CPsdAgentSMBase::CPsdAgentSMBase(MAgentNotify& aObserver, CDialogProcessor* aDlgPrc, CCommsDbAccess& aDbAccess)
+	: CAgentSMBase(aObserver,aDlgPrc,aDbAccess),
+		iIsQoSSupported(ETrue)//let's be optimists 
+/**
+Constructor
+*/
+	{}
+
+void CPsdAgentSMBase::ConstructL()
+/**
+2nd phase construction of the state machine base class
+to be called in the ConstuctL of derived classes.
+The function creates the logging objects and the objects
+that contain the parameters for the Context and the QoS
+*/
+	{
+	iEventLogger=CEventLogger::NewL();
+	iDataLogger=CDataLogger::NewL(this,this);
+	InquireModeL();
+	iConfig=CPsdContextConfig::NewL(*iDb,iNetworkMode);
+	iQoSConfig=CPsdContextQoSConfig::NewL(*iDb,iNetworkMode);
+	}
+
+CPsdAgentSMBase::~CPsdAgentSMBase()
+/**
+Destructor
+*/
+	{
+	iPacketNetwork.Close();
+	iContext.Close();
+	iQoS.Close();
+	iPhone.Close();
+	iTelServer.Close();
+	delete iQoSConfig;
+	delete iConfig;
+	delete iDataLogger;
+	delete iEventLogger;
+	iEventLogger=0;
+	}
+
+
+TInt CPsdAgentSMBase::GetExcessData(TDes8& /*aBuffer*/)
+/**
+This is only valid for CSD
+To retrieve data for the SM, and accessor functions for the state objects to use.
+
+@param contains data retrieved from the agent for SM.
+@return KErrNotSupported if data is not retrieved.
+*/
+	{
+	return KErrNotSupported;
+	}
+
+TInt CPsdAgentSMBase::Notification(TNifToAgentEventType /*aEvent*/, TAny* /*aInfo*/)
+/**
+No NIF to AGENT notifications supported by PSDAGX
+Act on / reply to NifMan's notification requests
+
+@param Type of event from Nifman to Agent.
+@param Information about the Agent
+@return KErrNotSupported if Event type does not exist.
+*/
+	{
+	return KErrNotSupported;
+	}
+
+void CPsdAgentSMBase::GetLastError(TInt& aError)
+/**
+If the context is still open, request last error, otherwise the last error will
+have been obtained on closure.
+
+@param error code if the context is not open.
+*/
+	{
+	if (iContext.SubSessionHandle())
+		iContext.GetLastErrorCause(aError);
+	else
+		aError=iErrorCause;
+	}
+	
+TBool CPsdAgentSMBase::IsIncomingAllowedL() const
+/**
+Function to allow clients to inquire if incomming connections are allowed
+
+@return ETrue if incomming connections allowed else EFalse
+*/
+	{
+	// Hurricane does not support Incoming connections so hard code this response to False
+#ifdef INCOMING_NOT_SUPORTED
+	return EFalse;
+#else
+	// Note - the code below should be used when incoming connections are supported
+	TUint32 allowed;
+	iDb->GetGlobalL(TPtrC(ACCEPT_INCOMING_GPRS),allowed);
+	return (TBool)allowed;
+#endif
+	}
+
+void CPsdAgentSMBase::GetRemotePartyL(TDes& aRemoteParty) const
+/**
+Function to allow clients to inquire the name of the remote party in the connection
+
+@param TDes& aRemoteParty reference to a descriptor into which the remote party name will be written.
+*/
+	{
+	iDb->GetDesL(TPtrC(KGeneralServiceTable),TPtrC(COMMDB_NAME),aRemoteParty);
+	}
+
+void CPsdAgentSMBase::InquireModeL()
+/**
+Internal function to figure out the current mode and set the iNetworkMode
+member appropriately
+*/ 
+	{
+	TBuf<KCommsDbSvrMaxColumnNameLength> serviceType;
+	iDb->GetServiceTypeL(serviceType);
+	if(serviceType == TPtrC(OUTGOING_GPRS))
+		{
+		iNetworkMode = EModeWCDMA;
+		}
+#ifndef INCOMING_NOT_SUPORTED	
+	else if(serviceType == TPtrC(INCOMING_GPRS))
+		{
+		iNetworkMode = EModeWCDMA;
+		}
+#endif // #ifndef INCOMING_NOT_SUPORTED	
+	else
+		{
+		// The service type is not supported by this AGX so leave
+		User::Leave(KErrNotSupported);
+		}
+	}
+
+MAgentStateMachineEnv& CPsdAgentSMBase::BaseEnv() 
+	{ return *this;}
+
+RTelServer& CPsdAgentSMBase::TelServer() 
+	{ return iTelServer;}
+
+RPhone& CPsdAgentSMBase::Phone() 
+	{ return iPhone;}
+
+RPacketService& CPsdAgentSMBase::PacketNetwork() 
+	{ return iPacketNetwork;}
+
+RPacketContext& CPsdAgentSMBase::Context() 
+	{ return iContext;}
+
+TBool CPsdAgentSMBase::IsQoSSupported()const
+	{return iIsQoSSupported;}
+
+void CPsdAgentSMBase::SetQoSSupported(TBool isSupported)
+	{iIsQoSSupported=isSupported;}
+
+RPacketQoS& CPsdAgentSMBase::QoS()
+	{ return iQoS;}
+
+const CPsdContextConfig& CPsdAgentSMBase::Config() const 
+	{ return *iConfig;}
+
+const CPsdContextQoSConfig& CPsdAgentSMBase::QoSConfig() const
+	{return *iQoSConfig;}
+
+TInt& CPsdAgentSMBase::ErrorCause()
+	{ return iErrorCause;}
+
+CEventLogger* CPsdAgentSMBase::Logger() 
+	{ return iEventLogger;}
+
+CDataLogger* CPsdAgentSMBase::DataLogger() 
+	{ return iDataLogger;}
+
+TBool& CPsdAgentSMBase::AmLogging()  
+/**
+@deprecated since logging requests are stored in a queue now
+*/
+	{ return iAmLogging;}
+
+TBool CPsdAgentSMBase::TsyLoaded() const
+	{ return iTsyLoaded;}
+
+void CPsdAgentSMBase::SetTsyLoaded(TBool aStatus)
+	{ iTsyLoaded=aStatus;}
+
+MPsdEnv::TNetworkMode CPsdAgentSMBase::Mode() const
+	{return iNetworkMode;}
+
+CPsdContextConfig* CPsdContextConfig::NewL(CCommsDbAccess& aDbAccess, MPsdEnv::TNetworkMode aMode)
+/**
+Function creates a CPsdContextConfig object
+
+@param CCommsDbAccess& aDbAccess a reference to the comm Db access object to allow the class to obtain details from CommDb
+@param TNetworkMode aMode the mode of the context config parameters to be created.
+@return CPsdContextConfig* the newly created object (ownership of the object is passed to the function caller)
+*/
+	{
+	CPsdContextConfig* self = new(ELeave)CPsdContextConfig(aDbAccess,aMode);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(); //self
+	return self;
+	}
+
+CPsdContextConfig::CPsdContextConfig(CCommsDbAccess& aDbAccess, MPsdEnv::TNetworkMode aMode)
+: iDbAccess(aDbAccess), iMode(aMode)
+	{	
+	}
+
+void CPsdContextConfig::ConstructL()
+/**
+2nd phase construction of CPsdContextConfig calls the appropriate internal construction
+function for the current mode
+*/
+	{
+	if(iMode == MPsdEnv::EModeWCDMA)
+		{
+		GprsConfigConstructL();
+		}
+	}
+
+CPsdContextConfig::~CPsdContextConfig()
+/**
+Destructor
+*/
+	{
+	delete iConfig;
+	delete iPackedConfig;
+	}
+
+const TPacketDataConfigBase& CPsdContextConfig::Config() const
+/**
+Function that returns the current context config parameters as a TPacketDataConfigBase
+
+@return TPacketDataConfigBase& reference to the config parameters. (reurned as the mode agnostic base class)
+*/
+	{
+	return *iConfig;
+	}
+
+TDesC8& CPsdContextConfig::PackedConfig() const
+/**
+Function that returns the current context config parameters packed in a descriptor
+
+@return TDesC8& reference to the config parameters packed in a descriptor.
+*/
+	{
+	return *iPackedConfig;
+	}
+
+TBool CPsdContextConfig::IsConfigSupportedL(const RPacketService& aPacketData, TCommDbConnectionDirection aDirection) const
+/**
+Inquiry function to enquire if the TSY is able to support the current context parameters
+
+@param RPacketService& aPacketData handle to a previously initialised RPacketService object
+@param TCommDbConnectionDirection aDirection the direction of the current connection
+@return TBool returns ETrue if config supported, EFalse otherwise.
+*/
+	{
+	if(!iStaticCaps)
+		{
+		// Only get the caps if they havn't been retrieved before
+		User::LeaveIfError(aPacketData.GetStaticCaps(iStaticCaps,iProtocolType));
+		}
+	TBool result=ETrue;
+	if(iMode == MPsdEnv::EModeWCDMA)
+		{
+		RPacketContext::TContextConfigGPRS& config = *(STATIC_CAST(RPacketContext::TContextConfigGPRS*, iConfig));
+
+		if ( (config.iAnonymousAccessReqd==RPacketContext::ERequired)
+			&&(aDirection == ECommDbConnectionDirectionIncoming) )
+			{
+			result=EFalse;
+			}
+		else if (!(iStaticCaps & RPacketService::KCapsAASupported)
+			&& (config.iAnonymousAccessReqd==RPacketContext::ERequired))
+			{
+			result=EFalse;
+			}
+		else if (!(iStaticCaps & RPacketService::KCapsPdpDataCompSupported)
+			&& (config.iPdpCompression & RPacketContext::KPdpDataCompression))
+			{
+			result=EFalse;
+			}
+		else if (!(iStaticCaps & RPacketService::KCapsPdpHeaderCompSupported)
+			&& (config.iPdpCompression & RPacketContext::KPdpHeaderCompression))
+			{
+			result=EFalse;
+			}
+		}
+	return result;
+	}
+
+
+TBool CPsdContextConfig::TsySupportsDataTransferInfoL(const RPacketService& aPacketData) const
+/**
+Inquiry function to enquire if the TSY is able to support data transfer inquiries
+
+@param RPacketService& aPacketData handle to a previously initialised RPacketService object
+@return TBool returns ETrue if data transfer inquiry supported, EFalse otherwise.
+*/
+	{
+	if(!iStaticCaps)
+		{
+		// Only get the caps if they havn't been retrieved before
+		User::LeaveIfError(aPacketData.GetStaticCaps(iStaticCaps,iProtocolType));
+		}
+	return(iStaticCaps & RPacketService::KCapsGetDataTransferredSupported);
+	}
+
+void CPsdContextConfig::GprsConfigConstructL()
+
+/**
+Internal function that constructs the object if the mode is GPRS
+interogates CommDb and reads the appropriate parameters from there
+
+Relies on SetCurrentSettingsL() having already been called by the controller
+Also expects the service setting to be opened on the correct GPRS Table (outgoing/incoming)
+*/
+	{
+	iConfig=new(ELeave)RPacketContext::TContextConfigGPRS();
+
+	RPacketContext::TContextConfigGPRS& config = *(STATIC_CAST(RPacketContext::TContextConfigGPRS*, iConfig));
+	TUint32 pdptype;
+	iDbAccess.GetIntL(TPtrC(KGeneralServiceTable),TPtrC(GPRS_PDP_TYPE),pdptype);
+	config.iPdpType = (RPacketContext::TProtocolType)pdptype;
+
+	// Save the protocol type seperately for easy access when retreiving static caps
+	iProtocolType = config.iPdpType;
+
+	iDbAccess.GetDesL(TPtrC(KGeneralServiceTable),TPtrC(GPRS_APN),config.iAccessPointName);
+	iDbAccess.GetDesL(TPtrC(KGeneralServiceTable),TPtrC(GPRS_PDP_ADDRESS),config.iPdpAddress);
+	
+	GetGprsCompressionL(config.iPdpCompression);
+	GetGprsAAL(config.iAnonymousAccessReqd);
+
+	iPackedConfig = new(ELeave)TPckg<RPacketContext::TContextConfigGPRS>(config);
+	}
+
+void CPsdContextConfig::GetGprsCompressionL(TUint& aCompression) const
+	{
+	aCompression = 0;
+	TBool isCompression;
+	iDbAccess.GetBoolL(TPtrC(KGeneralServiceTable),TPtrC(GPRS_DATA_COMPRESSION),isCompression);
+	if (isCompression)
+		{
+		aCompression |= RPacketContext::KPdpDataCompression;
+		}
+
+	iDbAccess.GetBoolL(TPtrC(KGeneralServiceTable),TPtrC(GPRS_HEADER_COMPRESSION),isCompression);
+	if (isCompression)
+		{
+		aCompression |= RPacketContext::KPdpHeaderCompression;
+		}
+	}
+
+void CPsdContextConfig::GetGprsAAL(RPacketContext::TAnonymousAccess& aAnonymous) const
+	{	
+	TBool isAnonymous;
+	iDbAccess.GetBoolL(TPtrC(KGeneralServiceTable),TPtrC(GPRS_ANONYMOUS_ACCESS),isAnonymous);
+	if (isAnonymous)
+		aAnonymous=RPacketContext::ERequired;
+	else
+		aAnonymous=RPacketContext::ENotRequired;
+	}
+
+void CPsdContextConfig::GetGprsEdgeL(TBool& aUseEdge) const
+	{	
+	TBool isUseEdge;
+	iDbAccess.GetBoolL(TPtrC(KGeneralServiceTable),TPtrC(GPRS_USE_EDGE),isUseEdge);
+	aUseEdge=isUseEdge;
+	}
+
+TBool CPsdContextConfig::QueryIfConfigAcceptable(TDesC8& aNewConfig) const
+/**
+Function to check if the config passed in the parameter meets the minimum requiremnts
+set in CommDb
+
+@param TDesC8& aNewConfig the config to be checked packed in a descriptor
+@return TBool ETrue if the config passed in is above or equal to the minimum values, EFalse otherwise.
+*/
+	{
+	TBool ret = ETrue;
+	if(iMode == MPsdEnv::EModeWCDMA)
+		{
+		TPckg<RPacketContext::TContextConfigGPRS> configPckg = *((TPckg<RPacketContext::TContextConfigGPRS>*)&aNewConfig);
+		RPacketContext::TContextConfigGPRS& newConfig = configPckg();
+		ret = QueryIfGprsConfigAcceptable(newConfig);
+		}
+	return ret;
+	}
+
+TBool CPsdContextConfig::QueryIfGprsConfigAcceptable(const RPacketContext::TContextConfigGPRS& /*aNewConfig*/) const
+/**
+Internal function to check if the config passed in the parameter meets the minimum required for GPRS
+
+@param RPacketContext::TContextConfigGPRS& aNewConfig the config to be checked against the minimum values
+@return TBool ETrue if the config passed in is above or equal to the minimum values, EFalse otherwise.
+*/
+	{
+	// Apparently the GPRS network has to give you what you asked for otherwise
+	// it will not complete the connection, so just return ETrue
+	return ETrue;
+	}
+
+TBool CPsdContextConfig::QueryIfIncommingConnectionAcceptable(const RPacketContext::TProtocolType& aProtocolType, const RPacketContext::TProtocolAddress& aProtocolAddress) const
+/**
+Inquiry function to enquire if incoming connection is valid
+
+@param RPacketContext::TProtocolType& aProtocolType the protocol type of the incomming connection
+@param RPacketContext::TProtocolAddress& aProtocolAddress the address of the incomming connection
+@return TBool returns ETrue if connection OK, EFalse otherwise.
+*/
+	{
+	if(iMode == MPsdEnv::EModeWCDMA)
+		{
+		RPacketContext::TContextConfigGPRS& config = *(STATIC_CAST(RPacketContext::TContextConfigGPRS*, iConfig));
+		// For GPRS incoming connection the connection must be IP based and the IP address must be static.
+		// The IP address should be the one stored in CommDb
+		if( ((aProtocolType==RPacketContext::EPdpTypeIPv4)||(aProtocolType==RPacketContext::EPdpTypeIPv6)) 
+			&& config.iPdpAddress==aProtocolAddress)
+			{
+			return ETrue;
+			}
+		else
+			{
+			return EFalse;
+			}
+		}
+	return EFalse;
+	}
+
+//======================================================
+//
+// CPsdContextQoSConfig
+//
+//======================================================
+
+CPsdContextQoSConfig* CPsdContextQoSConfig::NewL(CCommsDbAccess& aDbAccess, MPsdEnv::TNetworkMode aMode)
+/**
+Function creates a CPsdContextQoSConfig object
+
+@param CCommsDbAccess& aDbAccess a reference to the comm Db access object to allow the class to obtain details from CommDb
+@param TNetworkMode aMode the mode of the context config parameters to be created.
+@return CPsdContextQoSConfig* the newly created object (ownership of the object is passed to the function caller)
+*/
+	{
+	CPsdContextQoSConfig* self = new(ELeave)CPsdContextQoSConfig(aDbAccess,aMode);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(); //self
+	return self;
+	}
+
+CPsdContextQoSConfig::CPsdContextQoSConfig(CCommsDbAccess& aDbAccess, MPsdEnv::TNetworkMode aMode)
+: iDbAccess(aDbAccess), iMode(aMode)
+	{
+	}
+
+void CPsdContextQoSConfig::ConstructL()
+/**
+2nd phase construction of CPsdContextQoSConfig calls the appropriate internal construction
+function for the current mode
+*/
+	{
+	if(iMode == MPsdEnv::EModeWCDMA)
+		{
+		GprsQoSConfigConstructL();
+		}
+	}
+
+CPsdContextQoSConfig::~CPsdContextQoSConfig()
+/**
+Destructor
+*/
+	{
+	delete iPackedQoSConfig;
+	delete iQoSConfig;
+	}
+
+const TPacketDataConfigBase& CPsdContextQoSConfig::QoSConfig() const
+/**
+Function that returns the current QoS config parameters as a TPacketDataConfigBase
+
+@return TPacketDataConfigBase& reference to the QoS config parameters. (reurned as the mode agnostic base class)
+*/
+	{
+	return *iQoSConfig;
+	}
+
+TDes8& CPsdContextQoSConfig::PackedQoSConfig() const
+/**
+Function that returns the current QoS config parameters packed in a descriptor
+
+@return TDesC8& reference to the QoS config parameters packed in a descriptor.
+*/
+	{
+	return *iPackedQoSConfig;
+	}
+
+void CPsdContextQoSConfig::GprsQoSConfigConstructL()
+/**
+Internal function that constructs the object if the mode is GPRS
+interogates CommDb and reads the appropriate parameters from there
+*/
+	{
+	iQoSConfig=new(ELeave)RPacketQoS::TQoSGPRSRequested();
+	RPacketQoS::TQoSGPRSRequested& qoSConfig = *(STATIC_CAST(RPacketQoS::TQoSGPRSRequested*, iQoSConfig));
+
+
+	TUint32 data;
+	iDbAccess.GetIntL(TPtrC(KGeneralServiceTable),TPtrC(GPRS_REQ_PRECEDENCE),data);
+	qoSConfig.iReqPrecedence	= (RPacketQoS::TQoSPrecedence)data;
+
+	iDbAccess.GetIntL(TPtrC(KGeneralServiceTable),TPtrC(GPRS_REQ_DELAY),data);
+	qoSConfig.iReqDelay		= (RPacketQoS::TQoSDelay)data;
+
+	iDbAccess.GetIntL(TPtrC(KGeneralServiceTable),TPtrC(GPRS_REQ_RELIABILITY),data);
+	qoSConfig.iReqReliability	= (RPacketQoS::TQoSReliability)data;
+
+	iDbAccess.GetIntL(TPtrC(KGeneralServiceTable),TPtrC(GPRS_REQ_PEAK_THROUGHPUT),data);
+	qoSConfig.iReqPeakThroughput = (RPacketQoS::TQoSPeakThroughput)data;
+
+	iDbAccess.GetIntL(TPtrC(KGeneralServiceTable),TPtrC(GPRS_REQ_MEAN_THROUGHPUT),data);
+	qoSConfig.iReqMeanThroughput = (RPacketQoS::TQoSMeanThroughput)data;
+	
+	iDbAccess.GetIntL(TPtrC(KGeneralServiceTable),TPtrC(GPRS_MIN_PRECEDENCE),data);
+	qoSConfig.iMinPrecedence		= (RPacketQoS::TQoSPrecedence)data;
+
+	iDbAccess.GetIntL(TPtrC(KGeneralServiceTable),TPtrC(GPRS_MIN_DELAY),data);
+	qoSConfig.iMinDelay			= (RPacketQoS::TQoSDelay)data;
+
+	iDbAccess.GetIntL(TPtrC(KGeneralServiceTable),TPtrC(GPRS_MIN_RELIABILITY),data);
+	qoSConfig.iMinReliability	= (RPacketQoS::TQoSReliability)data;
+
+	iDbAccess.GetIntL(TPtrC(KGeneralServiceTable),TPtrC(GPRS_MIN_PEAK_THROUGHPUT),data);
+	qoSConfig.iMinPeakThroughput = (RPacketQoS::TQoSPeakThroughput)data;
+
+	iDbAccess.GetIntL(TPtrC(KGeneralServiceTable),TPtrC(GPRS_MIN_MEAN_THROUGHPUT),data);
+	qoSConfig.iMinMeanThroughput = (RPacketQoS::TQoSMeanThroughput)data;
+
+	iPackedQoSConfig = new(ELeave)TPckg<RPacketQoS::TQoSGPRSRequested>(qoSConfig);
+	}
+
+TBool CPsdContextQoSConfig::QueryIfQoSAcceptable(TDesC8& aNewQoS) const
+/**
+Function to check if the QoS config passed in the parameter meets the minimum requiremnts
+set in CommDb
+
+@param TDesC8& aNewQoS the QoS config to be checked packed in a descriptor
+@return TBool ETrue if the QoS config passed in is above or equal to the minimum values, EFalse otherwise.
+*/
+	{
+	TBool ret = ETrue;
+	if(iMode == MPsdEnv::EModeWCDMA)
+		{
+		TPckg<RPacketQoS::TQoSGPRSNegotiated> qoSPckg = *((TPckg<RPacketQoS::TQoSGPRSNegotiated>*)&aNewQoS);
+		RPacketQoS::TQoSGPRSNegotiated& newQoS = qoSPckg();
+		ret = QueryIfGprsQoSAcceptable(newQoS);
+		}
+	return ret;
+	}
+
+TBool CPsdContextQoSConfig::QueryIfGprsQoSAcceptable(const RPacketQoS::TQoSGPRSNegotiated& /*aNewQoS*/) const
+/**
+Internal function to check if the QoS config passed in the parameter meets the minimum required for GPRS
+
+@param RPacketQoS::TQoSGPRSNegotiated& aNewQoS the QoS config to be checked against the minimum values
+@return TBool ETrue if the config passed in is above or equal to the minimum values, EFalse otherwise.
+*/
+	{
+	// Apparently the GPRS network has to give you what you asked for otherwise
+	// it will not complete the connection, so just return ETrue
+	return ETrue;
+	}
+
+//
+//
+// CPsdContextChangeMonitor
+//
+
+CPsdContextChangeMonitor* CPsdContextChangeMonitor::NewL(MPsdEnv* aEnv, MPsdContextChangeObserver* aObserver)
+
+/**
+Function creates a CPsdContextChangeMonitor object
+
+@param MPsdEnv* aEnv a pointer to a object that provides the MPsdEnv interface
+@param MPsdContextChangeObserver* aObserver a pointer to the observing object that should be called back when the quality drops below the minimum value
+@return CPsdContextChangeMonitor* the newly created object (ownership of the object is passed to the function caller)
+*/
+	{
+	__ASSERT_DEBUG(aEnv && aObserver,User::Invariant());
+	CPsdContextChangeMonitor* self = new(ELeave)CPsdContextChangeMonitor(aEnv,aObserver);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(); //self
+	return self;
+	}
+
+CPsdContextChangeMonitor::~CPsdContextChangeMonitor()
+/**
+Destructor
+*/
+	{
+	Cancel();
+	iDebounceTimer.Close();
+	delete iQoSWatcher;
+	delete iConfigWatcher;
+	
+	delete iPackedActualQoSConfig;
+	delete iActualQoSConfig;
+	delete iPackedActualConfig;
+	delete iActualConfig;	
+	}
+
+CPsdContextChangeMonitor::CPsdContextChangeMonitor(MPsdEnv* aEnv, MPsdContextChangeObserver* aObserver)
+: CActive(EPriorityStandard), iSM(aEnv), iObserver(aObserver), iContextState(CPsdContextChangeMonitor::EContextQualityAcceptable)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CPsdContextChangeMonitor::ConstructL()
+/**
+2nd phase constructor. Initialises the member variables as appropriate for the current mode.
+Constructs a CPsdContextConfigChangeWatcher and a CPsdQoSConfigChangeWatcher object to watch for
+cahnges in context config and qos config.
+*/
+	{
+	TInt r=iDebounceTimer.CreateLocal();
+	if (r!=KErrNone)
+		User::Leave(r);
+	TUint32 timeOut = 0; // keeps compiler happy; we know it's always set below
+	if(iSM->Mode() == MPsdEnv::EModeWCDMA)
+		{
+		iActualConfig=new(ELeave)RPacketContext::TContextConfigGPRS();
+		RPacketContext::TContextConfigGPRS& config = *(STATIC_CAST(RPacketContext::TContextConfigGPRS*, iActualConfig));
+		iPackedActualConfig = new(ELeave)TPckg<RPacketContext::TContextConfigGPRS>(config);
+
+		iActualQoSConfig=new(ELeave)RPacketQoS::TQoSGPRSNegotiated();
+		RPacketQoS::TQoSGPRSNegotiated& qoSConfig = *(STATIC_CAST(RPacketQoS::TQoSGPRSNegotiated*, iActualQoSConfig));
+		iPackedActualQoSConfig = new(ELeave)TPckg<RPacketQoS::TQoSGPRSNegotiated>(qoSConfig);
+		// Get timeOut from the Db; default to 0 on error (eg. Db value is NULL)
+		TRAPD(rOk,iSM->BaseEnv().Db()->GetIntL(TPtrC(KGeneralServiceTable),TPtrC(GPRS_QOS_WARNING_TIMEOUT),timeOut));
+		if (rOk != KErrNone)
+			timeOut = 0;
+		}
+	iConfigWatcher = new(ELeave)CPsdContextConfigChangeWatcher(iSM->Context(), *this, *iPackedActualConfig);
+
+	if (iSM->IsQoSSupported())//the tsy might not support QoS
+		iQoSWatcher = new(ELeave)CPsdQoSConfigChangeWatcher(iSM->QoS(), *this, *iPackedActualQoSConfig);
+	else
+		iQoSWatcher=0;
+	
+	iDebounceTimeout = timeOut;
+	if(iDebounceTimeout.Int()>0)
+		{
+		// The timeout will be greater than zero if the service loss dialogs are enabled
+		iConfigWatcher->StartL();
+		if (iQoSWatcher)//the tsy might not support QoS
+			iQoSWatcher->StartL();
+		}
+	}
+
+void CPsdContextChangeMonitor::ReportConfigChange()
+/**
+Callback function, called when the CPsdContextConfigChangeWatcher object reports
+a change in context config parameters
+Checks to see if the changed parameters are below the minimum and if so
+starts the timeout which will cause the observer to be informed of the 
+connection going below quality.
+If the context config returns to acceptable values before the timeout completes
+the timeout is cancelled and the observer will not be notified of the change
+*/
+	{
+	// The config has changed check if it is acceptable
+	TBool acceptable = iSM->Config().QueryIfConfigAcceptable(*iPackedActualConfig);
+	// Only report if the context was previously of acceptable quality and now it is not
+	if(!acceptable && (iContextState == EContextQualityAcceptable))
+		{
+		// the context config has just gone below quality - don't report again until it becomes acceptable
+		iContextState |= EConfigQualityUnAcceptable;
+		StartTimeout();
+		}
+	else if(acceptable && (iContextState & EConfigQualityUnAcceptable))
+		{
+		// the context config has become of acceptable quality again
+		iContextState &= ~EConfigQualityUnAcceptable;
+		CancelTimeout();
+		}
+	}
+
+void CPsdContextChangeMonitor::ReportQoSChange()
+/**
+Callback function, called when the CPsdQoSConfigChangeWatcher object reports
+a change in QoS config parameters
+Checks to see if the changed parameters are below the minimum and if so
+starts the timeout which will cause the observer to be informed of the 
+connection going below quality.
+If the QoS config returns to acceptable values before the timeout completes
+the timeout is cancelled and the observer will not be notified of the change
+*/
+	{
+	// The QoS config has changed check if it is acceptable
+	TBool acceptable = iSM->QoSConfig().QueryIfQoSAcceptable(*iPackedActualQoSConfig);
+	// Only report if the context was previously of acceptable quality and now it is not
+	if(!acceptable && (iContextState == EContextQualityAcceptable))
+		{
+		// the QoS config has just gone below quality - don't report again until it becomes acceptable
+		iContextState |= EQoSQualityUnAcceptable;
+		StartTimeout();
+		}
+	else if(acceptable && (iContextState & EQoSQualityUnAcceptable))
+		{
+		// the context config has become of acceptable quality again
+		iContextState &= ~EQoSQualityUnAcceptable;
+		CancelTimeout();
+		}
+	}
+
+void CPsdContextChangeMonitor::RunL()
+/**
+The RunL will be called when the timeout completes following a drop below acceptable
+QoS or context quality. It informs the observer of the quality drop.
+*/
+	{
+	// The timeout has completed this means the context quality has been below acceptable
+	// for the duration of the timeout, so report it
+	iObserver->ReportContextBelowAcceptableQuality();
+	}
+
+void CPsdContextChangeMonitor::ReportConfigWatcherError(TInt aError)
+/**
+Callback function called when an error occurs in the CPsdContextConfigChangeWatcher object
+
+@param error code for error occurs in the CPsdContextConfigChangeWatcher object
+*/
+	{
+	iObserver->ReportError(aError);
+	}
+
+void CPsdContextChangeMonitor::ReportQoSWatcherError(TInt aError)
+/**
+Callback function called when an error occurs in the CPsdQoSConfigChangeWatcher object
+
+@param error code for error occurs in the CPsdQoSConfigChangeWatcher object
+*/
+	{
+	iObserver->ReportError(aError);
+	}
+
+void CPsdContextChangeMonitor::StartTimeout()
+	{
+	if(!IsActive())
+		{
+		iDebounceTimer.After(iStatus, iDebounceTimeout);
+		SetActive();
+		}
+	}
+
+void CPsdContextChangeMonitor::CancelTimeout()
+	{
+	if(iContextState == EContextQualityAcceptable)
+		{
+		Cancel();
+		}
+	}
+
+void CPsdContextChangeMonitor::DoCancel()
+	{	
+	iDebounceTimer.Cancel();
+	}
+//
+//
+// CPsdContextConfigChangeWatcher
+//
+
+CPsdContextConfigChangeWatcher::CPsdContextConfigChangeWatcher(const RPacketContext& aContext, MObserver& aObserver, TPtr8& aContextParams)
+: CActive(EPriorityStandard), iObserver(aObserver), iContext(aContext), iContextParams(aContextParams)
+/**
+Overloaded Constructor adding itself to the active scheduler
+*/
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CPsdContextConfigChangeWatcher::StartL()
+/**
+Start notifying observer of changes in context config parameters
+*/
+	{
+	iContext.NotifyConfigChanged(iStatus, iContextParams);
+	SetActive();
+	}
+
+CPsdContextConfigChangeWatcher::~CPsdContextConfigChangeWatcher()
+/**
+Destructor
+*/
+	{
+	Cancel();
+	}
+
+void CPsdContextConfigChangeWatcher::RunL()
+/**
+RunL completes when the context config parameters have changed - call back
+the observer to inform them of the event
+*/
+	{
+	if(iStatus != KErrNone)
+		{
+		iObserver.ReportConfigWatcherError(iStatus.Int());
+		}
+	else
+		{
+		iObserver.ReportConfigChange();
+		}
+	// Renew Request
+	iContext.NotifyConfigChanged(iStatus, iContextParams);
+	SetActive();
+	}
+
+void CPsdContextConfigChangeWatcher::DoCancel()
+/**
+Cancell the changes in the context configuration parameters and notifying its observer when such a change occurs.
+*/
+	{
+	iContext.CancelAsyncRequest(EPacketContextNotifyConfigChanged);
+	}
+
+//
+//
+// CPsdQoSConfigChangeWatcher
+//
+
+CPsdQoSConfigChangeWatcher::CPsdQoSConfigChangeWatcher(const RPacketQoS& aQoS, MObserver& aObserver, TPtr8& aQoSParams)
+: CActive(EPriorityStandard), iObserver(aObserver), iQoS(aQoS), iQoSParams(aQoSParams)
+/**
+Overloaded Constructor adding itself to the active scheduler
+*/
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CPsdQoSConfigChangeWatcher::StartL()
+/**
+Start notifying observer of changes in QoS config parameters
+*/
+	{
+	iQoS.NotifyProfileChanged(iStatus, iQoSParams);
+	SetActive();
+	}
+
+CPsdQoSConfigChangeWatcher::~CPsdQoSConfigChangeWatcher()
+/**
+Destructor
+*/
+	{
+	Cancel();
+	}
+
+void CPsdQoSConfigChangeWatcher::RunL()
+/**
+RunL completes when the QoS config parameters have changed - call back
+the observer to inform them of the event
+*/
+	{
+	if(iStatus != KErrNone)
+		{
+		iObserver.ReportQoSWatcherError(iStatus.Int());
+		}
+	else
+		{
+		iObserver.ReportQoSChange();
+		}
+	// Renew Request
+	iQoS.NotifyProfileChanged(iStatus, iQoSParams);
+	SetActive();
+	}
+
+void CPsdQoSConfigChangeWatcher::DoCancel()
+	{
+	iQoS.CancelAsyncRequest(EPacketQoSNotifyProfileChanged);
+	}
+