--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyserverplugins/multimodetsy/hayes/LINE.CPP Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,1072 @@
+// 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 "PHONE.H"
+#include "LINE.H"
+#include "CALL.H"
+#include "mSLOGGER.H"
+#include "ATINIT.H"
+#include "NOTIFY.H"
+#include "et_struct.h"
+
+//
+// Dummy function is necessary so that compiler knows how to expand a TPckg<RLine::TLineInfo>
+//
+
+void CLineHayes::Dummy1()
+ {
+ RLine::TLineInfo dummy0;
+ TPckg<RLine::TLineInfo> dummy1(dummy0);
+ dummy1.Zero();
+ }
+
+//
+// CLineHayes
+// General Line Functionality
+//
+void CLineHayes::CloseLine(TAny* aObj)
+//
+// Utility func for cleanup stack
+//
+ {
+ ((CObject*)aObj)->Close();
+ }
+
+CLineHayes::CLineHayes(CATIO* aATIO,CATInit* aInit,CPhoneGlobals* aPhoneGlobals) : iIo(aATIO)
+ ,iInit(aInit),iPhoneGlobals(aPhoneGlobals)
+ {}
+
+void CLineHayes::ConstructL(const TName& aName)
+ {
+ LOGTEXT(_L8("CLineHayes::ConstructL()"));
+ iLineName = aName;
+ iCalls.SetOffset(_FOFF(CCallEntry,iLink));
+ iSizeOfMemberData = new(ELeave) CArrayFixFlat<TInt>(4);
+ }
+
+void CLineHayes::AppendNewCallL(CCallHayes* aNewCall)
+ {
+ CCallEntry* entry = CCallEntry::NewL(aNewCall);
+ iCalls.AddLast(*entry);
+ }
+
+CLineHayes::~CLineHayes()
+ {
+ LOGTEXT(_L8("CLineHayes Destructor"));
+ if (Owner())
+ ((CPhoneHayes*)Owner())->RemoveLine(this);
+ iPhoneGlobals->iNotificationStore->RemoveClientFromLastEvents(this);
+ if (iSizeOfMemberData!=NULL)
+ iSizeOfMemberData->Reset();
+ delete iSizeOfMemberData;
+
+ CCallEntry* callEntry;
+ TDblQueIter<CCallEntry> iter(iCalls);
+ if (!(iCalls.IsEmpty()))
+ {
+ while (callEntry=iter++, callEntry)
+ {
+ if (callEntry->iCallHayes->IsOwnedByTSY())
+ {
+ callEntry->Deque();
+ callEntry->iCallHayes->Close();
+ delete callEntry;
+ __ASSERT_ALWAYS(iCalls.IsEmpty(),Panic(ECalls_Remaining));
+ return; // there should not be an iPreAlloc if one of the calls in the list was still
+ // owned by the TSY (ie no client had taken a handle on it)
+ }
+ }
+ }
+ if (iPreAlloc)
+ {
+ __ASSERT_ALWAYS(iPreAlloc,Panic(EPreAllocatedCallDoesNotExist));
+ iPreAlloc->iCallHayes->Close();
+ delete iPreAlloc;
+ }
+ }
+
+CTelObject::TReqMode CLineHayes::ReqModeL(const TInt aIpc)
+ {
+ TReqMode reqMode = CLineBase::ReqModeL(aIpc);
+ if ((reqMode & KReqModeFlowControlObeyed) && iPhoneGlobals->iPhoneStatus.iDataPortLoaned)
+ {
+ LOGTEXT2(_L8("ReqModeL Leaving with KErrInUse as data port is loaned (aIpc=%d)"),aIpc);
+ User::Leave(KErrInUse);
+ }
+ return reqMode;
+ }
+
+TInt CLineHayes::RegisterNotification(const TInt /*aIpc*/)
+ {
+ return KErrNone;
+ }
+
+TInt CLineHayes::DeregisterNotification(const TInt /*aIpc*/)
+ {
+ return KErrNone;
+ }
+
+void CLineHayes::Init()
+ {}
+
+TInt CLineHayes::NotifyIncomingCall(const TTsyReqHandle aTsyReqHandle, TName* aName)
+ {
+ iPhoneGlobals->iNotificationStore->RegisterNotification(EIncomingCall,aTsyReqHandle,this,aName);
+ LOGTEXT(_L8("Line:\tIncoming Call Notification lodged"));
+ iNotifyIncomingCallOutstanding=ETrue;
+
+ CCallEntry* callEntry;
+ TDblQueIter<CCallEntry> iter(iCalls);
+ while (callEntry=iter++, callEntry)
+ {
+ if ((callEntry->iCallHayes->CallInfo())->iMobileStatus==RMobileCall::EStatusRinging)
+ {
+ iPhoneGlobals->iNotificationStore->CheckNotification(callEntry->iCallHayes,ERingOccurred);
+ break;
+ }
+ }
+ if (iPhoneGlobals->iPhoneStatus.iInitStatus==EPhoneNotInitialised)
+ {
+ FlowControlSuspend();
+ iInit->SpecialStart();
+ }
+ return KErrNone;
+ }
+
+TInt CLineHayes::NotifyIncomingCallCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ LOGTEXT(_L8("Line:\tIncoming Call Notification cancelled"));
+ ResetNotifyIncomingCall();
+ iPhoneGlobals->iNotificationStore->RemoveNotification(aTsyReqHandle);
+ return KErrNone;
+ }
+
+TInt CLineHayes::NotifyHookChange(const TTsyReqHandle aTsyReqHandle, RCall::THookStatus* aHookStatus)
+ {
+ LOGTEXT(_L8("Line:\tHook Change Notification lodged"));
+ iPhoneGlobals->iNotificationStore->RegisterNotification(ELineHookChange,aTsyReqHandle,this,aHookStatus);
+ return KErrNone;
+ }
+
+TInt CLineHayes::NotifyHookChangeCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ LOGTEXT(_L8("Line:\tHook Change Notification cancelled"));
+ iPhoneGlobals->iNotificationStore->RemoveNotification(aTsyReqHandle);
+ return KErrNone;
+ }
+
+TInt CLineHayes::NotifyStatusChange(const TTsyReqHandle aTsyReqHandle, RCall::TStatus* aStatus)
+ {
+ LOGTEXT(_L8("Line:\tStatus Change Notification lodged"));
+ iPhoneGlobals->iNotificationStore->RegisterNotification(ELineStatusChange,aTsyReqHandle,this,aStatus);
+ return KErrNone;
+ }
+
+TInt CLineHayes::NotifyStatusChangeCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ LOGTEXT(_L8("Line:\tStatus Change Notification cancelled"));
+ iPhoneGlobals->iNotificationStore->RemoveNotification(aTsyReqHandle);
+ return KErrNone;
+ }
+
+TInt CLineHayes::NotifyCallAdded(const TTsyReqHandle aTsyReqHandle,TName* aName)
+ {
+ LOGTEXT(_L8("Line:\tCall Added Notification lodged"));
+ iPhoneGlobals->iNotificationStore->RegisterNotification(ENewCallAdded,aTsyReqHandle,this,aName);
+ return KErrNone;
+ }
+
+TInt CLineHayes::NotifyCallAddedCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ LOGTEXT(_L8("Line:\tCall Added Notification cancelled"));
+ iPhoneGlobals->iNotificationStore->RemoveNotification(aTsyReqHandle);
+ return KErrNone;
+ }
+
+TInt CLineHayes::NotifyCapsChange(const TTsyReqHandle aTsyReqHandle, RLine::TCaps* /*aCaps*/)
+ {
+ ReqCompleted(aTsyReqHandle,KErrNotSupported);
+ return KErrNone;
+ }
+
+TInt CLineHayes::NotifyCapsChangeCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ ReqCompleted(aTsyReqHandle,KErrCancel);
+ return KErrNone;
+ }
+
+CCallEntry* CLineHayes::CheckNewObject(const TDesC& aName)
+//
+// Server should have caught any identical names and treated them as new handles on existing
+// objects, and not calling OpenNewObjectL() on the TSY. So panic if there is an identical name,
+// unless it is the name of the pre-allocated call owned by the line in which case the server
+// would not have been aware of it.
+ {
+ CCallEntry* callEntry;
+ TDblQueIter<CCallEntry> iter(iCalls);
+ while(callEntry=iter++, callEntry!=NULL)
+ {
+ if(callEntry->iCallHayes->CheckName(aName))
+ {
+ if (callEntry->iCallHayes->IsOwnedByTSY())
+ return callEntry;
+ else
+ Panic(ECallNameAlreadyExists);
+ }
+ }
+ return NULL;
+ }
+
+TInt CLineHayes::GetInfo(const TTsyReqHandle aTsyReqHandle, RLine::TLineInfo* aLineInfo)
+ {
+ aLineInfo->iHookStatus = RCall::EHookStatusOn;
+ aLineInfo->iStatus = RCall::EStatusIdle;
+ CCallEntry* callEntry;
+ TDblQueIter<CCallEntry> iter(iCalls);
+ while (callEntry=iter++, callEntry)
+ {
+ TCallInfoTSY* infoTSY = callEntry->iCallHayes->CallInfo();
+ if (infoTSY->iHookStatus == RCall::EHookStatusOff)
+ {
+ aLineInfo->iHookStatus = RCall::EHookStatusOff;
+ }
+ if (callEntry->iCallHayes->GetCoreCallStatus() == iPhoneGlobals->iPhoneStatus.iLineStatus)
+ {
+ aLineInfo->iStatus = iPhoneGlobals->iPhoneStatus.iLineStatus;
+ }
+ }
+ GetLastCallName(aLineInfo->iNameOfLastCallAdded);
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+TInt CLineHayes::GetStatus(const TTsyReqHandle aTsyReqHandle,RCall::TStatus* aLineStatus)
+//
+// This line may not be the one on which a call is being made, so check to see if any of
+// the calls on this line have the same status as the 'global' line status and if so, this
+// can be assumed to be that line
+//
+ {
+ CCallEntry* callEntry;
+ TDblQueIter<CCallEntry> iter(iCalls);
+ while(callEntry=iter++, callEntry!=NULL)
+ {
+ if (callEntry->iCallHayes->GetCoreCallStatus() == iPhoneGlobals->iPhoneStatus.iLineStatus)
+ {
+ *aLineStatus = iPhoneGlobals->iPhoneStatus.iLineStatus;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+ }
+ *aLineStatus = RCall::EStatusIdle;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+TInt CLineHayes::EnumerateCall(const TTsyReqHandle aTsyReqHandle,TInt* aParams)
+//
+// Enumerate calls
+//
+ {
+ LOGTEXT(_L8("Line:\tEnumerate Calls"));
+ TInt count=0;
+ TDblQueIter<CCallEntry> iter(iCalls);
+ while (iter++)
+ {
+ count++;
+ }
+ *aParams = count;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+TInt CLineHayes::GetHookStatus(const TTsyReqHandle aTsyReqHandle,RCall::THookStatus* aHookStatus)
+//
+// Hook is considered ON if no calls exist on this line, or if all calls are idle
+// OFF if at least one is not idle. Should not be more than one active call.
+//
+ {
+ LOGTEXT(_L8("Line:\tGet hook status"));
+ RCall::THookStatus hookStatus = RCall::EHookStatusOn;
+ CCallEntry* callEntry;
+ TDblQueIter<CCallEntry> iter(iCalls);
+ while (callEntry=iter++, callEntry)
+ {
+ if (callEntry->iCallHayes->CallInfo()->iHookStatus == RCall::EHookStatusOff)
+ {
+ hookStatus = RCall::EHookStatusOff;
+ break; // if any calls are active, line hook status is off
+ }
+ }
+ *aHookStatus = hookStatus;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+void CLineHayes::SetCallsHookStatus(RCall::THookStatus aHookStatus)
+//
+// Is it valid to set all calls to a certain hook status at any time?
+//
+ {
+ CCallEntry* callEntry;
+ TDblQueIter<CCallEntry> iter(iCalls);
+ while (callEntry=iter++, callEntry)
+ callEntry->iCallHayes->CallInfo()->iHookStatus = aHookStatus;
+ }
+
+TBool CLineHayes::StopMyCallRinging()
+ {
+ CCallEntry* callEntry;
+ TDblQueIter<CCallEntry> iter(iCalls);
+ while (callEntry=iter++, callEntry)
+ {
+ if (callEntry->iCallHayes->CallInfo()->iMobileStatus==RMobileCall::EStatusRinging)
+ {
+ // EStatusIdle always results in KErrNone return
+ (void)callEntry->iCallHayes->ChangeCallStatus(RMobileCall::EStatusIdle);
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+void CLineHayes::GetLineStatus(RCall::TStatus& aLineStatus)
+ {
+ aLineStatus=iPhoneGlobals->iPhoneStatus.iLineStatus;
+ }
+
+void CLineHayes::RemoveCall(CCallHayes* aCallHayes)
+//
+// When a call closes, it calls this to remove itself from the array
+//
+ {
+ CCallEntry* callEntry;
+ TDblQueIter<CCallEntry> iter(iCalls);
+ while (callEntry=iter++, callEntry)
+ {
+ if (callEntry->iCallHayes == aCallHayes)
+ {
+ callEntry->Deque();
+ delete callEntry; // just deletes list entry, not the call itself
+ break;
+ }
+ }
+ }
+
+void CLineHayes::GetLastCallName(TDes& aName) const
+ {
+ TCallInfoIndex callInfo;
+ if (iCalls.IsEmpty())
+ {
+ aName.Zero();
+ return;
+ }
+ CCallEntry* callEntry = iCalls.Last();
+ __ASSERT_ALWAYS(callEntry,Panic(ENewCallDoesNotExist));
+ callEntry->iCallHayes->GetCallInfo(&callInfo);
+ aName = callInfo.iInfo.iCallName;
+ }
+
+void CLineHayes::GetNameOfCallForAnswering(TDes& aName)
+ {
+ TCallInfoIndex callInfo;
+ CCallEntry* callEntry;
+ TDblQueIter<CCallEntry> iter(iCalls);
+ while (callEntry=iter++, callEntry)
+ {
+ if (callEntry->iCallHayes->IsForIncomingCall() || callEntry->iCallHayes->IsOwnedByTSY())
+ {
+ callEntry->iCallHayes->GetCallInfo(&callInfo);
+ aName = callInfo.iInfo.iCallName;
+ return;
+ }
+ }
+ aName.Zero();
+ }
+
+TBool CLineHayes::AnswerIfPossible()
+//
+// Finds the call on this line which has been asked to Answer the next incoming call, if it
+// exists, and tells it to answer.
+//
+ {
+ CCallEntry* callEntry;
+ TDblQueIter<CCallEntry> iter(iCalls);
+ while (callEntry=iter++, callEntry)
+ {
+ if ((callEntry->iCallHayes->IsForIncomingCall()))
+ {
+ callEntry->iCallHayes->AnswerImmediately();
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+TBool CLineHayes::CheckForOutstandingAnswer()
+ {
+ CCallEntry* callEntry;
+ TDblQueIter<CCallEntry> iter(iCalls);
+ while (callEntry=iter++, callEntry)
+ {
+ if (callEntry->iCallHayes->IsForIncomingCall())
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+const CArrayFixFlat<TInt>* CLineHayes::ArrayOfMemberDataSizes(const TInt /*aIpc*/) const
+ {
+ return iSizeOfMemberData;
+ }
+
+void CLineHayes::ResetNotifyIncomingCall()
+ {
+ iNotifyIncomingCallOutstanding=EFalse;
+ }
+
+TBool CLineHayes::IsNotifyIncomingCallOutstanding()
+ {
+ return iNotifyIncomingCallOutstanding;
+ }
+
+//
+// Unimplemented Line Request Functions
+//
+
+TInt CLineHayes::ExtFunc(const TTsyReqHandle,const TInt, const TDataPackage&)
+//
+// Extensions aren't supported in this TSY
+//
+ {
+ return KErrNotSupported;
+ }
+
+
+/*
+ * CLineMobile class that implements Multimode ETel Mobile Call requests
+ */
+
+CLineMobile::CLineMobile(CATIO* aIo,CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
+ : CLineHayes(aIo, aInit, aPhoneGlobals)
+ {}
+
+CLineMobile::~CLineMobile()
+ {
+ }
+
+CTelObject::TReqMode CLineMobile::ReqModeL(const TInt aIpc)
+ {
+ // ReqModeL is called from the server's CTelObject::ReqAnalyserL
+ // in order to check the type of request it has
+
+ CTelObject::TReqMode ret=0;
+ switch (aIpc)
+ {
+//
+// No Flow Control NOR Multiple Completion
+//
+ case EMobileLineGetMobileLineStatus:
+ break;
+
+//
+// Multiple Completion Services with Immediate Server Repost
+// (Usually Notifications)
+//
+ case EMobileLineNotifyMobileLineStatusChange:
+ ret=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately;
+ break;
+//
+// Not Supported
+//
+ default:
+ ret=CLineHayes::ReqModeL(aIpc);
+ break;
+ }
+
+ return ret;
+ }
+
+
+TInt CLineMobile::NumberOfSlotsL(const TInt aIpc)
+ {
+ // NumberOfSlotsL is called by the server when it is registering a new notification
+ // It enables the TSY to tell the server how many buffer slots to allocate for
+ // "repost immediately" notifications that may trigger before clients collect them
+
+ TInt numberOfSlots=1;
+ switch (aIpc)
+ {
+ case EMobileLineNotifyMobileLineStatusChange:
+ LOGTEXT(_L8("CLineMobile: Registered with 5 slots"));
+ numberOfSlots=5;
+ break;
+ default:
+ numberOfSlots = CLineBase::NumberOfSlotsL(aIpc);
+ break;
+ }
+ return numberOfSlots;
+ }
+
+
+TInt CLineMobile::ExtFunc(const TTsyReqHandle aTsyReqHandle,const TInt aIpc,
+ const TDataPackage& aPackage)
+ {
+ // ExtFunc is called by the server when it has a "extended", i.e. non-core ETel request
+ // for the TSY to process
+ // A request handle, request type and request data are passed to the TSY
+
+ TAny* dataPtr=aPackage.Ptr1();
+
+ // The request data has to extracted from TDataPackage and the TAny* pointers have to
+ // be "cast" to the expected request data type
+
+ switch (aIpc)
+ {
+//
+// No Flow Control NOR Multiple Completion
+//
+ case EMobileLineGetMobileLineStatus:
+ return GetMobileLineStatus(aTsyReqHandle,
+ REINTERPRET_CAST(RMobileCall::TMobileCallStatus*,dataPtr));
+
+//
+// Multiple Completion Services with Immediate Server Repost
+// (Usually Notifications)
+//
+ case EMobileLineNotifyMobileLineStatusChange:
+ return NotifyMobileLineStatusChange(aTsyReqHandle,
+ REINTERPRET_CAST(RMobileCall::TMobileCallStatus*, dataPtr));
+//
+// Cancels
+//
+ case EMobileLineNotifyMobileLineStatusChangeCancel:
+ return NotifyMobileLineStatusChangeCancel(aTsyReqHandle);
+
+ default:
+ return KErrNotSupported;
+ }
+ }
+
+TInt CLineMobile::CancelService(const TInt aIpc, const TTsyReqHandle aTsyReqHandle)
+ {
+ // CancelService is called by the server when it is "cleaning-up" any still outstanding
+ // asynchronous requests before closing a client's sub-session.
+ // This will happen if a client closes its R-class handle without cancelling outstanding
+ // asynchronous requests.
+
+ switch (aIpc)
+ {
+ case EMobileLineNotifyMobileLineStatusChange:
+ return NotifyMobileLineStatusChangeCancel(aTsyReqHandle);
+ default:
+ return CLineBase::CancelService(aIpc,aTsyReqHandle);
+ }
+ }
+
+TInt CLineMobile::GetMobileLineStatus(const TTsyReqHandle aTsyReqHandle,RMobileCall::TMobileCallStatus* aStatus)
+ {
+ LOGTEXT(_L8("CLineMobile::GetMobileLineStatus called"));
+ CCallEntry* callEntry;
+ TDblQueIter<CCallEntry> iter(iCalls);
+ while(callEntry=iter++, callEntry!=NULL)
+ {
+ if (callEntry->iCallHayes->GetCoreCallStatus() == iPhoneGlobals->iPhoneStatus.iLineStatus)
+ {
+ //*aStatus = static_cast<RMobileCall::TMobileCallStatus>(iPhoneGlobals->iPhoneStatus.iLineStatus);
+ *aStatus = (RMobileCall::TMobileCallStatus)iPhoneGlobals->iPhoneStatus.iLineStatus;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+ }
+ *aStatus = RMobileCall::EStatusIdle;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+TInt CLineMobile::NotifyMobileLineStatusChange(const TTsyReqHandle aTsyReqHandle,RMobileCall::TMobileCallStatus* aStatus)
+ {
+ LOGTEXT(_L8("CLineMobile::NotifyMobileLineStatusChange lodged"));
+ iPhoneGlobals->iNotificationStore->RegisterNotification(EMobileLineStatusChange,aTsyReqHandle,this,aStatus);
+ return KErrNone;
+ }
+
+TInt CLineMobile::NotifyMobileLineStatusChangeCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ LOGTEXT(_L8("CLineMobile::NotifyMobileLineStatusChangeCancel called"));
+ iPhoneGlobals->iNotificationStore->RemoveNotification(aTsyReqHandle);
+ return KErrNone;
+ }
+
+
+//Added for Java Demo 4.4.99
+//
+// CLineMobileVoice
+// Voice Specific Line Functionality
+//
+CLineMobileVoice* CLineMobileVoice::NewL(CATIO* aATIO,CATInit* aInit,CPhoneGlobals* aPhoneGlobals,const TName& aName)
+ {
+ CLineMobileVoice* voiceLine=new(ELeave) CLineMobileVoice(aATIO,aInit,aPhoneGlobals);
+ TCleanupItem newLineVoiceHayesClose(CloseLine,voiceLine);
+ CleanupStack::PushL(newLineVoiceHayesClose);
+ voiceLine->ConstructL(aName);
+ CleanupStack::Pop();
+ return voiceLine;
+ }
+
+CLineMobileVoice::CLineMobileVoice(CATIO* aATIO, CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
+ :CLineMobile(aATIO,aInit,aPhoneGlobals)
+ {}
+
+void CLineMobileVoice::ConstructL(const TName& aName)
+ {
+ CLineHayes::ConstructL(aName);
+ TName preAllocName;
+ GenerateName(preAllocName);
+ CCallMobileVoice* newCall=CCallMobileVoice::NewL(iIo,iInit,iPhoneGlobals,preAllocName);
+ TCleanupItem newLineClose(CloseLine,newCall);
+ CleanupStack::PushL(newLineClose);
+ newCall->SetNameL(&preAllocName);
+ newCall->SetOwnedByTSY();
+ newCall->SetOwner(this);
+ iPreAlloc = CCallEntry::NewL(newCall);
+ CleanupStack::Pop();
+ }
+
+CLineMobileVoice::~CLineMobileVoice()
+ {}
+
+
+CTelObject* CLineMobileVoice::OpenNewObjectByNameL(const TDesC& aName)
+//
+// Open a voice call by name. This will be called if the user opens a pre-alloc'ed call by name
+//
+ {
+ CCallEntry* entry = NULL;
+ entry=CheckNewObject(aName); //if found in call list, must be a pre-alloc'ed call
+ if (!entry)
+ {
+ CCallMobileVoice* newCall=CCallMobileVoice::NewL(iIo,iInit,iPhoneGlobals,aName);
+ TCleanupItem newLineClose(CloseLine,newCall);
+ CleanupStack::PushL(newLineClose);
+ AppendNewCallL(newCall);
+ CleanupStack::Pop();
+ iPhoneGlobals->iNotificationStore->CheckNotification(this,ECallAdded);
+ return newCall;
+ }
+ else // this is a pre-allocated call
+ {
+ TName preAllocatedCallName; // pre-allocate next call
+ GenerateName(preAllocatedCallName);
+ CCallMobileVoice* call=CCallMobileVoice::NewL(iIo,iInit,iPhoneGlobals,preAllocatedCallName);
+ call->SetOwnedByTSY();
+ (void)User::LeaveIfError(call->SetName(&preAllocatedCallName));
+ call->SetOwner(this);
+ iPreAlloc = CCallEntry::NewL(call);
+
+ CCallHayes* oldpreAllocCall = entry->iCallHayes;
+ oldpreAllocCall->SetUnownedByTSY();
+ return oldpreAllocCall;
+ }
+ }
+
+CTelObject* CLineMobileVoice::OpenNewObjectL(TDes& aNewName)
+//
+// Open a voice call and return a name
+//
+ {
+ GenerateName(aNewName);
+ CCallMobileVoice* newCall=CCallMobileVoice::NewL(iIo,iInit,iPhoneGlobals,aNewName);
+ TCleanupItem newLineClose(CloseLine,newCall);
+ CleanupStack::PushL(newLineClose);
+ AppendNewCallL(newCall);
+ CleanupStack::Pop();
+ iPhoneGlobals->iNotificationStore->CheckNotification(this,ECallAdded);
+ return newCall;
+ }
+
+void CLineMobileVoice::GenerateName(TDes& aName)
+ {
+ aName.Append(KVoiceCallName);
+ aName.AppendNum(iNameIndex++);
+ }
+
+TInt CLineMobileVoice::GetCaps(const TTsyReqHandle aTsyReqHandle,RLine::TCaps* aLineCaps)
+ {
+ aLineCaps->iFlags = RLine::KCapsEventIncomingCall;
+ aLineCaps->iFlags |= RLine::KCapsVoice;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+TInt CLineMobileVoice::GetCallInfo(const TTsyReqHandle aTsyReqHandle,TCallInfoIndex* /*aCallInfoIndex*/)
+//
+// Provide info about voice call
+//
+ {
+ ReqCompleted(aTsyReqHandle,KErrNotSupported);
+ return KErrNone;
+ }
+
+//
+// CLineMobileData
+// Data Specific Line Functionality
+//
+CLineMobileData* CLineMobileData::NewL(CATIO* aATIO, CATInit* aInit,CPhoneGlobals* aPhoneGlobals,const TName& aName)
+ {
+ CLineMobileData* dataLine=new(ELeave) CLineMobileData(aATIO,aInit,aPhoneGlobals);
+ TCleanupItem newLineDataHayesClose(CloseLine,dataLine);
+ CleanupStack::PushL(newLineDataHayesClose);
+ dataLine->ConstructL(aName);
+ CleanupStack::Pop();
+ return dataLine;
+ }
+
+CLineMobileData::CLineMobileData(CATIO* aATIO, CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
+ :CLineMobile(aATIO,aInit,aPhoneGlobals)
+ {}
+
+void CLineMobileData::ConstructL(const TName& aName)
+//
+// Constructs a call which is to be used only when an incoming call arrives
+// and no client has designated an existing call to answer it. TSY holds responsibility to close
+// it unless a RING occurs, when the line will add the call to the linked list of calls
+// and alert any interested clients that a "new" call has been created - if any client then
+// opens a handle on it, the TSY relinquishes any responsibility to close it in the future
+// as the client has that responsibility. When the client opens a handle on it, using OpenByName
+// the line will create a new PreAlloc'ed call. If no client opens a handle, when the line
+// stops ringing the line will remove the pre-alloc'ed call from the list and keep the pointer
+// to it separately in CLineHayes::iPreAlloc, so any subsequent attempt by a client to
+// open a handle on it will fail with KErrDoesNotExist or something similar.
+//
+ {
+ CLineHayes::ConstructL(aName);
+ TName preAllocName;
+ GenerateName(preAllocName);
+ CCallMobileData* newCall=CCallMobileData::NewL(iIo,iInit,iPhoneGlobals,preAllocName);
+ TCleanupItem newLineClose(CloseLine,newCall);
+ CleanupStack::PushL(newLineClose);
+ newCall->SetNameL(&preAllocName);
+ newCall->SetOwnedByTSY();
+ newCall->SetOwner(this);
+ iPreAlloc = CCallEntry::NewL(newCall);
+ CleanupStack::Pop();
+ }
+
+CLineMobileData::~CLineMobileData()
+ {}
+
+CTelObject* CLineMobileData::OpenNewObjectByNameL(const TDesC& aName)
+//
+// Open a data call by name. This will be called if the user opens a pre-alloc'ed call by name
+//
+ {
+ CCallEntry* entry = NULL;
+ entry=CheckNewObject(aName); //if found in call list, must be a pre-alloc'ed call
+ if (!entry)
+ {
+ CCallMobileData* newCall=CCallMobileData::NewL(iIo,iInit,iPhoneGlobals,aName);
+ TCleanupItem newLineClose(CloseLine,newCall);
+ CleanupStack::PushL(newLineClose);
+ AppendNewCallL(newCall);
+ CleanupStack::Pop();
+ iPhoneGlobals->iNotificationStore->CheckNotification(this,ECallAdded);
+ return newCall;
+ }
+ else // this is a pre-allocated call
+ {
+ TName preAllocatedCallName; // pre-allocate next call
+ GenerateName(preAllocatedCallName);
+ CCallMobileData* call=CCallMobileData::NewL(iIo,iInit,iPhoneGlobals,preAllocatedCallName);
+ call->SetOwnedByTSY();
+ (void)User::LeaveIfError(call->SetName(&preAllocatedCallName));
+ call->SetOwner(this);
+ iPreAlloc = CCallEntry::NewL(call);
+
+ CCallHayes* oldpreAllocCall = entry->iCallHayes;
+ oldpreAllocCall->SetUnownedByTSY();
+ return oldpreAllocCall;
+ }
+ }
+
+CTelObject* CLineMobileData::OpenNewObjectL(TDes& aNewName)
+//
+// Open a data call and return a name
+//
+ {
+ GenerateName(aNewName);
+ CCallMobileData* newCall=CCallMobileData::NewL(iIo,iInit,iPhoneGlobals,aNewName);
+ TCleanupItem newLineClose(CloseLine,newCall);
+ CleanupStack::PushL(newLineClose);
+ AppendNewCallL(newCall);
+ CleanupStack::Pop();
+ iPhoneGlobals->iNotificationStore->CheckNotification(this,ECallAdded);
+ return newCall;
+ }
+
+void CLineMobileData::GenerateName(TDes& aName)
+ {
+ aName.Append(KDataCallName);
+ aName.AppendNum(iNameIndex++);
+ }
+
+TInt CLineMobileData::GetCaps(const TTsyReqHandle aTsyReqHandle,RLine::TCaps* aLineCaps)
+ {
+ aLineCaps->iFlags = RLine::KCapsEventIncomingCall;
+ if (iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & RPhone::KCapsData)
+ {
+ aLineCaps->iFlags |= RLine::KCapsData;
+ }
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+TInt CLineMobileData::GetCallInfo(const TTsyReqHandle aTsyReqHandle,TCallInfoIndex* aCallInfoIndex)
+//
+// Provide info about data call
+//
+ {
+ LOGTEXT(_L8("DataLine:\tGet Data Call Info"));
+ CCallEntry* callEntry;
+ TDblQueIter<CCallEntry> iter(iCalls);
+ iter.SetToFirst();
+ for (TInt i=0;i<(TInt)(aCallInfoIndex->iIndex);i++)
+ {
+ iter++;
+ }
+ callEntry=iter;
+ if (callEntry)
+ {
+ callEntry->iCallHayes->GetCallInfo(aCallInfoIndex);
+ aCallInfoIndex->iInfo.iCallCapsFlags |= RCall::KCapsData;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ }
+ else
+ ReqCompleted(aTsyReqHandle,KErrNotFound);
+ return KErrNone;
+ }
+
+void CLineHayes::SetPreAllocCall()
+//
+// If the incoming call hasn't been answered because there were no client-designated "Answerers"
+// on either line, notify any interested client that there is a new call (which is actually the
+// pre-allocated call).
+//
+ {
+ // EStatusRinging always returns KErrNone
+ (void)iPreAlloc->iCallHayes->ChangeCallStatus(RMobileCall::EStatusRinging);
+ iCalls.AddLast(*iPreAlloc);
+ iPhoneGlobals->iNotificationStore->CheckNotification(iPreAlloc->iCallHayes,ERingOccurred);
+ iPhoneGlobals->iNotificationStore->CheckNotification(this,ECallAdded);
+ iPreAlloc = NULL; // pre-alloc'ed call and "call entry" is now owned by iCalls
+ }
+
+void CLineHayes::FreePreAllocCallIfNecessary()
+//
+// Used when answering a call, to check if whether the the answer request has been given on a call object
+// that is not the preallocated call. If it has then free up the preallocated call.
+//
+ {
+ if(!iPreAlloc)
+ {
+ ResetPreAllocCall();
+ }
+ }
+
+void CLineHayes::ResetPreAllocCall()
+//
+// Removes the TSY-owned Pre allocated call from the list of calls and returns it to iPreAlloc.
+//
+ {
+ CCallEntry* callEntry;
+ TDblQueIter<CCallEntry> iter(iCalls);
+ while (callEntry=iter++, callEntry)
+ {
+ if ((callEntry->iCallHayes->IsOwnedByTSY()))
+ {
+ callEntry->Deque();
+ iPreAlloc = callEntry;
+ iPreAlloc->iCallHayes->ResetIsForIncomingCall();
+ }
+ }
+ }
+
+//
+// CLineMobileFax
+// Fax Specific Line Functionality
+//
+CLineMobileFax* CLineMobileFax::NewL(CATIO* aATIO, CATInit* aInit,CPhoneGlobals* aPhoneGlobals,const TName& aName)
+ {
+ CLineMobileFax* FaxLine=new(ELeave) CLineMobileFax(aATIO,aInit,aPhoneGlobals);
+ TCleanupItem newLineFaxHayesClose(CloseLine,FaxLine);
+ CleanupStack::PushL(newLineFaxHayesClose);
+ FaxLine->ConstructL(aName);
+ CleanupStack::Pop();
+ return FaxLine;
+ }
+
+CLineMobileFax::CLineMobileFax(CATIO* aATIO, CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
+ :CLineMobile(aATIO,aInit,aPhoneGlobals)
+ {}
+
+void CLineMobileFax::ConstructL(const TName& aName)
+//
+// Constructs a call which is to be used only when an incoming call arrives
+// and no client has designated an existing call to answer it. TSY holds responsibility to close
+// it unless a RING occurs, when the line will add the call to the linked list of calls
+// and alert any interested clients that a "new" call has been created - if any client then
+// opens a handle on it, the TSY relinquishes any responsibility to close it in the future
+// as the client has that responsibility. When the client opens a handle on it, using OpenByName
+// the line will create a new PreAlloc'ed call. If no client opens a handle, when the line
+// stops ringing the line will remove the pre-alloc'ed call from the list and keep the pointer
+// to it separately in CLineHayes::iPreAlloc, so any subsequent attempt by a client to
+// open a handle on it will fail with KErrDoesNotExist or something similar.
+//
+ {
+ CLineHayes::ConstructL(aName);
+ TName preAllocName;
+ GenerateName(preAllocName);
+ CCallMobileFax* newCall=CCallMobileFax::NewL(iIo,iInit,iPhoneGlobals,preAllocName);
+ TCleanupItem newLineClose(CloseLine,newCall);
+ CleanupStack::PushL(newLineClose);
+ newCall->SetNameL(&preAllocName);
+ newCall->SetOwnedByTSY();
+ newCall->SetOwner(this);
+ iPreAlloc = CCallEntry::NewL(newCall);
+ CleanupStack::Pop();
+ }
+
+CLineMobileFax::~CLineMobileFax()
+ {}
+
+void CLineMobileFax::GenerateName(TDes& aName)
+ {
+ aName.Append(KFaxCallName);
+ aName.AppendNum(iNameIndex++);
+ }
+
+CTelObject* CLineMobileFax::OpenNewObjectByNameL(const TDesC& aName)
+//
+// Open a Fax call
+//
+ {
+ CCallEntry* entry = NULL;
+ entry=CheckNewObject(aName); //if found in call list, must be a pre-alloc'ed call
+ if (!entry)
+ {
+ CCallMobileFax* newCall=CCallMobileFax::NewL(iIo,iInit,iPhoneGlobals,aName);
+ TCleanupItem newLineClose(CloseLine,newCall);
+ CleanupStack::PushL(newLineClose);
+ AppendNewCallL(newCall);
+ CleanupStack::Pop();
+ iPhoneGlobals->iNotificationStore->CheckNotification(this,ECallAdded);
+ return newCall;
+ }
+ else // this is a pre-allocated call
+ {
+ TName preAllocatedCallName; // pre-allocate next call
+ GenerateName(preAllocatedCallName);
+ CCallMobileFax* call=CCallMobileFax::NewL(iIo,iInit,iPhoneGlobals,preAllocatedCallName);
+ call->SetOwnedByTSY();
+ (void)User::LeaveIfError(call->SetName(&preAllocatedCallName));
+ call->SetOwner(this);
+ iPreAlloc = CCallEntry::NewL(call);
+
+ CCallHayes* oldpreAllocCall = entry->iCallHayes;
+ oldpreAllocCall->SetUnownedByTSY();
+ return oldpreAllocCall;
+ }
+ }
+
+CTelObject* CLineMobileFax::OpenNewObjectL(TDes& aNewName)
+//
+// Open a fax call
+//
+ {
+ GenerateName(aNewName);
+ CCallMobileFax* newCall=CCallMobileFax::NewL(iIo,iInit,iPhoneGlobals,aNewName);
+ TCleanupItem newLineClose(CloseLine,newCall);
+ CleanupStack::PushL(newLineClose);
+ AppendNewCallL(newCall);
+ CleanupStack::Pop();
+ iPhoneGlobals->iNotificationStore->CheckNotification(this,ECallAdded);
+ return newCall;
+ }
+
+TInt CLineMobileFax::GetCaps(const TTsyReqHandle aTsyReqHandle,RLine::TCaps* aLineCaps)
+ {
+ aLineCaps->iFlags = RLine::KCapsEventIncomingCall;
+ if (iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & KFaxCaps)
+ {
+ aLineCaps->iFlags |= RLine::KCapsFax;
+ }
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+TInt CLineMobileFax::GetCallInfo(const TTsyReqHandle aTsyReqHandle,TCallInfoIndex* aCallInfoIndex)
+//
+// Provide info about fax call
+//
+ {
+ LOGTEXT(_L8("FaxLine:\tGet Fax Call Info"));
+ CCallEntry* callEntry;
+ TDblQueIter<CCallEntry> iter(iCalls);
+ iter.SetToFirst();
+ for (TInt i=0;i<(TInt)(aCallInfoIndex->iIndex);i++)
+ {
+ iter++;
+ }
+ callEntry=iter;
+ if (callEntry)
+ {
+ callEntry->iCallHayes->GetCallInfo(aCallInfoIndex);
+ aCallInfoIndex->iInfo.iCallCapsFlags |= RCall::KCapsFax;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ }
+ else
+ ReqCompleted(aTsyReqHandle,KErrNotFound);
+ return KErrNone;
+ }
+
+CCallEntry* CCallEntry::NewL(CCallHayes* aCallHayes)
+//
+// Call Entry has a pointer to the call, and makes up an entry in the linked list iCalls
+//
+ {
+ return new(ELeave) CCallEntry(aCallHayes);
+ }
+
+CCallEntry::CCallEntry(CCallHayes* aCallHayes)
+//
+// CCallEntry constructor
+//
+ : iCallHayes(aCallHayes)
+ {}
+
+CCallEntry::~CCallEntry()
+//
+// CCallEntry destructor
+//
+ {}
+
+void CCallEntry::Deque()
+//
+// Deque CCallEntry list
+//
+ {
+ iLink.Deque();
+ iLink.iPrev=iLink.iNext=NULL;
+ }