diff -r 000000000000 -r 3553901f7fa8 telephonyprotocols/psdagt/src/MipCdma.cpp --- /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 + +/** +@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 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(); + } +