diff -r 6b1d113cdff3 -r 6638e7f4bd8f telephonyserverplugins/multimodetsy/hayes/LINE.CPP --- a/telephonyserverplugins/multimodetsy/hayes/LINE.CPP Mon May 03 13:37:20 2010 +0300 +++ b/telephonyserverplugins/multimodetsy/hayes/LINE.CPP Thu May 06 15:10:38 2010 +0100 @@ -1,935 +1,935 @@ -// 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(); - } - } - } - - -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; - } +// 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(); + } + } + } + + +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; + }