telephonyprotocols/psdagt/src/MipCdma.cpp
changeset 0 3553901f7fa8
child 24 6638e7f4bd8f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyprotocols/psdagt/src/MipCdma.cpp	Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,483 @@
+// 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:
+// This file contains the implementation of the
+// handling of MIP handovers in a CDMA2000 network.
+// 
+//
+
+/**
+ @file mipcdma.cpp
+*/
+
+#include "MipCdma.h"
+#include "PSDAGTBase.h"
+#include <comms-infras/nifprvar.h>
+
+/**
+@internalComponent
+*/
+const TInt K10Seconds = 10000000;
+
+/**
+@internalComponent
+*/
+_LIT(KTsyNameExtension,".tsy");
+
+CMipCdmaHandoverHandler* CMipCdmaHandoverHandler::NewLC(CPSDAgent& aAgent, CCommsDbAccess& aDb)
+/**
+2 Phase constructor
+
+This function creates the whole CDMA2000 MIP Handover handler object, including the subclass
+CMIPCdmaEtelZoneChangeRequest.
+
+@param aAgent Reference to owner of this class
+@param aDb access to CommDB.
+@exception Leaves if no memory is available
+@return A newly created CMipCdmaHandoverHandler object
+*/
+	{
+	CMipCdmaHandoverHandler* self = new(ELeave) CMipCdmaHandoverHandler(aAgent, aDb);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+CMipCdmaHandoverHandler* CMipCdmaHandoverHandler::NewL(CPSDAgent& aAgent, CCommsDbAccess& aDb)
+/**
+2 Phase constructor
+
+This function creates the whole MIP Handover handler object, including the subclass
+CMIPCdmaEtelZoneChangeRequest.
+
+@param aAgent Reference to owner of this class
+@param aDb access to CommDB.
+@exception Leaves if no memory is available
+@return A newly created CMipCdmaHandoverHandler object
+*/
+	{
+	CMipCdmaHandoverHandler* self = NewLC(aAgent, aDb);
+	CleanupStack::Pop(); //self
+	return self;
+	}
+
+CMipCdmaHandoverHandler::CMipCdmaHandoverHandler(CPSDAgent& aAgent, CCommsDbAccess& aDb) 
+	: CActive(CActive::EPriorityStandard),
+		iAgent(aAgent), iDb(aDb)
+/**
+Constructor
+
+Adds itself to the Active Sceduler. Also initalizes all member data.
+
+@param aAgent Reference to owner of this class
+@param aDb access to CommDB.
+*/
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CMipCdmaHandoverHandler::ConstructL()
+/**
+2nd phase Constructor
+
+Creates an ETEL Zone change listener object.
+Resets the timer object.
+
+@exception Leaves if no memory is available
+*/
+	{
+	//Create ETEL Zone Listener Object
+	iMipCdmaEtelZoneChanger = CMIPCdmaEtelZoneChangeRequest::NewL(*this, iAgent, iDb);
+	
+	//Reset the timer (initialize the timer)
+	(void)iTimer.CreateLocal();	
+	}
+
+CMipCdmaHandoverHandler::~CMipCdmaHandoverHandler()
+/**
+Destructor
+
+Calls cancel on the Active object which will cancel the timer.
+Deletes the ETEL Zone change listener object.
+*/
+	{
+	Cancel();		//Cancel potential outstanding timer request.
+	iTimer.Close();	//Needed to free resources on server side.
+	delete iMipCdmaEtelZoneChanger;
+	}
+
+TInt CMipCdmaHandoverHandler::StartListening()
+/**
+This function is called when the link is brought up. It is responsible to 
+start this object and start listening to incoming events from both PPP and ETEL.
+
+@return Returns whether the starting of the object went ok or not.
+*/
+	{
+	TInt err = KErrNone;
+	TBool val;
+	if(iAgent.ReadBool(TPtrC(CDMA_MIP), val)==KErrNone && val)
+		{
+		err = iMipCdmaEtelZoneChanger->StartListening();
+		}
+	return err;
+	}
+
+void CMipCdmaHandoverHandler::StopListening()
+/**
+This function is called when the link is brought down. It is responsible to 
+stop this object and its listener.
+*/
+	{
+	iMipCdmaEtelZoneChanger->StopListening();
+	}
+
+TBool CMipCdmaHandoverHandler::PPPLinkDownEvent()
+/**
+This function is called from the Reconnect() method in the CPSDAgent.
+It will report back to the CPSDAgent if we are using MIP or not.
+It will also start a timer that if it expires will force a manual reconnect of the link.
+If an ETEL notification event comes in before, or has already come in, an autmatic reconnect takes place.
+
+@return ETrue if we are using MIP else EFalse.
+*/
+	{
+	TBool val;
+	if(iAgent.ReadBool(TPtrC(CDMA_MIP), val)==KErrNone && val)
+		{
+		//We are using MIP
+		iPPPLinkDownEvent = ETrue;
+		if (iETELChangedZoneEvent)
+			{
+			Cancel();
+			RestartPPP();
+			}
+		else
+			{
+			//If timer is already started, cancel it and start it again.
+			Cancel();	//Will only cancel the timer if the AO is active.
+			StartTimer();
+			}		
+		return ETrue;
+		}
+	else
+		{
+		//We are NOT using MIP
+		return EFalse;
+		}
+	}
+
+void CMipCdmaHandoverHandler::ETELChangedZoneEvent()
+/**
+This function is called from the RunL() method in the CMIPCdmaEtelZoneChangeRequest.
+It will also start a timer that if it expires will force a manual reconnect of the link.
+If an PPP Link Down event comes in before, or has already come in, an autmatic reconnect takes place.
+*/
+	{
+	iETELChangedZoneEvent = ETrue;
+	if (iPPPLinkDownEvent)
+		{
+		Cancel();
+		// Notify nifman of the Changed Zone Event
+		iAgent.AgentEvent(EEtelEvent,ECurrentNetworkChangeEvent,KNullDesC8);
+		// Reconnect PPP
+		RunL();
+		}
+	else
+		{
+		//If timer is already started, cancel it and start it again.
+		Cancel();	//Will only cancel the timer if the AO is active.
+		StartTimer();
+		}
+	}
+
+void CMipCdmaHandoverHandler::StartTimer()
+/**
+Help function that will start the active object. E.g. it will start the timer and activate the object.
+*/
+	{
+	TUint32 time;
+	if(iAgent.ReadInt(TPtrC(CDMA_MIP_TIMEOUT), time)==KErrNone && time)
+		{
+		iTimer.After(iStatus, time);
+		}
+	else //default
+		{
+		iTimer.After(iStatus, K10Seconds); 
+		}
+
+	SetActive();
+	}
+
+void CMipCdmaHandoverHandler::RestartPPP()
+/**
+This function is responsible to do an automatic reconnect of the link. Will also "zero" the state variables
+*/
+	{
+	iPPPLinkDownEvent = EFalse;
+	iETELChangedZoneEvent = EFalse;
+
+	//Notify client to restart PPP silently
+	iAgent.MDPOReconnectComplete(KErrNone);
+	}
+
+void CMipCdmaHandoverHandler::DoCancel()
+/**
+Inherited from the CActive class. Will cancel the timer request.
+*/
+	{
+	// Cancel the timer request
+	iTimer.Cancel();
+	}
+
+void CMipCdmaHandoverHandler::RunL()
+/**
+Inherited from the CActive class. Will "zero" the state variables and restart the link manually.
+*/
+	{
+	iPPPLinkDownEvent = EFalse;
+	iETELChangedZoneEvent = EFalse;
+	//Notify client to restart PPP as we would in a normal Simple IP scenario
+	iAgent.Reconnect();
+	}
+
+CMIPCdmaEtelZoneChangeRequest* CMIPCdmaEtelZoneChangeRequest::NewLC(CMipCdmaHandoverHandler& aHandoverHandler, CPSDAgent& aAgent, CCommsDbAccess& aDb)
+/**
+2 Phase constructor
+
+This function creates a ETEL Zone Change Listener object.
+
+@param aHandoverHandler Reference to owner of this class
+@param aAgent Reference to the Controller
+@param aDb access to CommDB.
+@exception Leaves if no memory is available
+@return A newly created CMIPCdmaEtelZoneChangeRequest object
+*/
+	{
+	CMIPCdmaEtelZoneChangeRequest* self = new(ELeave) CMIPCdmaEtelZoneChangeRequest(aHandoverHandler, aAgent, aDb);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+CMIPCdmaEtelZoneChangeRequest* CMIPCdmaEtelZoneChangeRequest::NewL(CMipCdmaHandoverHandler& aHandoverHandler, CPSDAgent& aAgent, CCommsDbAccess& aDb)
+/**
+2 Phase constructor
+
+This function creates a ETEL Zone Change Listener object.
+
+@param aHandoverHandler Reference to owner of this class
+@param aAgent Reference to the Agent
+@param aDb access to CommDB.
+@exception Leaves if no memory is available
+@return A newly created CMIPCdmaEtelZoneChangeRequest object
+*/
+	{
+	CMIPCdmaEtelZoneChangeRequest* self = NewLC(aHandoverHandler, aAgent, aDb);
+	CleanupStack::Pop(); //self
+	return self;
+	}
+
+CMIPCdmaEtelZoneChangeRequest::CMIPCdmaEtelZoneChangeRequest(CMipCdmaHandoverHandler& aHandoverHandler, CPSDAgent& aAgent, CCommsDbAccess& aDb) 
+	: CActive(CActive::EPriorityStandard), iFirstTime(ETrue),
+	iHandoverHandler(aHandoverHandler), iAgent(aAgent), iDb(aDb),
+	iPhoneNetworkInfoPckg(iAsyncCurrentNetwork)
+/**
+Constructor
+
+Adds itself to the Active Sceduler. Also initalizes all member data.
+
+@param aHandoverHandler Reference to owner of this class
+@param aAgent Reference to the Agent
+*/
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CMIPCdmaEtelZoneChangeRequest::ConstructL()
+/**
+2nd phase Constructor
+*/
+	{
+	}
+
+CMIPCdmaEtelZoneChangeRequest::~CMIPCdmaEtelZoneChangeRequest()
+/**
+Destructor
+
+Calls cancel on the Active object which will cancel the outstanding request to ETEL.
+Closes the ETEL phone and server.
+*/	
+	{
+	StopListening();
+	}
+
+TInt CMIPCdmaEtelZoneChangeRequest::StartListening()
+/**
+This function is called when the link is brought up.
+It is responsible to initiate and create a phone object.
+
+@return Returns whether the starting of the object and phone went ok or not.
+*/
+	{
+	if (!iStarted)
+		{
+		iStarted = ETrue;
+		TRAPD(err, InitPhoneL());
+		if(err != KErrNone)
+			{
+			return err;
+			}
+
+		//Start request for notification
+		iFirstTime = ETrue;
+		StartRequest();
+		}
+	return KErrNone;
+	}
+
+void CMIPCdmaEtelZoneChangeRequest::StopListening()
+/**
+This function is called when the link is brought down. It is responsible to stop
+the phone object and the phone server 
+*/
+	{
+	if(iStarted)
+		{
+		iStarted=EFalse;
+		Cancel();
+
+		iMmPhone.Close();
+		(void)iTelServer.UnloadPhoneModule(*iTsyName);
+		delete iTsyName;
+		iTsyName = NULL;
+		iTelServer.Close();
+		}
+	}
+
+void CMIPCdmaEtelZoneChangeRequest::InitPhoneL()
+/**
+This function is help function that creates and intializes a phone object 
+
+@exception Leaves if no memory is available or if initiation of phone or server failed.
+*/
+	{
+	TFileName tsyName;
+	iDb.GetTsyNameL(tsyName);
+	if (tsyName.Right(4).CompareF(KTsyNameExtension) == 0)
+		tsyName = tsyName.Left(tsyName.Length() - 4);
+
+	// Connect to ETel
+	(void)User::LeaveIfError(iTelServer.Connect());
+
+	TInt err = iTelServer.LoadPhoneModule(tsyName);
+	if(err == KErrNotFound)
+		User::Leave(KErrNone);
+	else if(err != KErrNone)
+		User::Leave(err);
+
+	// Remember the tsy name so it can be unloaded
+	iTsyName = tsyName.AllocL();
+
+	// Find out how many phones are supported e.g. how many TSYs
+	TInt count = 0;
+	(void)User::LeaveIfError(iTelServer.EnumeratePhones(count));
+	if (count <= 0)
+		User::Leave(KErrNotFound);
+
+	RTelServer::TPhoneInfo info;
+	TBool found = EFalse;
+
+	// Loop through all the phones and find correct TSY
+	for (TInt i = 0; i < count; i++)
+		{
+		TBuf<KCommsDbSvrMaxFieldLength> currentTsyName;
+		(void)User::LeaveIfError(iTelServer.GetTsyName(i, currentTsyName));
+		// If the loaded object has .tsy extension, compare the name
+		// with aTsyName
+		if (currentTsyName.Right(4).CompareF(KTsyNameExtension) == 0)
+			currentTsyName = currentTsyName.Left(currentTsyName.Length() - 4);
+		if (currentTsyName.CompareF(tsyName) == 0)
+			{
+			// Get phone info from the TSY
+			(void)User::LeaveIfError(iTelServer.GetPhoneInfo(i, info));
+			found = ETrue;
+			break;
+			}	
+		}
+	if (!found)
+		User::Leave(KErrNotFound);
+	// Open multimode phone object
+	(void)User::LeaveIfError(iMmPhone.Open(iTelServer,info.iName));
+	}
+
+void CMIPCdmaEtelZoneChangeRequest::StartRequest()
+/**
+Trigger function. Will start the request for notifications for a zone change event from ETEL.
+
+If it is the first time the object is called we will get the network information and store it locally
+After the initial request we will only ask to get notfied when there is a change in network information.
+*/	
+	{
+	if (iFirstTime)
+		{
+		//Get current netowrk status
+		iMmPhone.GetCurrentNetwork(iStatus, iPhoneNetworkInfoPckg, iAsyncLocArea);
+		}
+	else
+		{
+		//start etel request for notifications
+		iMmPhone.NotifyCurrentNetworkChange(iStatus, iPhoneNetworkInfoPckg, iAsyncLocArea);	
+		}
+
+	SetActive();
+	}
+
+void CMIPCdmaEtelZoneChangeRequest::DoCancel()
+/**
+Inherited from the CActive class. Will cancel the ETEL request.
+*/
+	{
+	if (iFirstTime)
+		{
+		iMmPhone.CancelAsyncRequest(EMobilePhoneGetCurrentNetwork);
+		}
+	else
+		{
+		// Cancel the ETEL Request
+		iMmPhone.CancelAsyncRequest(EMobilePhoneNotifyCurrentNetworkChange);
+		}
+	}
+
+void CMIPCdmaEtelZoneChangeRequest::RunL()
+/**
+Inherited from the CActive class. Will notify the owner that a notification has ben received.
+Will requeue itself, e.g. will re-request notifications from ETEL.
+*/
+	{
+	if (iFirstTime)
+		{
+		iCurrentCdmaSID = iPhoneNetworkInfoPckg().iCdmaSID;
+		iCurrentNetworkId = iPhoneNetworkInfoPckg().iNetworkId;
+		iFirstTime = EFalse;
+		}
+	else
+		{
+		if ((iPhoneNetworkInfoPckg().iCdmaSID !=iCurrentCdmaSID) || (iPhoneNetworkInfoPckg().iNetworkId !=iCurrentNetworkId))
+			iHandoverHandler.ETELChangedZoneEvent();
+		}
+
+	//Requeue
+	StartRequest();
+	}
+