telephonyserverplugins/multimodetsy/hayes/NOTIFY.CPP
changeset 0 3553901f7fa8
child 19 630d2f34d719
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyserverplugins/multimodetsy/hayes/NOTIFY.CPP	Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,983 @@
+// Copyright (c) 1997-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:
+//
+
+#include "ETELFAX.H"
+#include "PHONE.H"
+#include "LINE.H"
+#include "CALL.H"
+#include "mSLOGGER.H"
+#include "mnetwork.h"
+#include "GprsNotify.h"
+
+//
+//	CNotifications - handles array of notifications placed on TSY
+//
+CNotifications* CNotifications::NewL()
+	{
+	CNotifications* notifications=new(ELeave) CNotifications();
+	CleanupStack::PushL(notifications);
+	notifications->ConstructL();
+	CleanupStack::Pop();
+	return notifications;
+	}
+
+CNotifications::CNotifications()
+	{}
+
+void CNotifications::ConstructL()
+	{
+	iNotifications = new (ELeave) CArrayPtrFlat<CNotifyBase>(4);
+	iLastEvents = new (ELeave) CArrayFixFlat<TLastEvent>(4);
+	}
+
+CNotifications::~CNotifications()
+//
+//	Notifications are removed by server prior to this
+//
+	{
+	if(iNotifications)
+		{
+		__ASSERT_ALWAYS(iNotifications->Count()==0,Panic(ENotifications_Remaining));
+		delete iNotifications;
+		}
+	if(iLastEvents)
+		{
+		__ASSERT_ALWAYS(iLastEvents->Count()==0,Panic(ELastEvents_Remaining));
+		delete iLastEvents;
+		}
+	}
+
+//
+//	Last Events
+//
+//	The most recent event to occur must be stored in the notification handler to be compared
+//  with the event passed with CheckNotification(), so that they can be compared (if they are 
+//  equal, the notification should not be completed).
+//	Each TelObject to use this Notification handler has a last event associated with it.
+//	The first time a TelObject calls RegisterNotification() to add a notification to the array, 
+//	an entry is made in the iLastEvents array connecting this TelObject with an event (to start
+//  with this is ENoEvent).
+//	When the notification completes, the LastEvent entry remains, as even if a TelObject has no
+//	notifications outstanding there must still be a record of its last event. This LastEvent
+//	entry must only be removed when the TelObject is destroyed, hence in the destructor of 
+//	each of CPhoneHayes, CLineHayes, CCallHayes and CFaxHayes RemoveClientFromLastEvents() is
+//  called.
+//
+
+TInt CNotifications::FindLastEvent(CTelObject* aTelObject)
+//
+// Finds the last event to occur to this TelObject
+// Returns the position in the array
+//
+	{
+	for (TInt i=0;i<iLastEvents->Count();i++)
+		{
+		if (iLastEvents->At(i).iTelObject==aTelObject)
+			return i;
+		}
+	return KErrNotFound;
+	}
+
+TInt CNotifications::GetLastEvent(CTelObject* aTelObject, TLastEvent& aLastEvent)
+//
+//	Searches for the relevant Last Event entry by TelObject, returns the reference to entry
+//  and its position
+//
+	{
+	TInt pos = FindLastEvent(aTelObject);
+	if (pos!=KErrNotFound)
+		{
+		aLastEvent = iLastEvents->At(pos);
+		}
+	return pos;
+	}
+
+TInt CNotifications::AddLastEvent(CTelObject* aTelObject,TEvent aLastEvent)
+//
+//	Searches for relevant entry. If exists, updates it with new event. If not, appends a new
+//	entry to the array.
+//
+	{
+	TLastEvent lastEvent;
+	lastEvent.iLastEvent=aLastEvent;
+
+	TInt pos = FindLastEvent(aTelObject);
+	if (pos!=KErrNotFound)
+		{
+		iLastEvents->At(pos).iLastEvent=lastEvent.iLastEvent; // Update array element's iLastEvent.
+		}
+	else
+		{	
+		lastEvent.iTelObject=aTelObject;
+		TRAPD(ret, iLastEvents->AppendL(lastEvent,1) );
+
+		if (ret!=KErrNone)
+			{
+			LOGTEXT2(_L8("CNotifications::AddLastEvent Append failed with error %d"), ret);
+			return ret; 
+			}
+		}
+
+	return pos;
+	}
+	
+//
+//	public functions
+//
+
+void CNotifications::RemoveClientFromLastEvents(CTelObject* aTelObject)
+//
+//	The notification store needs to know when a TelObject is closed so it can remove its
+//  entry in the Last Events list.
+	{
+	for (TInt i=0;i<iLastEvents->Count();i++)
+		{
+		if (iLastEvents->At(i).iTelObject==aTelObject)
+			{
+			iLastEvents->Delete(i);
+			return;
+			}
+		}
+	}
+
+void CNotifications::RemoveEventFromLastEvents(TEvent aEvent)
+//
+// The removes all events of a particular type from the event list.  It is used when a line stops
+// ringing to remove all ringing references.
+//
+	{
+	for (TInt i=0;i<iLastEvents->Count();i++)
+		{
+		if (iLastEvents->At(i).iLastEvent==aEvent)
+			{
+			iLastEvents->Delete(i);
+			return;
+			}
+		}
+	}
+
+void CNotifications::RegisterNotification(TNotifications aWhichNotification,TTsyReqHandle aTsyReqHandle,CTelObject* aTelObject,TAny* aParams)
+	{
+	CNotifyBase* newNotify = NULL;
+	TInt ret=KErrNone;
+	switch (aWhichNotification)
+		{
+	case EModemDetection:
+		TRAP(ret,newNotify = CNotifyModemDetected::NewL((RPhone::TModemDetection*)aParams,aTsyReqHandle,aTelObject));
+		break;
+	case EIncomingCall:
+		TRAP(ret,newNotify = CNotifyIncomingCall::NewL((TDes*)aParams,aTsyReqHandle,aTelObject));
+		break;
+	case ELineHookChange:
+		TRAP(ret,newNotify = CNotifyLineHookChange::NewL((RCall::THookStatus*)aParams,aTsyReqHandle,aTelObject));
+		break;
+	case ECallHookChange:
+		TRAP(ret,newNotify = CNotifyCallHookChange::NewL((RCall::THookStatus*)aParams,aTsyReqHandle,aTelObject));
+		break;
+	case ELineStatusChange:
+		TRAP(ret,newNotify = CNotifyLineStatusChange::NewL((RCall::TStatus*)aParams,aTsyReqHandle,aTelObject));
+		break;
+	case EMobileLineStatusChange:
+		TRAP(ret,newNotify = CNotifyMobileLineStatusChange::NewL((RMobileCall::TMobileCallStatus*)aParams,aTsyReqHandle,aTelObject));
+		break;
+	case ECallDurationChange:
+		TRAP(ret,newNotify = CNotifyCallDurationChange::NewL((TTimeIntervalSeconds*)aParams,aTsyReqHandle,aTelObject));
+		break;
+	case ENewCallAdded:
+		TRAP(ret,newNotify = CNotifyLineNewCallAdded::NewL((TDes*)aParams,aTsyReqHandle,aTelObject));
+		break;
+	case ECallStatusChange:
+		TRAP(ret,newNotify = CNotifyCallStatusChange::NewL((RCall::TStatus*)aParams,aTsyReqHandle,aTelObject));
+		break;
+	case EMobileCallStatusChange:
+		TRAP(ret,newNotify = CNotifyMobileCallStatusChange::NewL((RMobileCall::TMobileCallStatus*)aParams,aTsyReqHandle,aTelObject));
+		break;
+	case EReadOrWriteFax:
+		TRAP(ret,newNotify = CNotifyFaxReadOrWrite::NewL(aTsyReqHandle,aTelObject));
+		break;
+	case EEndOfFaxPage:
+		TRAP(ret,newNotify = CNotifyFaxEndOfPage::NewL(aTsyReqHandle,aTelObject));
+		break;
+	case ECallCaps:
+		TRAP(ret,newNotify = CNotifyCallCaps::NewL((RCall::TCaps*)aParams,aTsyReqHandle,aTelObject));
+		break;
+	case ECallMobileCaps:
+		TRAP(ret,newNotify = CNotifyMobileCallCaps::NewL((TDes8*)aParams,aTsyReqHandle,aTelObject));
+		break;
+	case ERegistrationStatus:
+		TRAP(ret,newNotify = CNotifyNetworkRegistrationStatusChange::NewL(aTsyReqHandle,aTelObject,(RMobilePhone::TMobilePhoneRegistrationStatus*)aParams));
+		break;
+	case ECurrentNetwork:
+		TRAP(ret,newNotify = CNotifyCurrentNetworkChange::NewL(aTsyReqHandle,aTelObject,(TInt*)aParams)); 
+		break;
+
+	// GPRS
+	case EPacketContextAdded:
+		TRAP(ret,newNotify = CGprsContextAddedNotify::NewL(aTsyReqHandle,aTelObject,(TDes*)aParams));
+		break; 
+	case EPacketStatusChange:
+		TRAP(ret,newNotify = CGprsStatusNotify::NewL(aTsyReqHandle,aTelObject,(RPacketService::TStatus*)aParams));
+		break;
+	case EPacketNtwkRegStatusChange:
+		TRAP(ret,newNotify = CGprsNtwkRegStatusChangeNotify::NewL(aTsyReqHandle,aTelObject,(RPacketService::TRegistrationStatus*)aParams));
+		break;
+
+	// GPRS context
+	case EPacketContextConfigChange:
+		TRAP(ret,newNotify = CGprsContextConfigNotify::NewL(aTsyReqHandle,aTelObject,(TDes8*)aParams));
+		break;
+	case EPacketContextStatusChange:
+		TRAP(ret,newNotify = CGprsContextStatusNotify::NewL(aTsyReqHandle,aTelObject,(RPacketContext::TContextStatus*)aParams));
+		break;
+
+	// GPRS QoS
+	case EPacketQoSProfileChange:
+		TRAP(ret,newNotify = CGprsQoSProfileNotify::NewL(aTsyReqHandle, aTelObject, (TDes8*)aParams));
+		break;
+
+	default:
+		Panic(EIllegalEvent);
+		break;
+		}
+	if (ret!=KErrNone)
+		{
+		aTelObject->ReqCompleted(aTsyReqHandle,ret);
+		delete newNotify;
+		}
+	else
+		{
+		TRAP(ret,RegisterNotificationL(newNotify));
+		if (ret!=KErrNone)
+			aTelObject->ReqCompleted(aTsyReqHandle,ret);
+		}
+	}
+
+void CNotifications::RegisterNotificationL(CNotifyBase* aNotify)
+	{
+	iNotifications->AppendL(aNotify);
+	TInt pos = FindLastEvent(aNotify->TelObject());
+	if (pos==KErrNotFound)
+		{
+		TLastEvent lastEvent;
+		lastEvent.iTelObject=aNotify->TelObject();
+		lastEvent.iLastEvent=ENoEvent;
+		iLastEvents->AppendL(lastEvent,1);
+		}
+	}
+
+void CNotifications::CheckNotification(CTelObject* aTelObject,TEvent aEvent)
+//
+//	Due to the possibility of immediate re-posting of notification from server which may
+//	initiate another CheckNotification synchronously causing the problem that the last event
+//  has not yet been set to current event - an infinite loop occurs. Fixed here by setting
+//  a boolean on entry and resetting on exit
+//
+	{
+	if (iAlreadyChecking)
+		return;
+	iAlreadyChecking = ETrue;
+	TLastEvent lastEvent;
+	TInt ret = GetLastEvent(aTelObject,lastEvent);
+	if (ret==KErrNotFound)
+		lastEvent.iLastEvent=ENoEvent;	// to be passed to each notify object
+	TBool flag=EFalse;
+	for (TInt i=iNotifications->Count(); i>0; i--)
+		{
+		CNotifyBase* notify = iNotifications->At(i-1);
+		if(notify->CheckAndCompleteNotification(aTelObject,aEvent,lastEvent.iLastEvent))
+			{
+			iNotifications->Delete(i-1);
+			delete notify;
+			flag=ETrue;
+			}
+		}
+	if (flag)
+		iNotifications->Compress();
+	ret = AddLastEvent(aTelObject,aEvent);
+	__ASSERT_ALWAYS( ret == KErrNotFound  || ret >= 0,Panic(EGeneral));
+	iAlreadyChecking = EFalse;
+	}
+
+void CNotifications::CheckNotification(CCallBase* aCallObject,TEvent aEvent)
+	{
+	if (iAlreadyChecking)
+		return;
+	iAlreadyChecking = ETrue;
+	TLastEvent lastEvent;
+	TInt ret = GetLastEvent(aCallObject,lastEvent);
+	if (ret==KErrNotFound)
+		lastEvent.iLastEvent=ENoEvent;
+	TBool flag=EFalse;
+	for (TInt i=iNotifications->Count(); i>0; i--)
+		{
+		CNotifyBase* notify = iNotifications->At(i-1);
+		if (notify->CheckAndCompleteNotification(aCallObject,aEvent,lastEvent.iLastEvent))
+			{
+			iNotifications->Delete(i-1);
+			delete notify;
+			flag=ETrue;
+			}
+		}
+	if (flag)
+		iNotifications->Compress();
+	ret = AddLastEvent(aCallObject,aEvent);
+	__ASSERT_ALWAYS( ret == KErrNotFound  || ret >= 0,Panic(EGeneral));
+	iAlreadyChecking = EFalse;
+	}
+
+void CNotifications::CheckNotification(CFaxSession* aETelFaxObject,TEvent aEvent,TInt aError,TAny* aParams)
+	{
+	iAlreadyChecking = ETrue;
+	TBool flag=EFalse;
+	for (TInt i=iNotifications->Count(); i>0; i--)
+		{
+		CNotifyBase* notify = iNotifications->At(i-1);
+		if (notify->CheckAndCompleteNotification(aETelFaxObject,aEvent,aError,aParams))
+			{
+			iNotifications->Delete(i-1);
+			delete notify;
+			flag=ETrue;
+			}
+		}
+	if (flag)
+		iNotifications->Compress();
+	iAlreadyChecking = EFalse;
+	}
+
+//
+//
+// This function is added to deal specifically with notifications only (ie: no events)
+// An incoming SMS message notification for example!
+//
+//
+void CNotifications::CheckNotification(CTelObject* aTelObject, TNotifications aNotification)
+	{
+	if (iAlreadyChecking)
+		return;
+	iAlreadyChecking = ETrue;
+	TBool flag = EFalse;
+	for (TInt i = 0; i<iNotifications->Count(); i++)
+		{
+		CNotifyBase* notify = iNotifications->At(i);
+		if (notify->CheckAndCompleteNotification(aTelObject, aNotification))
+			{
+			iNotifications->Delete(i);
+			delete notify;
+			flag = ETrue;
+			} 
+		} 
+	if (flag)
+		iNotifications->Compress();
+	iAlreadyChecking = EFalse;
+}
+
+void CNotifications::RemoveNotification(TTsyReqHandle aTsyReqHandle)
+//
+//	Cancel a notification by its TsyReqHandle (unique to that notification)
+//
+	{
+	for (TInt i=0;i<iNotifications->Count();i++)
+		{
+		CNotifyBase* notify = iNotifications->At(i);
+		if (notify->TsyReqHandle() == aTsyReqHandle)
+			{
+			notify->TelObject()->ReqCompleted(notify->TsyReqHandle(),KErrCancel);
+			iNotifications->Delete(i);
+			delete notify;
+			break;
+			}
+		}
+	}
+
+void CNotifications::CompleteNotificationsWithError(TInt aError)
+	{
+	for (TInt i=0;i<iNotifications->Count();i++)
+		{
+		CNotifyBase* notify = iNotifications->At(0);
+		notify->TelObject()->ReqCompleted(notify->TsyReqHandle(),aError);
+		iNotifications->Delete(0);
+		delete notify;
+		}
+	}
+	
+//
+//	CNotifyBase class - base class for all notifications
+//
+
+CNotifyBase::CNotifyBase(TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	: iReqHandle(aReqHandle),iTelObject(aTelObject)
+	{}
+
+CNotifyBase::~CNotifyBase()
+	{}
+
+TTsyReqHandle CNotifyBase::TsyReqHandle()
+	{
+	return iReqHandle;
+	}
+
+CTelObject* CNotifyBase::TelObject()
+	{
+	return iTelObject;
+	}
+
+TBool CNotifyBase::CheckAndCompleteNotification(CTelObject* /*aTelObject*/,TEvent /*aEvent*/,TEvent /*aLastEvent*/)
+	{
+	return EFalse;
+	}
+	
+TBool CNotifyBase::CheckAndCompleteNotification(CCallBase* /*aCallObject*/,TEvent /*aEvent*/,TEvent /*aLastEvent*/)
+	{
+	return EFalse;
+	}
+
+TBool CNotifyBase::CheckAndCompleteNotification(CFaxSession* /*aETelFaxObject*/,TEvent /*aEvent*/,TInt /*aError*/,TAny* /*aParams*/)
+	{
+	return EFalse;
+	}
+
+TBool CNotifyBase::CheckAndCompleteNotification(CTelObject* /*aTelObject*/, TNotifications /*aNotification*/)
+	{
+	return EFalse;
+	}
+
+//
+// CNotifyPhoneDetection
+//
+CNotifyModemDetected* CNotifyModemDetected::NewL(RPhone::TModemDetection* aDetection,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	{
+	return new(ELeave) CNotifyModemDetected(aDetection,aReqHandle,aTelObject);
+	}
+
+CNotifyModemDetected::CNotifyModemDetected(RPhone::TModemDetection* aDetection,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	 : CNotifyBase(aReqHandle,aTelObject),iDetection(aDetection)
+	{}
+
+CNotifyModemDetected::~CNotifyModemDetected()
+	{}
+
+TBool CNotifyModemDetected::CheckAndCompleteNotification(CTelObject* /*aTelObject*/,TEvent aEvent,TEvent aLastEvent)
+//
+//	After phone has been in the "Not detected" state, the next state should be "Detected"
+//  or a "Ring Occurred"
+//  
+	{
+	if ((aEvent==ERingOccurred || aEvent==EPhoneDetected)
+		&&(aLastEvent==EPhoneNotDetected || aLastEvent==ENoEvent))
+		{
+		*iDetection=RPhone::EDetectedPresent;
+		}
+	else if (aEvent==EPhoneNotDetected && aLastEvent!=EPhoneNotDetected)
+		{
+		*iDetection=RPhone::EDetectedNotPresent;
+		}
+	else return EFalse;
+	LOGTEXT2(_L8("Event %d:\tModem Detection Change Notification completed"),aEvent);
+	iTelObject->ReqCompleted(iReqHandle,KErrNone);
+	return ETrue;
+	}
+
+TBool CNotifyModemDetected::CheckAndCompleteNotification(CCallBase* aCallObject,TEvent aEvent,TEvent aLastEvent)
+	{
+	return CheckAndCompleteNotification(STATIC_CAST(CTelObject*,aCallObject),aEvent,aLastEvent);
+	}
+//
+// CNotifyIncomingCall
+//
+CNotifyIncomingCall* CNotifyIncomingCall::NewL(TDes* aName,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	{
+	return new(ELeave) CNotifyIncomingCall(aName,aReqHandle,aTelObject);
+	}
+
+CNotifyIncomingCall::CNotifyIncomingCall(TDes* aName,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	 : CNotifyBase(aReqHandle,aTelObject),iName(aName)
+	{}
+
+CNotifyIncomingCall::~CNotifyIncomingCall()
+	{}
+
+TBool CNotifyIncomingCall::CheckAndCompleteNotification(CTelObject* aTelObject,TEvent aEvent,TEvent aLastEvent)
+//
+//	Checks that the last event to happen was not an incoming call. 
+//  Adv: If the first Notification for an incoming call is placed after the line started ringing,
+//		 it can check the line status and complete immediately.
+	{
+	if (aEvent==ERingOccurred && aLastEvent!=ERingOccurred
+		&& aTelObject==iTelObject)
+		{
+		CLineHayes* line = STATIC_CAST(CLineHayes*,iTelObject);
+		line->GetNameOfCallForAnswering(*iName);
+		line->ResetNotifyIncomingCall();	
+		LOGTEXT2(_L8("Event %d:\tIncoming Call Notification completed"),aEvent);
+		iTelObject->ReqCompleted(iReqHandle,KErrNone);
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+TBool CNotifyIncomingCall::CheckAndCompleteNotification(CCallBase* aCallBase,TEvent aEvent,TEvent aLastEvent)
+	{
+	return CheckAndCompleteNotification(REINTERPRET_CAST(CLineBase*,aCallBase->Owner()),aEvent,aLastEvent);
+	}
+
+//
+// CNotifyLineHookChange
+//
+CNotifyLineHookChange* CNotifyLineHookChange::NewL(RCall::THookStatus* aHookStatus,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	{
+	return new(ELeave) CNotifyLineHookChange(aHookStatus,aReqHandle,aTelObject);
+	}
+
+CNotifyLineHookChange::CNotifyLineHookChange(RCall::THookStatus* aHookStatus,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	 : CNotifyBase(aReqHandle,aTelObject),iHookStatus(aHookStatus)
+	{}
+
+CNotifyLineHookChange::~CNotifyLineHookChange()
+	{}
+
+TBool CNotifyLineHookChange::CheckAndCompleteNotification(CCallBase* aCallObject,TEvent aEvent,TEvent aLastEvent)
+//
+//	Line hook can only change if a call-owned object (eg ATDial) is in progress
+//
+	{
+	if (iTelObject != REINTERPRET_CAST(CLineHayes*,aCallObject->Owner()))
+		return EFalse;
+	if (aEvent==EBegunConnecting && aLastEvent!=EBegunConnecting)
+		*iHookStatus = RCall::EHookStatusOff;
+	else if (aEvent==EBecomeIdle && aLastEvent!=EBecomeIdle)
+		*iHookStatus = RCall::EHookStatusOn;
+	else 
+		return EFalse;
+	LOGTEXT2(_L8("Event %d:\tLine Hook Change Notification completed"),aEvent);
+	iTelObject->ReqCompleted(iReqHandle,KErrNone);
+	return ETrue;
+	}
+//
+// CNotifyCallHookChange
+//
+CNotifyCallHookChange* CNotifyCallHookChange::NewL(RCall::THookStatus* aHookStatus,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	{
+	return new(ELeave) CNotifyCallHookChange(aHookStatus,aReqHandle,aTelObject);
+	}
+	
+CNotifyCallHookChange::CNotifyCallHookChange(RCall::THookStatus* aHookStatus,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	 : CNotifyBase(aReqHandle,aTelObject),iHookStatus(aHookStatus)
+	{}
+
+CNotifyCallHookChange::~CNotifyCallHookChange()
+	{}
+
+TBool CNotifyCallHookChange::CheckAndCompleteNotification(CTelObject* /*aTelObject*/,TEvent aEvent,TEvent aLastEvent)
+	{
+	if (aEvent==EBegunConnecting && aLastEvent!=EBegunConnecting)
+		*iHookStatus = RCall::EHookStatusOff;
+	else if (aEvent==EBecomeIdle && aLastEvent!=EBecomeIdle)
+		*iHookStatus = RCall::EHookStatusOn;
+	else 
+		return EFalse;
+	LOGTEXT2(_L8("Event %d:\tCall Hook Change Notification completed"),aEvent);
+	iTelObject->ReqCompleted(iReqHandle,KErrNone);
+	return ETrue;
+	}
+
+TBool CNotifyCallHookChange::CheckAndCompleteNotification(CCallBase* aCallObject,TEvent aEvent,TEvent aLastEvent)
+	{
+	if (iTelObject != aCallObject)
+		return EFalse;
+	return CheckAndCompleteNotification(STATIC_CAST(CTelObject*,aCallObject),aEvent,aLastEvent);
+	}
+//
+// CNotifyLineStatusChange
+//
+CNotifyLineStatusChange* CNotifyLineStatusChange::NewL(RCall::TStatus* aStatus,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	{
+	return new(ELeave) CNotifyLineStatusChange(aStatus,aReqHandle,aTelObject);
+	}
+
+CNotifyLineStatusChange::CNotifyLineStatusChange(RCall::TStatus* aStatus,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	 : CNotifyBase(aReqHandle,aTelObject),iStatus(aStatus)
+	{}
+	
+CNotifyLineStatusChange::~CNotifyLineStatusChange()
+	{}
+
+TBool CNotifyLineStatusChange::CheckAndCompleteNotification(CTelObject* /*aTelObject*/,TEvent aEvent,TEvent aLastEvent)
+	{
+	if ((aEvent==ERingOccurred && aLastEvent!=ERingOccurred) ||
+		(aEvent==EBegunConnecting && aLastEvent!=EBegunConnecting) ||
+		(aEvent==EConnected && aLastEvent!=EConnected) ||
+		(aEvent==EBegunHangingUp && aLastEvent!=EBegunHangingUp) ||
+		(aEvent==EBecomeIdle && aLastEvent!=EBecomeIdle))
+		{
+		REINTERPRET_CAST(CLineHayes*,iTelObject)->GetLineStatus(*iStatus);
+		LOGTEXT2(_L8("Event %d:\tLine Status change Notification completed"),aEvent);
+		iTelObject->ReqCompleted(iReqHandle,KErrNone);
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+TBool CNotifyLineStatusChange::CheckAndCompleteNotification(CCallBase* aCallObject,TEvent aEvent,TEvent aLastEvent)
+	{
+	if (iTelObject == REINTERPRET_CAST(CLineHayes*,aCallObject->Owner()))
+		return CheckAndCompleteNotification(STATIC_CAST(CTelObject*,aCallObject),aEvent,aLastEvent);
+	else 
+		return EFalse;
+	}
+
+
+//
+// CNotifyMobileLineStatusChange
+//
+CNotifyMobileLineStatusChange* CNotifyMobileLineStatusChange::NewL(RMobileCall::TMobileCallStatus* aStatus,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	{
+	return new(ELeave) CNotifyMobileLineStatusChange(aStatus,aReqHandle,aTelObject);
+	}
+
+CNotifyMobileLineStatusChange::CNotifyMobileLineStatusChange(RMobileCall::TMobileCallStatus* aStatus,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	 : CNotifyBase(aReqHandle,aTelObject),iStatus(aStatus)
+	{}
+	
+CNotifyMobileLineStatusChange::~CNotifyMobileLineStatusChange()
+	{}
+
+TBool CNotifyMobileLineStatusChange::CheckAndCompleteNotification(CTelObject* /*aTelObject*/,TEvent aEvent,TEvent aLastEvent)
+	{
+	if ((aEvent==ERingOccurred && aLastEvent!=ERingOccurred) ||
+		(aEvent==EBegunConnecting && aLastEvent!=EBegunConnecting) ||
+		(aEvent==EConnected && aLastEvent!=EConnected) ||
+		(aEvent==EBegunHangingUp && aLastEvent!=EBegunHangingUp) ||
+		(aEvent==EBecomeIdle && aLastEvent!=EBecomeIdle))
+		{
+		RCall::TStatus coreStatus;
+		REINTERPRET_CAST(CLineHayes*,iTelObject)->GetLineStatus(coreStatus);
+		//*iStatus = static_cast<RMobileCall::TMobileCallStatus>(coreStatus);
+		*iStatus = (RMobileCall::TMobileCallStatus)coreStatus;
+		LOGTEXT2(_L8("Event %d:\tMobile Line Status Change Notification completed"),aEvent);
+		iTelObject->ReqCompleted(iReqHandle,KErrNone);
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+TBool CNotifyMobileLineStatusChange::CheckAndCompleteNotification(CCallBase* aCallObject,TEvent aEvent,TEvent aLastEvent)
+	{
+	if (iTelObject == REINTERPRET_CAST(CLineHayes*,aCallObject->Owner()))
+		return CheckAndCompleteNotification(STATIC_CAST(CTelObject*,aCallObject),aEvent,aLastEvent);
+	else 
+		return EFalse;
+	}
+
+//
+// CNotifyLineNewCallAdded
+//
+CNotifyLineNewCallAdded* CNotifyLineNewCallAdded::NewL(TDes* aName,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	{
+	return new(ELeave) CNotifyLineNewCallAdded(aName,aReqHandle,aTelObject);
+	}
+
+CNotifyLineNewCallAdded::CNotifyLineNewCallAdded(TDes* aName,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	 : CNotifyBase(aReqHandle,aTelObject),iName(aName)
+	{}
+	
+CNotifyLineNewCallAdded::~CNotifyLineNewCallAdded()
+	{}
+
+TBool CNotifyLineNewCallAdded::CheckAndCompleteNotification(CTelObject* aTelObject,TEvent aEvent,TEvent /*aLastEvent*/)
+//
+//	No need to check here whether the last event for this TelObject was Call Added, because this
+//	notification should complete every time a new call is added, irrespective of what has
+//	happened inbetween times.
+//
+	{
+	if (aEvent==ECallAdded && iTelObject==aTelObject)
+		{
+		REINTERPRET_CAST(CLineHayes*,iTelObject)->GetLastCallName(*iName);
+		LOGTEXT2(_L8("Event %d:\tNew Call Added Notification completed"),aEvent);
+		iTelObject->ReqCompleted(iReqHandle,KErrNone);
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+//
+// CNotifyCallStatusChange
+//
+CNotifyCallStatusChange* CNotifyCallStatusChange::NewL(RCall::TStatus* aStatus,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	{
+	return new(ELeave) CNotifyCallStatusChange(aStatus,aReqHandle,aTelObject);
+	}
+
+CNotifyCallStatusChange::CNotifyCallStatusChange(RCall::TStatus* aStatus,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	 : CNotifyBase(aReqHandle,aTelObject),iStatus(aStatus)
+	{}
+
+CNotifyCallStatusChange::~CNotifyCallStatusChange()
+	{}
+
+/*
+TBool CNotifyCallStatusChange::CheckAndCompleteNotification(CTelObject* aTelObject,TEvent aEvent,TEvent aLastEvent)
+//
+//	All calls are set ringing if a RING occurs
+//
+	{
+	if (aEvent==ERingOccurred && aLastEvent!=ERingOccurred) 
+		{	
+		*iStatus = RCall::EStatusRinging;
+		LOGTEXT2(_L8("Event %d:\tCall Status Change Notification completed from non-call-derived object"),aEvent);
+		iTelObject->ReqCompleted(iReqHandle,KErrNone);
+		return ETrue;
+		}
+	return EFalse;
+	}
+*/
+
+TBool CNotifyCallStatusChange::CheckAndCompleteNotification(CCallBase* aCallObject,TEvent aEvent,TEvent aLastEvent)
+	{
+	if ((aEvent==ERingOccurred && aLastEvent!=ERingOccurred) ||
+		(aEvent==EBegunConnecting && aLastEvent!=EBegunConnecting) ||
+		(aEvent==EConnected && aLastEvent!=EConnected) ||
+		(aEvent==EBegunHangingUp && aLastEvent!=EBegunHangingUp) ||
+		(aEvent==EBecomeIdle && aLastEvent!=EBecomeIdle))
+		{
+		if (iTelObject == aCallObject)
+					// correct call
+			{
+			LOGTEXT2(_L8("Event %d:\tCall Status Change Notification completed"),aEvent);
+			RMobileCall::TMobileCallStatus callStatus = REINTERPRET_CAST(CCallHayes*,aCallObject)->CallInfo()->iMobileStatus;
+			*iStatus = (RCall::TStatus)callStatus;  // should really call a proper conversion function here
+			iTelObject->ReqCompleted(iReqHandle,KErrNone);
+			return ETrue;
+			}
+		}
+	return EFalse;
+	}
+
+
+//
+// CNotifyMobileCallStatusChange
+//
+CNotifyMobileCallStatusChange* CNotifyMobileCallStatusChange::NewL(RMobileCall::TMobileCallStatus* aStatus,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	{
+	return new(ELeave) CNotifyMobileCallStatusChange(aStatus,aReqHandle,aTelObject);
+	}
+
+CNotifyMobileCallStatusChange::CNotifyMobileCallStatusChange(RMobileCall::TMobileCallStatus* aStatus,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	 : CNotifyBase(aReqHandle,aTelObject),iStatus(aStatus)
+	{}
+
+CNotifyMobileCallStatusChange::~CNotifyMobileCallStatusChange()
+	{}
+
+TBool CNotifyMobileCallStatusChange::CheckAndCompleteNotification(CCallBase* aCallObject,TEvent aEvent,TEvent aLastEvent)
+	{
+	if ((aEvent==ERingOccurred && aLastEvent!=ERingOccurred) ||
+		(aEvent==EBegunConnecting && aLastEvent!=EBegunConnecting) ||
+		(aEvent==EConnected && aLastEvent!=EConnected) ||
+		(aEvent==EBegunHangingUp && aLastEvent!=EBegunHangingUp) ||
+		(aEvent==EBecomeIdle && aLastEvent!=EBecomeIdle))
+		{
+		if (iTelObject == aCallObject)
+					// correct call
+			{
+			LOGTEXT2(_L8("Event %d:\tNotify Mobile Call Status Change completed"),aEvent);
+			*iStatus = REINTERPRET_CAST(CCallHayes*,aCallObject)->CallInfo()->iMobileStatus;
+			iTelObject->ReqCompleted(iReqHandle,KErrNone);
+			return ETrue;
+			}
+		}
+	return EFalse;
+	}
+
+//
+// CNotifyCallDurationChange
+//
+CNotifyCallDurationChange* CNotifyCallDurationChange::NewL(TTimeIntervalSeconds* aTime,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	{
+	return new(ELeave) CNotifyCallDurationChange(aTime,aReqHandle,aTelObject);
+	}
+	
+CNotifyCallDurationChange::CNotifyCallDurationChange(TTimeIntervalSeconds* aTime,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	 : CNotifyBase(aReqHandle,aTelObject),iTime(aTime)
+	{}
+
+CNotifyCallDurationChange::~CNotifyCallDurationChange()
+	{}
+
+TBool CNotifyCallDurationChange::CheckAndCompleteNotification(CCallBase* aCallObject,TEvent aEvent,TEvent /*aLastEvent*/)
+	{
+	if (iTelObject != aCallObject)
+		return EFalse;
+	if (aEvent==ETimePeriodElapsed)
+		{
+		REINTERPRET_CAST(CCallHayes*,aCallObject)->GetCallDuration(*iTime);
+		iTelObject->ReqCompleted(iReqHandle,KErrNone);
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+//
+// CNotifyCallCaps 
+//
+CNotifyCallCaps* CNotifyCallCaps::NewL(RCall::TCaps* aCaps,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	{
+	return new(ELeave) CNotifyCallCaps(aCaps,aReqHandle,aTelObject);
+	}
+	
+CNotifyCallCaps::CNotifyCallCaps(RCall::TCaps* aCaps,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	 : CNotifyBase(aReqHandle,aTelObject),iCaps(aCaps)
+	{}
+
+CNotifyCallCaps::~CNotifyCallCaps()
+	{}
+
+TBool CNotifyCallCaps::CheckAndCompleteNotification(CTelObject* /*aTelObject*/,TEvent aEvent,TEvent aLastEvent)
+//
+// Dynamic call caps change when :
+//	(a) Call starts to connect - cannot dial/answer/hangup
+//	(b) Call has connected - cannot dial/answer. Can hangup/loan data port
+//	(c) Data port is loaned - cannot dial/answer/hang up/loan dataport. Can Recover data port.
+//	(d) Call begins to hang up - cannot do anything.
+//	(e) Call is in idle state - depends if any other call is being used to connect.
+//
+	{
+	if (aEvent==aLastEvent && aEvent!=ECallAdded)
+		return EFalse;
+	if (aEvent==EPhoneDetected || aEvent==EPhoneNotDetected ||
+		aEvent==EBegunConnecting || aEvent==EConnected ||
+		aEvent==EBegunHangingUp || aEvent==EBecomeIdle ||
+		aEvent==EDataPortLoaned || aEvent==EDataPortRecovered)
+		{
+		TBool changed = REINTERPRET_CAST(CCallHayes*,iTelObject)->CollateCurrentCoreCaps(iReqHandle, reinterpret_cast<TUint32*>(&iCaps->iFlags));
+		if (changed)
+			{
+			iTelObject->ReqCompleted(iReqHandle,KErrNone);
+			return ETrue;
+			}
+		}
+	return EFalse;
+	}
+
+TBool CNotifyCallCaps::CheckAndCompleteNotification(CCallBase* aCallObject,TEvent aEvent,TEvent aLastEvent)
+	{
+//	if (iTelObject == aCallObject)
+		return CheckAndCompleteNotification(STATIC_CAST(CTelObject*,aCallObject),aEvent,aLastEvent);
+//	else 
+//		return EFalse;
+	}
+
+//
+// CNotifyMobileCallCaps 
+//
+CNotifyMobileCallCaps* CNotifyMobileCallCaps::NewL(TDes8* aCaps,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	{
+	return new(ELeave) CNotifyMobileCallCaps(aCaps,aReqHandle,aTelObject);
+	}
+	
+CNotifyMobileCallCaps::CNotifyMobileCallCaps(TDes8* aCaps,TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	 : CNotifyBase(aReqHandle,aTelObject)
+	{
+	iCapsPckg = REINTERPRET_CAST(RMobileCall::TMobileCallCapsV1Pckg *,aCaps);
+	}
+
+CNotifyMobileCallCaps::~CNotifyMobileCallCaps()
+	{}
+
+TBool CNotifyMobileCallCaps::CheckAndCompleteNotification(CTelObject* /*aTelObject*/,TEvent aEvent,TEvent aLastEvent)
+//
+// Dynamic call caps change when :
+//	(a) Call starts to connect - cannot dial/answer/hangup
+//	(b) Call has connected - cannot dial/answer. Can hangup/loan data port
+//	(c) Data port is loaned - cannot dial/answer/hang up/loan dataport. Can Recover data port.
+//	(d) Call begins to hang up - cannot do anything.
+//	(e) Call is in idle state - depends if any other call is being used to connect.
+//
+	{
+	if (aEvent==aLastEvent && aEvent!=ECallAdded)
+		return EFalse;
+	if (aEvent==EPhoneDetected || aEvent==EPhoneNotDetected ||
+		aEvent==EBegunConnecting || aEvent==EConnected ||
+		aEvent==EBegunHangingUp || aEvent==EBecomeIdle ||
+		aEvent==EDataPortLoaned || aEvent==EDataPortRecovered)
+		{
+		RMobileCall::TMobileCallCapsV1& caps = (*iCapsPckg)();
+		TBool changed = REINTERPRET_CAST(CCallHayes*,iTelObject)->CollateCurrentMobileCaps(iReqHandle, &(caps.iCallControlCaps));
+		if (changed)
+			{
+			iTelObject->ReqCompleted(iReqHandle,KErrNone);
+			return ETrue;
+			}
+		}
+	return EFalse;
+	}
+
+TBool CNotifyMobileCallCaps::CheckAndCompleteNotification(CCallBase* aCallObject,TEvent aEvent,TEvent aLastEvent)
+	{
+	return CheckAndCompleteNotification(STATIC_CAST(CTelObject*,aCallObject),aEvent,aLastEvent);
+	}
+
+//
+// CNotifyFaxReadOrWrite 
+//
+CNotifyFaxReadOrWrite* CNotifyFaxReadOrWrite::NewL(TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	{
+	return new(ELeave) CNotifyFaxReadOrWrite(aReqHandle,aTelObject);
+	}
+
+CNotifyFaxReadOrWrite::CNotifyFaxReadOrWrite(TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	 : CNotifyBase(aReqHandle,aTelObject)
+	{}
+
+CNotifyFaxReadOrWrite::~CNotifyFaxReadOrWrite()
+	{}
+
+TBool CNotifyFaxReadOrWrite::CheckAndCompleteNotification(CFaxSession* /*aETelFaxObject*/,TEvent aEvent,TInt aError,TAny* /*aParams*/)
+	{
+	if (aEvent==EFaxReadOrWriteCompleted || aEvent==EFaxSessionTerminated)
+		{
+		iTelObject->ReqCompleted(iReqHandle,aError);
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+//
+// CNotifyEndOfFaxPage
+//
+CNotifyFaxEndOfPage* CNotifyFaxEndOfPage::NewL(TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	{
+	return new(ELeave) CNotifyFaxEndOfPage(aReqHandle,aTelObject);
+	}
+
+CNotifyFaxEndOfPage::CNotifyFaxEndOfPage(TTsyReqHandle aReqHandle,CTelObject* aTelObject)
+	 : CNotifyBase(aReqHandle,aTelObject)
+	{}
+
+CNotifyFaxEndOfPage::~CNotifyFaxEndOfPage()
+	{}
+
+TBool CNotifyFaxEndOfPage::CheckAndCompleteNotification(CFaxSession* /*aETelFaxObject*/,TEvent aEvent,TInt aError,TAny* /*aParams*/)
+	{
+	if (aEvent==EEndOfFaxPageCompleted || aEvent==EFaxSessionTerminated)
+		{
+		LOGTEXT2(_L8("Event %d:\tFax End Of Page Notification completed"),aEvent);
+		iTelObject->ReqCompleted(iReqHandle,aError);
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+