diff -r 000000000000 -r 3553901f7fa8 telephonyserverplugins/multimodetsy/hayes/LINE.CPP --- /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 +// + +void CLineHayes::Dummy1() + { + RLine::TLineInfo dummy0; + TPckg 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(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 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 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 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 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 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 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 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 iter(iCalls); + while (callEntry=iter++, callEntry) + callEntry->iCallHayes->CallInfo()->iHookStatus = aHookStatus; + } + +TBool CLineHayes::StopMyCallRinging() + { + CCallEntry* callEntry; + TDblQueIter 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 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 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 iter(iCalls); + while (callEntry=iter++, callEntry) + { + if ((callEntry->iCallHayes->IsForIncomingCall())) + { + callEntry->iCallHayes->AnswerImmediately(); + return ETrue; + } + } + return EFalse; + } + +TBool CLineHayes::CheckForOutstandingAnswer() + { + CCallEntry* callEntry; + TDblQueIter iter(iCalls); + while (callEntry=iter++, callEntry) + { + if (callEntry->iCallHayes->IsForIncomingCall()) + return ETrue; + } + return EFalse; + } + +const CArrayFixFlat* 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 iter(iCalls); + while(callEntry=iter++, callEntry!=NULL) + { + if (callEntry->iCallHayes->GetCoreCallStatus() == iPhoneGlobals->iPhoneStatus.iLineStatus) + { + //*aStatus = static_cast(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 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 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 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; + }