--- a/telephonyserver/etelserverandcore/SETEL/ET_CORE.CPP Mon May 03 13:37:20 2010 +0300
+++ b/telephonyserver/etelserverandcore/SETEL/ET_CORE.CPP Thu May 06 15:10:38 2010 +0100
@@ -1,1347 +1,1723 @@
-// 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 "ET_SSTD.H"
-#include "ETBUFFER.H"
-#include <f32file.h>
-#include "etsvr_slots.h"
-#include "et_phone_util.h"
-//
-//
-// CFaxBase
-//
-//
-EXPORT_C CFaxBase::CFaxBase()
-//
-// C'Tor
-//
- {
- __DECLARE_NAME(_S("CFaxBase"));
- }
-
-EXPORT_C CFaxBase::~CFaxBase()
-//
-// D'Tor
-//
- {}
-
-EXPORT_C CTelObject* CFaxBase::OpenNewObjectByNameL(const TDesC&)
-//
-// Always return NULL not allow CFaxBase Tsy object to create new object
-//
- {
- User::Leave(KErrNotSupported);
- return NULL;
- }
-
-EXPORT_C CTelObject* CFaxBase::OpenNewObjectL(TDes&)
-//
-// Always return NULL not allow CFaxBase Tsy object to create new object
-//
- {
- User::Leave(KErrNotSupported);
- return NULL;
- }
-
-EXPORT_C void CFaxBase::OpenPostProcessing(CTelSession*,const TInt)
-//
-// Perform post-processing after object has been added to session's CObjectIx.
-//
- {}
-
-EXPORT_C void CFaxBase::CloseSubSessionPreProcessing(CTelSession* aSession,const TInt aSubSessionHandle)
- {
- CreateDummySession(aSession,aSubSessionHandle);
- FlushReqs(aSession,aSubSessionHandle);
- }
-
-EXPORT_C TInt CFaxBase::CancelService(const TInt aIpc,const TTsyReqHandle /*aTsyReqHandle*/)
-//
-// Cancel Service for Fax
-//
- {
- __ASSERT_ALWAYS((aIpc==EEtelFaxRead) ||
- (aIpc==EEtelFaxWrite) ||
- (aIpc==EEtelFaxWaitForEndOfPage)
- ,Fault(EEtelFaultInvalidIpcForCancel));
-
- switch (aIpc)
- {
- // this is a special case for Fax session -
- // count already increment before calling susession
- // for those reqs below - server do expect Tsy to call ReqCompleted()
- // so the count should be decrement again !
- case EEtelFaxRead:
- case EEtelFaxWrite:
- case EEtelFaxWaitForEndOfPage:
- return KErrNone;
- // There is no individual cancel associated with these requests
- default:
- return KErrGeneral;
- }
- }
-
-
-EXPORT_C TInt CFaxBase::Service(const RMessage2& /*aMessage*/,CReqEntry* aReqEntry)
-//
-// The ServiceL functionality for the fax
-//
- {
- __ASSERT_ALWAYS(aReqEntry!=NULL,Fault(EEtelFaultCallTsyServiceWithoutReqPackage));
- aReqEntry->iPlacedRequest=ETrue;
- TTsyReqHandle tsyReqHandle=aReqEntry->iTsyReqHandle;
- TDes8* des1 = BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotWrite);
-
- switch (aReqEntry->iFunction)
- {
- case EEtelFaxRead:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return Read(tsyReqHandle,des1);
- case EEtelFaxWrite:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return Write(tsyReqHandle,des1);
- case EEtelFaxWaitForEndOfPage:
- return WaitForEndOfPage(tsyReqHandle);
- case EEtelFaxTerminateFaxSession:
- return TerminateFaxSession(tsyReqHandle);
- default:
- return KErrNotSupported;
- }
- }
-
-
-EXPORT_C void CFaxBase::Init()
- {}
-
-EXPORT_C CTelObject::TReqMode CFaxBase::ReqModeL(const TInt aIpc)
-//
-// Fax Request Inquiry Functions
-//
- {
- CTelObject::TReqMode mode=0;
- switch (aIpc)
- {
- case EEtelFaxTerminateFaxSession:
- mode=KReqModeMultipleCompletionEnabled; // if two clients call this, only want the first to
- // be acted upon
- break;
- case EEtelFaxRead:
- case EEtelFaxWrite:
- case EEtelFaxWaitForEndOfPage:
- mode=KReqModeFlowControlObeyed;
- break;
- default:
- User::Leave(KErrNotSupported);
- break;
- }
- return mode;
- }
-
-EXPORT_C TInt CFaxBase::NumberOfSlotsL(const TInt /*aIpc*/)
- {
- User::Leave(KErrNotSupported); // there are no repost immediately functions for fax
- return KSlotNumbersDefault;
- }
-
-//
-//
-// CCallBase
-//
-//
-EXPORT_C CCallBase::CCallBase()
-//
-// C'Tor
-//
- :iOwnershipStatus(EOwnedUnowned)
- ,iOwnerSession(NULL)
- ,iOwnerSubSessionHandle(0)
- ,iLoanDataPort(EFalse)
- {
- __DECLARE_NAME(_S("CCallBase"));
- }
-
-EXPORT_C CCallBase::~CCallBase()
-//
-// D'Tor
-// Attual closing of the owner is done in CSubSessionBase destructor
-// This is for all object inherit fron CSubSessionBase
-//
- {
- LOGTEXT("~CCallBase");
- }
-
-EXPORT_C TInt CCallBase::CancelService(const TInt aIpc,const TTsyReqHandle aTsyReqHandle)
-//
-// Cancel Service for Call
-//
- {
- __ASSERT_ALWAYS((aIpc==EEtelCallNotifyHookChange) ||
- (aIpc==EEtelCallNotifyStatusChange) ||
- (aIpc==EEtelCallNotifyDurationChange) ||
- (aIpc==EEtelCallCapsChangeNotification) ||
- (aIpc==EEtelCallAcquireOwnership) ||
- (aIpc==EEtelCallDial) ||
- (aIpc==EEtelCallAnswer) ||
- (aIpc==EEtelCallHangUp) ||
- (aIpc==EEtelCallConnect)||
- (aIpc==EEtelCallLoanDataPort)
- ,Fault(EEtelFaultInvalidIpcForCancel));
- switch (aIpc)
- {
- case EEtelCallCapsChangeNotification:
- return NotifyCapsChangeCancel(aTsyReqHandle);
- case EEtelCallNotifyHookChange:
- return NotifyHookChangeCancel(aTsyReqHandle);
- case EEtelCallNotifyStatusChange:
- return NotifyStatusChangeCancel(aTsyReqHandle);
- case EEtelCallNotifyDurationChange:
- return NotifyDurationChangeCancel(aTsyReqHandle);
- case EEtelCallAcquireOwnership:
- return AcquireOwnershipCancel(aTsyReqHandle);
- case EEtelCallDial:
- return DialCancel(aTsyReqHandle);
- case EEtelCallConnect:
- return ConnectCancel(aTsyReqHandle);
- case EEtelCallAnswer:
- return AnswerIncomingCallCancel(aTsyReqHandle);
- case EEtelCallHangUp:
- return HangUpCancel(aTsyReqHandle);
- case EEtelCallLoanDataPort:
- return LoanDataPortCancel(aTsyReqHandle);
- default:
- return KErrGeneral; // should never reached here
- }
- }
-
-EXPORT_C void CCallBase::Init()
- {}
-
-EXPORT_C CCallBase::TCallOwnership CCallBase::CheckOwnership(const TTsyReqHandle aTsyReqHandle) const
-//
-// Tsy upcall function - return the call ownership status
-//
- {
- CReqEntry* reqEntry=PhoneOwner()->FindByTsyHandle(aTsyReqHandle);
- __ASSERT_ALWAYS(reqEntry!=NULL,Fault(EEtelFaultNotRecognisedTsyHandle));
- RCall::TOwnershipStatus owner=CheckOwnershipBySession(reqEntry->iSession,reqEntry->iMessage.Int3());
-
- if (owner==RCall::EOwnershipUnowned)
- return EOwnedUnowned;
-
- if (owner==RCall::EOwnershipOwnedByThisClient)
- return EOwnedTrue;
-
- if (owner==RCall::EOwnershipThisIsPriorityClient)
- return EOwnedPriorityClient;
-
- return EOwnedFalse;
- }
-
-EXPORT_C RCall::TOwnershipStatus CCallBase::CheckOwnershipBySession(CTelSession* aSession,const TInt /*aSubSessionHandle*/) const
-//
-// Return true if the owner
-//
- {
- if (iOwnershipStatus==EOwnedUnowned)
- return RCall::EOwnershipUnowned;
-
- if(iOwnershipStatus==EOwnedTrue && iOwnerSession==aSession /*&& iOwnerSubSessionHandle==aSubSessionHandle*/) // ownership is session based!
- return RCall::EOwnershipOwnedByThisClient;
-
-// Ann changed
- if (iOwnershipStatus==EOwnedTrue && aSession->TelServer()->IsPriorityClient(aSession))
- return RCall::EOwnershipThisIsPriorityClient;
-// end
-
- return RCall::EOwnershipOwnedByAnotherClient;
- }
-
-EXPORT_C TInt CCallBase::SetUnowned()
-//
-// Return Owner ship status
-//
- {
- iOwnershipStatus=EOwnedUnowned;
- iOwnerSession=NULL; // set to invalid value
- iOwnerSubSessionHandle=0;
-
- return KErrNone;
- }
-
-EXPORT_C TInt CCallBase::SetOwnership(const TTsyReqHandle aTsyReqHandle)
-//
-// If owner ship if not own
-//
- {
- CReqEntry* reqEntry=PhoneOwner()->FindByTsyHandle(aTsyReqHandle);
- __ASSERT_ALWAYS(reqEntry!=NULL,Fault(EEtelFaultNotRecognisedTsyHandle));
-
- iOwnershipStatus=EOwnedTrue;
- iOwnerSession=reqEntry->iSession;
- iOwnerSubSessionHandle=reqEntry->iMessage.Int3();
- return KErrNone;
- }
-
-EXPORT_C TBool CCallBase::CheckPriorityClient(const TTsyReqHandle aTsyReqHandle) const
- {
- CReqEntry* reqEntry=PhoneOwner()->FindByTsyHandle(aTsyReqHandle);
- __ASSERT_ALWAYS(reqEntry!=NULL,Fault(EEtelFaultNotRecognisedTsyHandle));
-
- return reqEntry->iSession->TelServer()->IsPriorityClient(reqEntry->iSession);
- }
-
-EXPORT_C CCallBase* CCallBase::ResolveSubSessionHandle(const TTsyReqHandle aTsyReqHandle,
- const TInt aSubSessionHandle)
-//
-// expects the subsession handle of a call, which must have been opened by the same client session
-// which opened this call and called the current request (identified by aTsyReqHandle)
-//
- {
- CReqEntry* reqEntry=PhoneOwner()->FindByTsyHandle(aTsyReqHandle);
- __ASSERT_ALWAYS(reqEntry!=NULL,Fault(EEtelFaultNotRecognisedTsyHandle));
- return REINTERPRET_CAST(CCallBase*,reqEntry->iSession->CObjectFromHandle(aSubSessionHandle));
- }
-
-EXPORT_C void CCallBase::OpenPostProcessing(CTelSession* ,const TInt)
-//
-// Perform post-processing after object has been added to session's CObjectIx.
-//
- {}
-
-EXPORT_C void CCallBase::CloseSubSessionPreProcessing(CTelSession* aSession,const TInt aSubSessionHandle)
-//
-// Perform close post-processing before object being close
-// if is owner then set to EUnOwned
-//
- {
- LOGTEXT("CCallBase::CloseSubSessionPreProcessing() - about to create dummy session");
- CreateDummySession(aSession,aSubSessionHandle);
- RCall::TOwnershipStatus owner=CheckOwnershipBySession(aSession,aSubSessionHandle);
- if (owner==RCall::EOwnershipOwnedByThisClient)
- {
- CreateDummySession(aSession,aSubSessionHandle,ETrue);
- if (iLoanDataPort) // data port being on loan by this owner
- RecoverDataPortAndRelinquishOwnership(); // inform tsy about this
- else
- RelinquishOwnership();
- }
- FlushReqs(aSession,aSubSessionHandle);
- }
-
-EXPORT_C void CCallBase::RelinquishOwnershipCompleted(const TInt aError)
-//
-// Server called Tsy with RelinquishOwnership()
-// TSY should do a Up call with this function
-//
- {
- __ASSERT_ALWAYS(aError==KErrNone,Fault(EEtelFaultCanNotRelinquishOwnership));
- CheckAndDestroyDummySubSession();
- }
-
-EXPORT_C void CCallBase::RecoverDataPortAndRelinquishOwnershipCompleted(const TInt aError)
-//
-// Server called Tsy with RecoverDataPortAndRelinquishOwnership()
-// TSY should do a Up call with this function
-//
- {
- __ASSERT_ALWAYS(aError==KErrNone,Fault(EEtelFaultCanNotRelinquishOwnership));
- iLoanDataPort=EFalse;
- RelinquishOwnershipCompleted(aError);
- }
-
-EXPORT_C TInt CCallBase::Service(const RMessage2& aMessage,CReqEntry* aReqEntry)
-//
-// The ServiceL functionality for the call
-//
- {
- __ASSERT_ALWAYS(aReqEntry!=NULL,Fault(EEtelFaultCallTsyServiceWithoutReqPackage));
- aReqEntry->iPlacedRequest=ETrue;
- TTsyReqHandle tsyReqHandle=aReqEntry->iTsyReqHandle;
- TDes8* des1 = BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotWrite);
- TUint8* ptr1=Ptr1(des1);
- switch (aReqEntry->iFunction)
- {
-
- // Asynchronous + Cancel
- case EEtelCallCapsChangeNotification:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return NotifyCapsChange(tsyReqHandle,REINTERPRET_CAST(RCall::TCaps*,ptr1));
- case EEtelCallCapsChangeNotificationCancel:
- return NotifyCapsChangeCancel(tsyReqHandle);
- case EEtelCallNotifyHookChange:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return NotifyHookChange(tsyReqHandle,REINTERPRET_CAST(RCall::THookStatus*,ptr1));
- case EEtelCallNotifyHookChangeCancel:
- return NotifyHookChangeCancel(tsyReqHandle);
-
- case EEtelCallNotifyStatusChange:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return NotifyStatusChange(tsyReqHandle,REINTERPRET_CAST(RCall::TStatus*,ptr1));
- case EEtelCallNotifyStatusChangeCancel:
- return NotifyStatusChangeCancel(tsyReqHandle);
- case EEtelCallNotifyDurationChange:
- return NotifyDurationChange(tsyReqHandle,REINTERPRET_CAST(TTimeIntervalSeconds*,ptr1));
- case EEtelCallNotifyDurationChangeCancel:
- return NotifyDurationChangeCancel(tsyReqHandle);
- case EEtelCallDial:
- {
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- TDes* des2 = NULL;
- des2 = BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotWrite);
- __ASSERT_ALWAYS(des2!=NULL,Fault(EEtelFaultDes2DoesNotExist));
- return Dial(tsyReqHandle,des1,des2);
- }
- case EEtelCallDialCancel:
- return DialCancel(tsyReqHandle);
-
- case EEtelCallConnect:
- return Connect(tsyReqHandle,des1);
- case EEtelCallConnectCancel:
- return ConnectCancel(tsyReqHandle);
-
- case EEtelCallAnswer:
- return AnswerIncomingCall(tsyReqHandle,des1);
- case EEtelCallAnswerCancel:
- return AnswerIncomingCallCancel(tsyReqHandle);
-
- case EEtelCallHangUp:
- return HangUp(tsyReqHandle);
- case EEtelCallHangUpCancel:
- return HangUpCancel(tsyReqHandle);
-
- case EEtelCallAcquireOwnership:
- {
- if (RCall::EOwnershipOwnedByThisClient==
- CheckOwnershipBySession(aReqEntry->iSession,aMessage.Int3()))
- return KErrEtelAlreadyCallOwner;
- else
- return AcquireOwnership(tsyReqHandle);
- }
- case EEtelCallAcquireOwnershipCancel:
- return AcquireOwnershipCancel(tsyReqHandle);
-
- // Synchronous
- case EEtelCallGetInfo:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return GetInfo(tsyReqHandle,REINTERPRET_CAST(RCall::TCallInfo*,ptr1));
- case EEtelCallGetStatus:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return GetStatus(tsyReqHandle,REINTERPRET_CAST(RCall::TStatus*,ptr1));
- case EEtelCallGetCaps:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return GetCaps(tsyReqHandle,REINTERPRET_CAST(RCall::TCaps*,ptr1));
- case EEtelCallLoanDataPort:
- {
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- TInt ret=LoanDataPort(tsyReqHandle,REINTERPRET_CAST(RCall::TCommPort*,ptr1));
- if (ret==KErrNone)
- iLoanDataPort=ETrue;
- return ret;
- }
- case EEtelCallLoanDataPortCancel:
- return LoanDataPortCancel(tsyReqHandle);
-
- case EEtelCallRecoverDataPort:
- {
- TInt ret=RecoverDataPort(tsyReqHandle);
- if (ret==KErrNone)
- iLoanDataPort=EFalse;
- return ret;
- }
-
- case EEtelCallTransferOwnership:
- return TransferOwnership(tsyReqHandle);
- case EEtelCallGetBearerServiceInfo:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return GetBearerServiceInfo(tsyReqHandle,REINTERPRET_CAST(RCall::TBearerService*,ptr1));
-
- case EEtelCallGetOwnershipStatus:
- {
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
-
- RCall::TOwnershipStatus* owner=REINTERPRET_CAST(RCall::TOwnershipStatus*,ptr1);
- *owner=CheckOwnershipBySession(aReqEntry->iSession,aMessage.Int3());
- ReqCompleted(tsyReqHandle,KErrNone);
- return KErrNone;
- }
-
- case EEtelCallGetCallParams:
- {
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return GetCallParams(tsyReqHandle,des1);
- }
- case EEtelCallGetCallDuration:
- {
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return GetCallDuration(tsyReqHandle,REINTERPRET_CAST(TTimeIntervalSeconds*,ptr1));
- }
- case EEtelCallGetFaxSettings:
- {
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return GetFaxSettings(tsyReqHandle,REINTERPRET_CAST(RCall::TFaxSessionSettings*,ptr1));
- }
-
- case EEtelCallSetFaxSettings:
- {
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return SetFaxSettings(tsyReqHandle,REINTERPRET_CAST(RCall::TFaxSessionSettings*,ptr1));
- }
- case EEtelCallReferenceCount:
- {
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
-
- TInt* count=REINTERPRET_CAST(TInt*,ptr1);
- *count=AccessCount();
- ReqCompleted(tsyReqHandle,KErrNone);
- return KErrNone;
- }
- case EEtelAdoptFaxSharedHeaderFile:
- {
- CFaxSharedFileHandles* fshare = NULL;
- TRAPD(err, fshare = CFaxSharedFileHandles::NewL(aMessage));
- if(err != KErrNone)
- {
- return err;
- }
- //Pass the CFaxSharedFileHandles object to the TSY. If call is successful then TSY assumes owenership of the object else we delete it.
- TInt ret = SetFaxSharedHeaderFile(tsyReqHandle, fshare);
- if(ret!= KErrNone)
- {
- delete fshare;
- }
- return ret;
- }
- default:
- return ServiceExtFunc(aMessage,aReqEntry);
- }
- }
-
-EXPORT_C RHandleBase* CCallBase::GlobalKernelObjectHandle()
- {
- if (iChunk.Handle() == KNullHandle) return NULL;
- return &iChunk;
- }
-
-
-EXPORT_C RFax::TProgress* CCallBase::CreateFaxProgressChunk()
-//
-// Even if already created, return pointer to it
-//
- {
- if (iChunk.Handle() == KNullHandle)
- {
- TInt r = iChunk.CreateGlobal(KNullDesC,sizeof (RFax::TProgress), sizeof (RFax::TProgress),EOwnerProcess);
- if (r == KErrNone)
- {
- RFax::TProgress* progress = new(iChunk.Base()) RFax::TProgress;
- progress->iLastUpdateTime = 0;
- progress->iAnswerback.Zero ();
- progress->iPhase = ENotYetStarted;
- progress->iSpeed = 9600;
- progress->iResolution = EFaxNormal;
- progress->iCompression = EModifiedHuffman;
- progress->iECM = 0;
- progress->iPage = 0;
- progress->iLines = 0;
- return progress;
- }
- if (r != KErrNone)
- return NULL;
-
- }
- return (RFax::TProgress*)iChunk.Base();
- }
-
-/**
-Base implementation for virtual API declared in MCallBaseTSY. This base implementation always returns KErrNotSupported and
-it is therefore necessary for TSYs who support this API to override this in their CCallBase derived class.
-
-This function passes through a pointer to a heap-based CFaxSharedFileHandles object. This object is instantiated by Etel but
-a successful return of this function will pass responsibility for deletion of aFaxSharedFileHandles from Etel server to the TSY.
-If an error code is returned from this function (e.g. KErrNotSupported) Etel maintains ownership of the aFaxSharedFileHandles and
-is responsible for its deletion.
-
-TSY overrides of this function must correctly handle the cleanup of the aFaxSharedFileHandles object if they take ownership of it
-which is implied when returning from this function with KErrNone.
-
-@publishedPartner
-@param aTsyReqHandle Handle to request.
-@param aFaxSharedFileHandles CFaxSharedFileHandles instance to be stored in TSY.
-@released Released v9.0 to allow a fax client to pass a file handle to the Fax server.
-*/
-EXPORT_C TInt CCallBase::SetFaxSharedHeaderFile(const TTsyReqHandle /*aTsyReqHandle*/, CFaxSharedFileHandles* /*aFaxSharedFileHandles*/)
- {
- return KErrNotSupported;
- }
-
-EXPORT_C void CCallBase::DeleteFaxProgressChunk()
- {
- iChunk.Close();
- }
-
-EXPORT_C CTelObject::TReqMode CCallBase::ReqModeL(const TInt aIpc)
-//
-// Basic Request Mode for Call
-//
- {
- CTelObject::TReqMode mode=0;
- switch (aIpc)
- {
- case EEtelCallNotifyHookChange:
- case EEtelCallNotifyStatusChange:
- case EEtelCallNotifyDurationChange:
- case EEtelCallCapsChangeNotification:
- mode=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately;
- break;
- case EEtelCallGetInfo:
- case EEtelCallRecoverDataPort:
- case EEtelCallGetStatus:
- case EEtelCallGetCaps:
- case EEtelCallTransferOwnership:
- case EEtelCallAcquireOwnership:
- case EEtelCallGetFaxSettings:
- case EEtelCallGetCallParams:
- case EEtelCallGetCallDuration:
- case EEtelCallAnswer: // no longer obeys flow control since it may be placed long before
- // a call arrives
- break;
- case EEtelCallGetOwnershipStatus:
- case EEtelCallGetBearerServiceInfo:
- case EEtelCallSetFaxSettings:
- case EEtelAdoptFaxSharedHeaderFile:
- case EEtelCallReferenceCount:
- break;
- case EEtelCallLoanDataPort:
- case EEtelCallDial:
- case EEtelCallConnect:
- case EEtelCallHangUp:
-
- mode=KReqModeFlowControlObeyed;
- break;
-
- default:
- User::Leave(KErrNotSupported);
- break;
- }
- return mode;
- }
-
-EXPORT_C TInt CCallBase::NumberOfSlotsL(const TInt aIpc)
- {
- switch (aIpc)
- {
- case EEtelCallNotifyHookChange:
- case EEtelCallNotifyDurationChange:
- break;
- case EEtelCallNotifyStatusChange:
- return KSlotNumbersCallStatusChange;
- case EEtelCallCapsChangeNotification:
- return KSlotNumbersCallCapsChange;
- default:
- User::Leave(KErrNotSupported);
- break;
- }
- return KSlotNumbersDefault;
- }
-
-//
-//
-// CLineBase
-//
-//
-EXPORT_C CLineBase::CLineBase()
-//
-// C'Tor
-//
- {
- __DECLARE_NAME(_S("CLineBase"));
- }
-
-EXPORT_C CLineBase::~CLineBase()
-//
-// D'Tor
-//
- {
- LOGTEXT("~CLineBase");
- }
-
-EXPORT_C TInt CLineBase::CancelService(const TInt aIpc,const TTsyReqHandle aTsyReqHandle)
-//
-// Cancel Service for Line
-//
- {
- __ASSERT_ALWAYS(( aIpc==EEtelLineNotifyIncomingCall ||
- aIpc==EEtelLineNotifyHookChange ||
- aIpc==EEtelLineNotifyStatusChange ||
- aIpc==EEtelLineNotifyCallAdded ||
- aIpc==EETelLineCapsChangeNotification)
- ,Fault(EEtelFaultInvalidIpcForCancel));
- switch (aIpc)
- {
- case EEtelLineNotifyIncomingCall:
- return NotifyIncomingCallCancel(aTsyReqHandle);
- case EEtelLineNotifyHookChange:
- return NotifyHookChangeCancel(aTsyReqHandle);
- case EEtelLineNotifyStatusChange:
- return NotifyStatusChangeCancel(aTsyReqHandle);
- case EEtelLineNotifyCallAdded:
- return NotifyCallAddedCancel(aTsyReqHandle);
- case EETelLineCapsChangeNotification:
- return NotifyCapsChangeCancel(aTsyReqHandle);
- default:
- return KErrGeneral; // should never reaches here
- }
- }
-
-EXPORT_C TInt CLineBase::Service(const RMessage2& aMessage, CReqEntry* aReqEntry)
-//
-// The ServiceL Functionality for the Line
-//
- {
- __ASSERT_ALWAYS(aReqEntry!=NULL,Fault(EEtelFaultCallTsyServiceWithoutReqPackage));
- aReqEntry->iPlacedRequest=ETrue;
- TTsyReqHandle tsyReqHandle=aReqEntry->iTsyReqHandle;
- TDes8* des1 = BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotWrite);
- TUint8* ptr1=Ptr1(des1);
-
- switch (aReqEntry->iFunction)
- {
- case EETelLineCapsChangeNotification:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return NotifyCapsChange(tsyReqHandle,REINTERPRET_CAST(RLine::TCaps*,ptr1));
- case EETelLineCapsChangeNotificationCancel:
- return NotifyCapsChangeCancel(tsyReqHandle);
- case EEtelLineNotifyIncomingCall:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return NotifyIncomingCall(tsyReqHandle,REINTERPRET_CAST(TName*,ptr1));
- case EEtelLineNotifyIncomingCallCancel:
- return NotifyIncomingCallCancel(tsyReqHandle);
-
- case EEtelLineNotifyHookChange:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return NotifyHookChange(tsyReqHandle,REINTERPRET_CAST(RCall::THookStatus*,ptr1));
- case EEtelLineNotifyHookChangeCancel:
- return NotifyHookChangeCancel(tsyReqHandle);
- case EEtelLineNotifyStatusChange:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return NotifyStatusChange(tsyReqHandle,REINTERPRET_CAST(RCall::TStatus*,ptr1));
- case EEtelLineNotifyStatusChangeCancel:
- return NotifyStatusChangeCancel(tsyReqHandle);
- case EEtelLineNotifyCallAdded:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return NotifyCallAdded(tsyReqHandle,REINTERPRET_CAST(TName*,ptr1));
- case EEtelLineNotifyCallAddedCancel:
- return NotifyCallAddedCancel(tsyReqHandle);
-
- case EEtelLineGetHookStatus:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return GetHookStatus(tsyReqHandle,REINTERPRET_CAST(RCall::THookStatus*,ptr1));
-
- case EEtelLineGetInfo:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return GetInfo(tsyReqHandle,REINTERPRET_CAST(RLine::TLineInfo*,ptr1));
- case EEtelLineGetCaps:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return GetCaps(tsyReqHandle,REINTERPRET_CAST(RLine::TCaps*,ptr1));
- case EEtelLineGetStatus:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return GetStatus(tsyReqHandle,REINTERPRET_CAST(RCall::TStatus*,ptr1));
- case EEtelLineEnumerateCall:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return EnumerateCall(tsyReqHandle,REINTERPRET_CAST(TInt*,ptr1));
- case EEtelLineGetCallInfo:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return GetCallInfo(tsyReqHandle,REINTERPRET_CAST(TCallInfoIndex*,ptr1));
- default:
- return ServiceExtFunc(aMessage,aReqEntry);
- }
- }
-
-EXPORT_C void CLineBase::Init()
-//
-// not used for Line
-//
- {}
-
-EXPORT_C void CLineBase::OpenPostProcessing(CTelSession*,const TInt)
-//
-// Perform post-processing after object has been added to session's CObjectIx.
-//
- {}
-
-EXPORT_C void CLineBase::CloseSubSessionPreProcessing(CTelSession* aSession,const TInt aSubSessionHandle)
-//
-//
-//
- {
- LOGTEXT("CLineBase::CloseSubSessionPreProcessing() - about to create dummy session");
- CreateDummySession(aSession,aSubSessionHandle);
- FlushReqs(aSession,aSubSessionHandle);
- }
-
-EXPORT_C CTelObject::TReqMode CLineBase::ReqModeL(const TInt aIpc)
-//
-// Mode Request Inquiry Functions
-//
- {
- CTelObject::TReqMode mode=0;
- switch (aIpc)
- {
- case EEtelLineGetCaps:
- case EEtelLineGetStatus:
- case EEtelLineGetHookStatus:
- case EEtelLineEnumerateCall:
- case EEtelLineGetCallInfo:
- case EEtelLineGetInfo:
- case EEtelLineNotifyIncomingCall: // 3/12/98 Removed Repost ability.
- mode=KReqModeMultipleCompletionEnabled;
- break;
- case EEtelLineNotifyHookChange:
- case EEtelLineNotifyStatusChange:
- case EEtelLineNotifyCallAdded:
- case EETelLineCapsChangeNotification:
- mode=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately;
- break;
- default:
- User::Leave(KErrNotSupported);
- break;
- }
- return mode;
- }
-
-EXPORT_C TInt CLineBase::NumberOfSlotsL(const TInt aIpc)
- {
- switch (aIpc)
- {
- case EEtelLineNotifyHookChange:
- case EETelLineCapsChangeNotification:
- break;
- case EEtelLineNotifyStatusChange:
- return KSlotNumbersLineStatusChange;
- case EEtelLineNotifyCallAdded:
- return KSlotNumbersLineCallAddedChange;
- default:
- User::Leave(KErrNotSupported);
- break;
- }
- return KSlotNumbersDefault;
- }
-
-//
-//
-// CPhoneBase
-//
-//
-EXPORT_C CPhoneBase::CPhoneBase()
-//
-// CPhoneBase constructor
-//
- {
- __DECLARE_NAME(_S("CPhoneBase"));
- iReqWaitList.SetOffset(_FOFF(CReqEntry,iLink));
- iReqActiveList.SetOffset(_FOFF(CReqEntry,iLink));
- iTsyReqHandleCnt=TSY_HANDLE_INIT_VALUE;
- }
-
-EXPORT_C CPhoneBase::~CPhoneBase()
-//
-// CPhone destructor.
-// Attual closing of the owner is done in CSubSessionBase destructor
-// This is for all object inherit fron CSubSesissionBase
-//
- {
- LOGTEXT("~CPhoneBase");
- }
-
-//
-// Request List Manipulation Functions
-//
-CReqEntry* CPhoneBase::ActivateNextWaitingReq()
-//
-// Use: during completion to Activate the next waiting request
-// Action: Find next Waiting Req, move to active, and return.
-//
- {
- if(iReqWaitList.IsEmpty())
- return NULL;
-
- CReqEntry* reqEntry=iReqWaitList.First();
- if(reqEntry==NULL)
- return NULL;
- reqEntry->iLink.Deque();
- iReqActiveList.AddLast(*reqEntry);
- if (reqEntry->iReqMode & KReqModeMultipleCompletionEnabled)
- {
- CReqEntry* otherClientsEntry;
- TDblQueIter<CReqEntry> iter(iReqWaitList);
- while(otherClientsEntry=iter++, otherClientsEntry!=NULL)
- {
- if(otherClientsEntry->iTsyReqHandle==reqEntry->iTsyReqHandle)
- {
- otherClientsEntry->iLink.Deque();
- iReqActiveList.AddLast(*otherClientsEntry);
- }
- }
- }
- return reqEntry;
- }
-
-CReqEntry* CPhoneBase::FindByTsyHandleAndPlacedRequest(const TTsyReqHandle aTsyReqHandle)
-//
-// Use: to search active req list for a single req, remove and then return it. Can be called repeatedly for Notification
-//
- {
- CReqEntry* reqEntry;
- TDblQueIter<CReqEntry> iter(iReqActiveList);
- while(reqEntry=iter++, reqEntry!=NULL)
- {
- if(reqEntry->iTsyReqHandle==aTsyReqHandle && reqEntry->iPlacedRequest)
- return reqEntry;
- }
- return NULL;
- }
-
-CReqEntry* CPhoneBase::FindByTsyHandle(const TTsyReqHandle aTsyReqHandle)
-//
-// Use: to search active req list for a single req, remove and then return it. Can be called repeatedly for Notification
-//
- {
- CReqEntry* reqEntry;
- TDblQueIter<CReqEntry> iter(iReqActiveList);
- while(reqEntry=iter++, reqEntry!=NULL)
- {
- if(reqEntry->iTsyReqHandle==aTsyReqHandle)
- return reqEntry;
- }
- return NULL;
- }
-
-void CPhoneBase::UpdateBuffer(CReqEntry* aUpdatedReqEntry,CReqEntry* aReqEntry)
-//
-// Is passed both the TSY-updated request entry (which may be multi-buffered or not)
-// and another request entry which is to have the data copied into it (which again may or may
-// not be multi-buffered) copies the latest data into the target request entry.
-//
- {
- __ASSERT_ALWAYS(aUpdatedReqEntry->iFunction==aReqEntry->iFunction,Fault(EEtelFaultUpdatingBufferOfDifferentIpc));
- TInt msgType = aReqEntry->iMessage.Int1();
- if (msgType==EIsaNarrowAndUnicodeDoubleDesTobeRead)
- {
- TDes8* targetDes1 = BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotWrite);
- TDes16* targetDes2 = BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotWrite);
- TDes8* sourceDes1 = BufferDes1(aUpdatedReqEntry->iBuffer,CBuffer::ESlotWrite);
- TDes16* sourceDes2 = BufferDes2u(aUpdatedReqEntry->iBuffer,CBuffer::ESlotWrite);
- if (sourceDes1!=targetDes1)
- {
- targetDes1->Copy(*sourceDes1);
- if (targetDes2)
- targetDes2->Copy(*sourceDes2);
- aReqEntry->iBuffer->IncWrite();
- }
- return;
- }
- if (aUpdatedReqEntry->iSession->IsUnicodeReq(msgType))
- {
- TDes16* targetDes1 = BufferDes1u(aReqEntry->iBuffer,CBuffer::ESlotWrite);
- TDes16* targetDes2 = BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotWrite);
- TDes16* sourceDes1 = BufferDes1u(aUpdatedReqEntry->iBuffer,CBuffer::ESlotWrite);
- TDes16* sourceDes2 = BufferDes2u(aUpdatedReqEntry->iBuffer,CBuffer::ESlotWrite);
- if (sourceDes1!=targetDes1)
- {
- targetDes1->Copy(*sourceDes1);
- if (targetDes2)
- targetDes2->Copy(*sourceDes2);
- aReqEntry->iBuffer->IncWrite();
- }
- }
- else // this is narrow
- {
- TDes8* targetDes1 = BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotWrite);
- TDes8* targetDes2 = BufferDes2(aReqEntry->iBuffer,CBuffer::ESlotWrite);
- TDes8* sourceDes1 = BufferDes1(aUpdatedReqEntry->iBuffer,CBuffer::ESlotWrite);
- TDes8* sourceDes2 = BufferDes2(aUpdatedReqEntry->iBuffer,CBuffer::ESlotWrite);
- if (sourceDes1!=targetDes1)
- {
- targetDes1->Copy(*sourceDes1);
- if (targetDes2)
- targetDes2->Copy(*sourceDes2);
- aReqEntry->iBuffer->IncWrite();
- }
- }
- }
-
-CReqEntry* CPhoneBase::FindClientInWaiting(CTelSession* aSession,const TInt aSubSessionHandle,const TInt aIpc)
-//
-// Used to search waiting list for a req that's to be cancelled.
-// If non-Null is returned it will have been removed by this function and can be completed by the caller.
-//
- {
- CReqEntry* reqEntry;
- TDblQueIter<CReqEntry> iter(iReqWaitList);
- while(reqEntry = iter++, reqEntry!=NULL)
- {
- if((reqEntry->iSession==aSession)&&(reqEntry->iMessage.Int3()==aSubSessionHandle)&&(reqEntry->iFunction==aIpc))
- return reqEntry;
- }
- return NULL;
- }
-
-CReqEntry* CPhoneBase::FindClientInActive(CTelSession* aSession,const TInt aSubSessionHandle,const TInt aIpc)
-//
-// Used to search the active req list for a req that's to be cancelled.
-// The function will return any req entry found, by the caller does not know to pass the cancel down until a search has been done just on the aIpc
-//
- {
- CReqEntry* reqEntry;
- TDblQueIter<CReqEntry> iter(iReqActiveList);
- while(reqEntry = iter++, reqEntry!=NULL)
- {
- if((reqEntry->iSession==aSession)&&(reqEntry->iMessage.Int3()==aSubSessionHandle)&&(reqEntry->iFunction==aIpc))
- return reqEntry;
- }
- return NULL;
- }
-
-CReqEntry* CPhoneBase::FindByIpcAndTelObject(const TInt aIpc, const CTelObject* aTelObject, const TUint aBufSize)
-//
-// Finds an active request by both IPC and by the TelObject it was placed on
-//
- {
- CReqEntry* reqEntry;
- TDblQueIter<CReqEntry> iter(iReqActiveList);
- while(reqEntry = iter++, reqEntry!=NULL)
- {
- if(reqEntry->iFunction==aIpc && reqEntry->iTelObject==aTelObject
- && reqEntry->iBuffer->Size() == aBufSize)
- return reqEntry;
- }
- return NULL;
- }
-
-CReqEntry* CPhoneBase::FindByIpcAndTelObjectInWaiting(const TInt aIpc, const CTelObject* aTelObject, const TUint aBufSize)
-//
-// Finds a waiting request by both IPC and by the TelObject it was placed on
-//
- {
- CReqEntry* reqEntry;
- TDblQueIter<CReqEntry> iter(iReqWaitList);
- while(reqEntry = iter++, reqEntry!=NULL)
- {
- if(reqEntry->iFunction==aIpc && reqEntry->iTelObject==aTelObject
- && reqEntry->iBuffer->Size() == aBufSize)
- return reqEntry;
- }
- return NULL;
- }
-
-void CPhoneBase::AddReqToActive(CReqEntry* aReqEntry)
-//
-// Add reqEntry to the 'active list'
-//
- {
- LOGTEXT2("CPhoneBase::AddReqToActive with TsyHandle of %d", aReqEntry->iTsyReqHandle);
- iReqActiveList.AddLast(*aReqEntry);
- }
-
-void CPhoneBase::AddReqToWaiting(CReqEntry* aReqEntry)
-//
-// Add entry to the 'wait list'
-//
- {
- LOGTEXT2("CPhoneBase::AddReqToWaiting with TsyHandle of %d", aReqEntry->iTsyReqHandle);
- iReqWaitList.AddLast(*aReqEntry);
- }
-
-TTsyReqHandle CPhoneBase::TsyReqHandle()
-//
-// Return the request handle if wrap round avoid assigned to TSY_HANDLE_INIT_VALUE
-//
- {
- iTsyReqHandleCnt++ ;
- if (iTsyReqHandleCnt==TSY_HANDLE_INIT_VALUE)
- iTsyReqHandleCnt=(TSY_HANDLE_INIT_VALUE+1);
- return iTsyReqHandleCnt;
- }
-
-CReqEntry* CPhoneBase::NewReqL(const RMessage2& aMessage, CTelSession* aSession,CBuffer* aBuffer,
- const CTelObject* aTelObject,TInt aFunction)
-//
-// Create new req entry
-//
- {
- return CReqEntry::NewL(TsyReqHandle(),aMessage,aSession,aBuffer,aTelObject,aFunction,aSession->EmergencyClientHeap(aMessage.Int1()));
- }
-
-CReqEntry* CPhoneBase::FindSameClientEntry(CTelSession* aSession,const TInt aSubSessionHandle,const TInt aIpc)
-//
-// Seaching for duplicate request and panic client is return not NULL
-//
- {
- CReqEntry* reqEntry=FindClientInWaiting(aSession,aSubSessionHandle,aIpc);
-
- if (reqEntry!=NULL)
- return reqEntry;
- else // not found in waiting
- reqEntry=FindClientInActive(aSession,aSubSessionHandle,aIpc);
- return reqEntry;
-
- }
-
-EXPORT_C void CPhoneBase::OpenPostProcessing(CTelSession*,const TInt)
-//
-// Perform post-processing after object has been added to session's CObjectIx.
-//
- {}
-
-EXPORT_C void CPhoneBase::CloseSubSessionPreProcessing(CTelSession* aSession,const TInt aSubSessionHandle)
-//
-// Find if any active request if so create a dummy session
-//
- {
- LOGTEXT("CPhoneBase::CloseSubSessionPreProcessing");
- CreateDummySession(aSession,aSubSessionHandle);
- FlushReqs(aSession,aSubSessionHandle);
- }
-
-EXPORT_C TInt CPhoneBase::Service(const RMessage2& aMessage, CReqEntry* aReqEntry)
-//
-// The ServiceL functionality for the phone
-//
- {
- __ASSERT_ALWAYS(aReqEntry!=NULL,Fault(EEtelFaultCallTsyServiceWithoutReqPackage));
- aReqEntry->iPlacedRequest=ETrue;
- TTsyReqHandle tsyReqHandle=aReqEntry->iTsyReqHandle;
- TDes8* des1 = BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotWrite);
- TUint8* ptr1=Ptr1(des1);
- switch (aReqEntry->iFunction)
- {
- case EETelPhoneCapsChangeNotification:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return NotifyCapsChange(tsyReqHandle,REINTERPRET_CAST(RPhone::TCaps*,ptr1));
- case EETelPhoneCapsChangeNotificationCancel:
- return NotifyCapsChangeCancel(tsyReqHandle);
- case EEtelPhoneInitialise:
- return ControlledInitialisation(tsyReqHandle);
- case EEtelPhoneInitialiseCancel:
- return ControlledInitialisationCancel(tsyReqHandle);
- case EEtelPhoneNotifyModemDetected:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return NotifyModemDetected(tsyReqHandle,REINTERPRET_CAST(RPhone::TModemDetection*,ptr1) );
- case EEtelPhoneNotifyModemDetectedCancel:
- return NotifyModemDetectedCancel(tsyReqHandle);
- case EEtelPhoneGetInfo:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return GetInfo(tsyReqHandle,REINTERPRET_CAST(RPhone::TPhoneInfo*,ptr1));
- case EEtelPhoneGetCaps:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return GetCaps(tsyReqHandle,REINTERPRET_CAST(RPhone::TCaps*,ptr1));
- case EEtelPhoneGetStatus:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return GetStatus(tsyReqHandle,REINTERPRET_CAST(RPhone::TStatus*,ptr1));
- case EEtelPhoneEnumerateLines:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return EnumerateLines(tsyReqHandle,REINTERPRET_CAST(TInt*,ptr1));
- case EEtelPhoneGetLineInfo:
- __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- return GetLineInfo(tsyReqHandle,REINTERPRET_CAST(TLineInfoIndex*,ptr1));
- default:
- return ServiceExtFunc(aMessage,aReqEntry);
- }
- }
-
-EXPORT_C TInt CPhoneBase::CancelService(const TInt aIpc,const TTsyReqHandle aTsyReqHandle)
-//
-// Cancel Outstanding service for the phone
-//
- {
- switch (aIpc)
- {
- case EEtelPhoneNotifyModemDetected:
- return NotifyModemDetectedCancel(aTsyReqHandle);
- case EETelPhoneCapsChangeNotification:
- return NotifyCapsChangeCancel(aTsyReqHandle);
- case EEtelPhoneInitialise:
- return ControlledInitialisationCancel(aTsyReqHandle);
- default:
- return KErrGeneral;
- }
- }
-
-CReqEntry* CPhoneBase::FindClientReqInWaitList(CTelSession* aSession,const TInt aSubSessionHandle)
-//
-// Find first entry already logged by this client - in wait list
-//
- {
- CReqEntry* reqEntry;
- TDblQueIter<CReqEntry> iter(iReqWaitList);
- while(reqEntry = iter++, reqEntry!=NULL)
- {
- if(aSession==reqEntry->iSession && aSubSessionHandle==reqEntry->iMessage.Int3())
- return reqEntry;
- }
- return NULL;
- }
-
-CReqEntry* CPhoneBase::FindThisReqByAnotherClient(CTelSession* aSession,const TInt aSubSessionHandle,const TInt aIpc,const TUint aBufSize,const CTelObject* aThisTelObject)
-//
-// Find this IPC in active list, placed by a different client
-//
- {
- CReqEntry* reqEntry;
- TDblQueIter<CReqEntry> iter(iReqActiveList);
- while(reqEntry=iter++,reqEntry!=NULL)
- {
- if((aSession!=reqEntry->iSession || aSubSessionHandle!=reqEntry->iMessage.Int3())
- && reqEntry->iFunction==aIpc && reqEntry->iTelObject==aThisTelObject
- && reqEntry->iBuffer->Size()==aBufSize)
- {
- return reqEntry;
- }
- }
- return NULL;
- }
-
-CReqEntry* CPhoneBase::FindNonCancelledClientReq(CTelSession* aSession,const TInt aSubSessionHandle,const TInt aIpc)
-//
-// Find this IPC in active list, placed by this client but not the one which placed request on TSY
-//
- {
- CReqEntry* reqEntry;
- TDblQueIter<CReqEntry> iter(iReqActiveList);
- while(reqEntry=iter++,reqEntry!=NULL)
- {
- if(aSession==reqEntry->iSession && aSubSessionHandle==reqEntry->iMessage.Int3() && reqEntry->iFunction==aIpc && reqEntry->iCancelFnCalled==EFalse)
- {
- return reqEntry;
- }
- }
- return NULL;
- }
-
-void CPhoneBase::CheckAndCompleteAllActive(CReqEntry* aUpdatedReqEntry,const TReqMode aReqMode,const TInt aIpc,const TInt aError)
-//
-// Cycles through active list, checking for any requests with the same IPC value and if
-// registered, copying the data from the buffer that the TSY filled in to this buffer. All those
-// with the same IPC are completed up to the client (if the client is ready).
-//
- {
- CReqEntry* reqEntry;
- TDblQueIter<CReqEntry> iter(iReqActiveList);
- while(reqEntry = iter++, reqEntry!=NULL)
- {
- if(reqEntry->iFunction==aIpc && reqEntry!=aUpdatedReqEntry
- && reqEntry->iTelObject==aUpdatedReqEntry->iTelObject
- && reqEntry->iBuffer->Size()==aUpdatedReqEntry->iBuffer->Size())
- {
- UpdateBuffer(aUpdatedReqEntry,reqEntry);
- TInt error = ResolveError(reqEntry->iSession,aError); // set error as either low or high byte
- if (aReqMode & KReqModeRePostImmediately)
- UpdateAndCompleteIfNecessary(reqEntry,error);
- else
- WriteBackAndCompleteReq(reqEntry,error);
- }
- }
- }
-//
-// CPhoneBase performs Flow Control
-//
-TInt CPhoneBase::FlowControl() const
-//
-// Return the value of iFlowControlCnt
-//
- {
- return iFlowControlCnt;
- }
-
-void CPhoneBase::FlowControlInc()
-//
-// Increase iFlowControlCnt
-//
- {
- LOGTEXT3("Incrementing Flow Control from %d to %d", iFlowControlCnt, iFlowControlCnt+1);
- iFlowControlCnt++;
- }
-
-void CPhoneBase::FlowControlDec()
-//
-// Decrease iFlowControlCnt
-//
- {
- __ASSERT_ALWAYS((iFlowControlCnt>0),Fault(EEtelFaultNegativeFlowcontrolCount));
- LOGTEXT3("Decrementing Flow Control from %d to %d", iFlowControlCnt, iFlowControlCnt-1);
- iFlowControlCnt--;
- }
-
-EXPORT_C TBool CPhoneBase::CheckEmergencyClient(const TTsyReqHandle aTsyReqHandle) const
- {
- CReqEntry* reqEntry=PhoneOwner()->FindByTsyHandle(aTsyReqHandle);
- __ASSERT_ALWAYS(reqEntry!=NULL,Fault(EEtelFaultNotRecognisedTsyHandle));
-
- return reqEntry->iSession->TelServer()->IsEmergencyClient(reqEntry->iSession);
- }
-
-
-EXPORT_C CTelObject::TReqMode CPhoneBase::ReqModeL(const TInt aIpc)
-//
-// Mode Request Inquiry Functions
-//
- {
- CTelObject::TReqMode mode=0;
- switch (aIpc)
- {
- case EEtelPhoneInitialise: //test
- mode=KReqModeFlowControlObeyed | KReqModeMultipleCompletionEnabled;
- break;
- case EEtelPhoneGetCaps:
- case EEtelPhoneGetStatus:
- case EEtelPhoneEnumerateLines:
- case EEtelPhoneGetLineInfo:
- case EEtelPhoneGetInfo:
- mode=KReqModeMultipleCompletionEnabled;
- break;
- case EETelPhoneSetEmergencyClient:
- mode=KReqModeFlowControlObeyed;
- break;
- case EEtelPhoneNotifyModemDetected:
- case EETelPhoneCapsChangeNotification:
- mode=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately;
- break;
- default:
- User::Leave(KErrNotSupported);
- break;
- }
- return mode;
- }
-
-EXPORT_C TInt CPhoneBase::NumberOfSlotsL(const TInt aIpc)
- {
- switch (aIpc)
- {
- case EEtelPhoneNotifyModemDetected:
- case EETelPhoneCapsChangeNotification:
- break;
- default:
- User::Leave(KErrNotSupported);
- break;
- }
- return KSlotNumbersDefault;
- }
-
-TDblQue<CReqEntry>& CPhoneBase::ReqActiveList()
- {
- return iReqActiveList;
- }
-
-
+// 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 "ET_SSTD.H"
+#include "ETBUFFER.H"
+#include <f32file.h>
+#include "etsvr_slots.h"
+#include "et_phone_util.h"
+#include "et_patchdata.h"
+//
+//
+// CFaxBase
+//
+//
+EXPORT_C CFaxBase::CFaxBase()
+//
+// C'Tor
+//
+ {
+ __DECLARE_NAME(_S("CFaxBase"));
+ }
+
+EXPORT_C CFaxBase::~CFaxBase()
+//
+// D'Tor
+//
+ {}
+
+EXPORT_C CTelObject* CFaxBase::OpenNewObjectByNameL(const TDesC&)
+//
+// Always return NULL not allow CFaxBase Tsy object to create new object
+//
+ {
+ User::Leave(KErrNotSupported);
+ return NULL;
+ }
+
+EXPORT_C CTelObject* CFaxBase::OpenNewObjectL(TDes&)
+//
+// Always return NULL not allow CFaxBase Tsy object to create new object
+//
+ {
+ User::Leave(KErrNotSupported);
+ return NULL;
+ }
+
+EXPORT_C void CFaxBase::OpenPostProcessing(CTelSession*,const TInt)
+//
+// Perform post-processing after object has been added to session's CObjectIx.
+//
+ {}
+
+EXPORT_C void CFaxBase::CloseSubSessionPreProcessing(CTelSession* aSession,const TInt aSubSessionHandle)
+ {
+ CreateDummySession(aSession,aSubSessionHandle);
+ FlushReqs(aSession,aSubSessionHandle);
+ }
+
+EXPORT_C TInt CFaxBase::CancelService(const TInt aIpc,const TTsyReqHandle /*aTsyReqHandle*/)
+//
+// Cancel Service for Fax
+//
+ {
+ __ASSERT_ALWAYS((aIpc==EEtelFaxRead) ||
+ (aIpc==EEtelFaxWrite) ||
+ (aIpc==EEtelFaxWaitForEndOfPage)
+ ,Fault(EEtelFaultInvalidIpcForCancel));
+
+ switch (aIpc)
+ {
+ // this is a special case for Fax session -
+ // count already increment before calling susession
+ // for those reqs below - server do expect Tsy to call ReqCompleted()
+ // so the count should be decrement again !
+ case EEtelFaxRead:
+ case EEtelFaxWrite:
+ case EEtelFaxWaitForEndOfPage:
+ return KErrNone;
+ // There is no individual cancel associated with these requests
+ default:
+ return KErrGeneral;
+ }
+ }
+
+
+EXPORT_C TInt CFaxBase::Service(const RMessage2& /*aMessage*/,CReqEntry* aReqEntry)
+//
+// The ServiceL functionality for the fax
+//
+ {
+ __ASSERT_ALWAYS(aReqEntry!=NULL,Fault(EEtelFaultCallTsyServiceWithoutReqPackage));
+ aReqEntry->iPlacedRequest=ETrue;
+ TTsyReqHandle tsyReqHandle=aReqEntry->iTsyReqHandle;
+ TDes8* des1 = BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotWrite);
+
+ switch (aReqEntry->iFunction)
+ {
+ case EEtelFaxRead:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return Read(tsyReqHandle,des1);
+ case EEtelFaxWrite:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return Write(tsyReqHandle,des1);
+ case EEtelFaxWaitForEndOfPage:
+ return WaitForEndOfPage(tsyReqHandle);
+ case EEtelFaxTerminateFaxSession:
+ return TerminateFaxSession(tsyReqHandle);
+ default:
+ return KErrNotSupported;
+ }
+ }
+
+
+EXPORT_C void CFaxBase::Init()
+ {}
+
+EXPORT_C CTelObject::TReqMode CFaxBase::ReqModeL(const TInt aIpc)
+//
+// Fax Request Inquiry Functions
+//
+ {
+ CTelObject::TReqMode mode=0;
+ switch (aIpc)
+ {
+ case EEtelFaxTerminateFaxSession:
+ // if two clients call this, only want the first to be acted upon
+ mode=KReqModeMultipleCompletionEnabled;
+ break;
+ case EEtelFaxRead:
+ case EEtelFaxWrite:
+ case EEtelFaxWaitForEndOfPage:
+ mode=KReqModeFlowControlObeyed;
+ break;
+ default:
+ User::Leave(KErrNotSupported);
+ break;
+ }
+ return mode;
+ }
+
+EXPORT_C TInt CFaxBase::NumberOfSlotsL(const TInt /*aIpc*/)
+ {
+ User::Leave(KErrNotSupported); // there are no repost immediately functions for fax
+ return KSlotNumbersDefault;
+ }
+
+//
+//
+// CCallBase
+//
+//
+EXPORT_C CCallBase::CCallBase()
+//
+// C'Tor
+//
+ :iOwnershipStatus(EOwnedUnowned)
+ ,iOwnerSession(NULL)
+ ,iOwnerSubSessionHandle(0)
+ ,iLoanDataPort(EFalse)
+ {
+ __DECLARE_NAME(_S("CCallBase"));
+ }
+
+EXPORT_C CCallBase::~CCallBase()
+//
+// D'Tor
+// Attual closing of the owner is done in CSubSessionBase destructor
+// This is for all object inherit fron CSubSessionBase
+//
+ {
+ LOGTEXT("~CCallBase");
+ }
+
+EXPORT_C TInt CCallBase::CancelService(const TInt aIpc,const TTsyReqHandle aTsyReqHandle)
+//
+// Cancel Service for Call
+//
+ {
+ __ASSERT_ALWAYS((aIpc==EEtelCallNotifyHookChange) ||
+ (aIpc==EEtelCallNotifyStatusChange) ||
+ (aIpc==EEtelCallNotifyDurationChange) ||
+ (aIpc==EEtelCallCapsChangeNotification) ||
+ (aIpc==EEtelCallAcquireOwnership) ||
+ (aIpc==EEtelCallDial) ||
+ (aIpc==EEtelCallAnswer) ||
+ (aIpc==EEtelCallHangUp) ||
+ (aIpc==EEtelCallConnect)||
+ (aIpc==EEtelCallLoanDataPort)
+ ,Fault(EEtelFaultInvalidIpcForCancel));
+ switch (aIpc)
+ {
+ case EEtelCallCapsChangeNotification:
+ return NotifyCapsChangeCancel(aTsyReqHandle);
+ case EEtelCallNotifyHookChange:
+ return NotifyHookChangeCancel(aTsyReqHandle);
+ case EEtelCallNotifyStatusChange:
+ return NotifyStatusChangeCancel(aTsyReqHandle);
+ case EEtelCallNotifyDurationChange:
+ return NotifyDurationChangeCancel(aTsyReqHandle);
+ case EEtelCallAcquireOwnership:
+ return AcquireOwnershipCancel(aTsyReqHandle);
+ case EEtelCallDial:
+ return DialCancel(aTsyReqHandle);
+ case EEtelCallConnect:
+ return ConnectCancel(aTsyReqHandle);
+ case EEtelCallAnswer:
+ return AnswerIncomingCallCancel(aTsyReqHandle);
+ case EEtelCallHangUp:
+ return HangUpCancel(aTsyReqHandle);
+ case EEtelCallLoanDataPort:
+ return LoanDataPortCancel(aTsyReqHandle);
+ default:
+ return KErrGeneral; // should never reached here
+ }
+ }
+
+EXPORT_C void CCallBase::Init()
+ {}
+
+EXPORT_C CCallBase::TCallOwnership CCallBase::CheckOwnership(const TTsyReqHandle aTsyReqHandle) const
+//
+// Tsy upcall function - return the call ownership status
+//
+ {
+ CReqEntry* reqEntry=PhoneOwner()->FindByTsyHandle(aTsyReqHandle);
+ __ASSERT_ALWAYS(reqEntry!=NULL,Fault(EEtelFaultNotRecognisedTsyHandle));
+ RCall::TOwnershipStatus owner=CheckOwnershipBySession(reqEntry->iSession,reqEntry->iMessage.Int3());
+
+ if (owner==RCall::EOwnershipUnowned)
+ return EOwnedUnowned;
+
+ if (owner==RCall::EOwnershipOwnedByThisClient)
+ return EOwnedTrue;
+
+ if (owner==RCall::EOwnershipThisIsPriorityClient)
+ return EOwnedPriorityClient;
+
+ return EOwnedFalse;
+ }
+
+EXPORT_C RCall::TOwnershipStatus CCallBase::CheckOwnershipBySession(CTelSession* aSession,const TInt /*aSubSessionHandle*/) const
+//
+// Return true if the owner
+//
+ {
+ if (iOwnershipStatus==EOwnedUnowned)
+ return RCall::EOwnershipUnowned;
+
+ if(iOwnershipStatus==EOwnedTrue && iOwnerSession==aSession /*&& iOwnerSubSessionHandle==aSubSessionHandle*/) // ownership is session based!
+ return RCall::EOwnershipOwnedByThisClient;
+
+// Ann changed
+ if (iOwnershipStatus==EOwnedTrue && aSession->TelServer()->IsPriorityClient(aSession))
+ return RCall::EOwnershipThisIsPriorityClient;
+// end
+
+ return RCall::EOwnershipOwnedByAnotherClient;
+ }
+
+EXPORT_C TInt CCallBase::SetUnowned()
+//
+// Return Owner ship status
+//
+ {
+ iOwnershipStatus=EOwnedUnowned;
+ iOwnerSession=NULL; // set to invalid value
+ iOwnerSubSessionHandle=0;
+
+ return KErrNone;
+ }
+
+EXPORT_C TInt CCallBase::SetOwnership(const TTsyReqHandle aTsyReqHandle)
+//
+// If owner ship if not own
+//
+ {
+ CReqEntry* reqEntry=PhoneOwner()->FindByTsyHandle(aTsyReqHandle);
+ __ASSERT_ALWAYS(reqEntry!=NULL,Fault(EEtelFaultNotRecognisedTsyHandle));
+
+ iOwnershipStatus=EOwnedTrue;
+ iOwnerSession=reqEntry->iSession;
+ iOwnerSubSessionHandle=reqEntry->iMessage.Int3();
+ return KErrNone;
+ }
+
+EXPORT_C TBool CCallBase::CheckPriorityClient(const TTsyReqHandle aTsyReqHandle) const
+ {
+ CReqEntry* reqEntry=PhoneOwner()->FindByTsyHandle(aTsyReqHandle);
+ __ASSERT_ALWAYS(reqEntry!=NULL,Fault(EEtelFaultNotRecognisedTsyHandle));
+
+ return reqEntry->iSession->TelServer()->IsPriorityClient(reqEntry->iSession);
+ }
+
+EXPORT_C CCallBase* CCallBase::ResolveSubSessionHandle(const TTsyReqHandle aTsyReqHandle,
+ const TInt aSubSessionHandle)
+//
+// expects the subsession handle of a call, which must have been opened by the same client session
+// which opened this call and called the current request (identified by aTsyReqHandle)
+//
+ {
+ CReqEntry* reqEntry=PhoneOwner()->FindByTsyHandle(aTsyReqHandle);
+ __ASSERT_ALWAYS(reqEntry!=NULL,Fault(EEtelFaultNotRecognisedTsyHandle));
+ return REINTERPRET_CAST(CCallBase*,reqEntry->iSession->CObjectFromHandle(aSubSessionHandle));
+ }
+
+EXPORT_C void CCallBase::OpenPostProcessing(CTelSession* ,const TInt)
+//
+// Perform post-processing after object has been added to session's CObjectIx.
+//
+ {}
+
+EXPORT_C void CCallBase::CloseSubSessionPreProcessing(CTelSession* aSession,const TInt aSubSessionHandle)
+//
+// Perform close post-processing before object being close
+// if is owner then set to EUnOwned
+//
+ {
+ LOGTEXT("CCallBase::CloseSubSessionPreProcessing() - about to create dummy session");
+ CreateDummySession(aSession,aSubSessionHandle);
+ RCall::TOwnershipStatus owner=CheckOwnershipBySession(aSession,aSubSessionHandle);
+ if (owner==RCall::EOwnershipOwnedByThisClient)
+ {
+ CreateDummySession(aSession,aSubSessionHandle,ETrue);
+ if (iLoanDataPort) // data port being on loan by this owner
+ RecoverDataPortAndRelinquishOwnership(); // inform tsy about this
+ else
+ RelinquishOwnership();
+ }
+ FlushReqs(aSession,aSubSessionHandle);
+ }
+
+EXPORT_C void CCallBase::RelinquishOwnershipCompleted(const TInt aError)
+//
+// Server called Tsy with RelinquishOwnership()
+// TSY should do a Up call with this function
+//
+ {
+ __ASSERT_ALWAYS(aError==KErrNone,Fault(EEtelFaultCanNotRelinquishOwnership));
+ CheckAndDestroyDummySubSession();
+ }
+
+EXPORT_C void CCallBase::RecoverDataPortAndRelinquishOwnershipCompleted(const TInt aError)
+//
+// Server called Tsy with RecoverDataPortAndRelinquishOwnership()
+// TSY should do a Up call with this function
+//
+ {
+ __ASSERT_ALWAYS(aError==KErrNone,Fault(EEtelFaultCanNotRelinquishOwnership));
+ iLoanDataPort=EFalse;
+ RelinquishOwnershipCompleted(aError);
+ }
+
+EXPORT_C TInt CCallBase::Service(const RMessage2& aMessage,CReqEntry* aReqEntry)
+//
+// The ServiceL functionality for the call
+//
+ {
+ __ASSERT_ALWAYS(aReqEntry!=NULL,Fault(EEtelFaultCallTsyServiceWithoutReqPackage));
+ aReqEntry->iPlacedRequest=ETrue;
+ TTsyReqHandle tsyReqHandle=aReqEntry->iTsyReqHandle;
+ TDes8* des1 = BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotWrite);
+ TUint8* ptr1=Ptr1(des1);
+ switch (aReqEntry->iFunction)
+ {
+
+ // Asynchronous + Cancel
+ case EEtelCallCapsChangeNotification:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return NotifyCapsChange(tsyReqHandle,REINTERPRET_CAST(RCall::TCaps*,ptr1));
+ case EEtelCallCapsChangeNotificationCancel:
+ return NotifyCapsChangeCancel(tsyReqHandle);
+ case EEtelCallNotifyHookChange:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return NotifyHookChange(tsyReqHandle,REINTERPRET_CAST(RCall::THookStatus*,ptr1));
+ case EEtelCallNotifyHookChangeCancel:
+ return NotifyHookChangeCancel(tsyReqHandle);
+
+ case EEtelCallNotifyStatusChange:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return NotifyStatusChange(tsyReqHandle,REINTERPRET_CAST(RCall::TStatus*,ptr1));
+ case EEtelCallNotifyStatusChangeCancel:
+ return NotifyStatusChangeCancel(tsyReqHandle);
+ case EEtelCallNotifyDurationChange:
+ return NotifyDurationChange(tsyReqHandle,REINTERPRET_CAST(TTimeIntervalSeconds*,ptr1));
+ case EEtelCallNotifyDurationChangeCancel:
+ return NotifyDurationChangeCancel(tsyReqHandle);
+ case EEtelCallDial:
+ {
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ TDes* des2 = NULL;
+ des2 = BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotWrite);
+ __ASSERT_ALWAYS(des2!=NULL,Fault(EEtelFaultDes2DoesNotExist));
+ return Dial(tsyReqHandle,des1,des2);
+ }
+ case EEtelCallDialCancel:
+ return DialCancel(tsyReqHandle);
+
+ case EEtelCallConnect:
+ return Connect(tsyReqHandle,des1);
+ case EEtelCallConnectCancel:
+ return ConnectCancel(tsyReqHandle);
+
+ case EEtelCallAnswer:
+ return AnswerIncomingCall(tsyReqHandle,des1);
+ case EEtelCallAnswerCancel:
+ return AnswerIncomingCallCancel(tsyReqHandle);
+
+ case EEtelCallHangUp:
+ return HangUp(tsyReqHandle);
+ case EEtelCallHangUpCancel:
+ return HangUpCancel(tsyReqHandle);
+
+ case EEtelCallAcquireOwnership:
+ {
+ if (RCall::EOwnershipOwnedByThisClient==
+ CheckOwnershipBySession(aReqEntry->iSession,aMessage.Int3()))
+ return KErrEtelAlreadyCallOwner;
+ else
+ return AcquireOwnership(tsyReqHandle);
+ }
+ case EEtelCallAcquireOwnershipCancel:
+ return AcquireOwnershipCancel(tsyReqHandle);
+
+ // Synchronous
+ case EEtelCallGetInfo:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return GetInfo(tsyReqHandle,REINTERPRET_CAST(RCall::TCallInfo*,ptr1));
+ case EEtelCallGetStatus:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return GetStatus(tsyReqHandle,REINTERPRET_CAST(RCall::TStatus*,ptr1));
+ case EEtelCallGetCaps:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return GetCaps(tsyReqHandle,REINTERPRET_CAST(RCall::TCaps*,ptr1));
+ case EEtelCallLoanDataPort:
+ {
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ TInt ret=LoanDataPort(tsyReqHandle,REINTERPRET_CAST(RCall::TCommPort*,ptr1));
+ if (ret==KErrNone)
+ iLoanDataPort=ETrue;
+ return ret;
+ }
+ case EEtelCallLoanDataPortCancel:
+ return LoanDataPortCancel(tsyReqHandle);
+
+ case EEtelCallRecoverDataPort:
+ {
+ TInt ret=RecoverDataPort(tsyReqHandle);
+ if (ret==KErrNone)
+ iLoanDataPort=EFalse;
+ return ret;
+ }
+
+ case EEtelCallTransferOwnership:
+ return TransferOwnership(tsyReqHandle);
+ case EEtelCallGetBearerServiceInfo:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return GetBearerServiceInfo(tsyReqHandle,REINTERPRET_CAST(RCall::TBearerService*,ptr1));
+
+ case EEtelCallGetOwnershipStatus:
+ {
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+
+ RCall::TOwnershipStatus* owner=REINTERPRET_CAST(RCall::TOwnershipStatus*,ptr1);
+ *owner=CheckOwnershipBySession(aReqEntry->iSession,aMessage.Int3());
+ ReqCompleted(tsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+ case EEtelCallGetCallParams:
+ {
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return GetCallParams(tsyReqHandle,des1);
+ }
+ case EEtelCallGetCallDuration:
+ {
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return GetCallDuration(tsyReqHandle,REINTERPRET_CAST(TTimeIntervalSeconds*,ptr1));
+ }
+ case EEtelCallGetFaxSettings:
+ {
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return GetFaxSettings(tsyReqHandle,REINTERPRET_CAST(RCall::TFaxSessionSettings*,ptr1));
+ }
+
+ case EEtelCallSetFaxSettings:
+ {
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return SetFaxSettings(tsyReqHandle,REINTERPRET_CAST(RCall::TFaxSessionSettings*,ptr1));
+ }
+ case EEtelCallReferenceCount:
+ {
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+
+ TInt* count=REINTERPRET_CAST(TInt*,ptr1);
+ *count=AccessCount();
+ ReqCompleted(tsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+ case EEtelAdoptFaxSharedHeaderFile:
+ {
+ CFaxSharedFileHandles* fshare = NULL;
+ TRAPD(err, fshare = CFaxSharedFileHandles::NewL(aMessage));
+ if(err != KErrNone)
+ {
+ return err;
+ }
+ //Pass the CFaxSharedFileHandles object to the TSY. If call is successful then TSY assumes owenership of the object else we delete it.
+ TInt ret = SetFaxSharedHeaderFile(tsyReqHandle, fshare);
+ if(ret!= KErrNone)
+ {
+ delete fshare;
+ }
+ return ret;
+ }
+ default:
+ return ServiceExtFunc(aMessage,aReqEntry);
+ }
+ }
+
+EXPORT_C RHandleBase* CCallBase::GlobalKernelObjectHandle()
+ {
+ if (iChunk.Handle() == KNullHandle) return NULL;
+ return &iChunk;
+ }
+
+
+EXPORT_C RFax::TProgress* CCallBase::CreateFaxProgressChunk()
+//
+// Even if already created, return pointer to it
+//
+ {
+ if (iChunk.Handle() == KNullHandle)
+ {
+ TInt r = iChunk.CreateGlobal(KNullDesC,sizeof (RFax::TProgress), sizeof (RFax::TProgress),EOwnerProcess);
+ if (r == KErrNone)
+ {
+ RFax::TProgress* progress = new(iChunk.Base()) RFax::TProgress;
+ progress->iLastUpdateTime = 0;
+ progress->iAnswerback.Zero ();
+ progress->iPhase = ENotYetStarted;
+ progress->iSpeed = 9600;
+ progress->iResolution = EFaxNormal;
+ progress->iCompression = EModifiedHuffman;
+ progress->iECM = 0;
+ progress->iPage = 0;
+ progress->iLines = 0;
+ return progress;
+ }
+ if (r != KErrNone)
+ return NULL;
+
+ }
+ return (RFax::TProgress*)iChunk.Base();
+ }
+
+/**
+Base implementation for virtual API declared in MCallBaseTSY. This base implementation always returns KErrNotSupported and
+it is therefore necessary for TSYs who support this API to override this in their CCallBase derived class.
+
+This function passes through a pointer to a heap-based CFaxSharedFileHandles object. This object is instantiated by Etel but
+a successful return of this function will pass responsibility for deletion of aFaxSharedFileHandles from Etel server to the TSY.
+If an error code is returned from this function (e.g. KErrNotSupported) Etel maintains ownership of the aFaxSharedFileHandles and
+is responsible for its deletion.
+
+TSY overrides of this function must correctly handle the cleanup of the aFaxSharedFileHandles object if they take ownership of it
+which is implied when returning from this function with KErrNone.
+
+@publishedPartner
+@param aTsyReqHandle Handle to request.
+@param aFaxSharedFileHandles CFaxSharedFileHandles instance to be stored in TSY.
+@released Released v9.0 to allow a fax client to pass a file handle to the Fax server.
+*/
+EXPORT_C TInt CCallBase::SetFaxSharedHeaderFile(const TTsyReqHandle /*aTsyReqHandle*/, CFaxSharedFileHandles* /*aFaxSharedFileHandles*/)
+ {
+ return KErrNotSupported;
+ }
+
+EXPORT_C void CCallBase::DeleteFaxProgressChunk()
+ {
+ iChunk.Close();
+ }
+
+EXPORT_C CTelObject::TReqMode CCallBase::ReqModeL(const TInt aIpc)
+//
+// Basic Request Mode for Call
+//
+ {
+ CTelObject::TReqMode mode=0;
+ switch (aIpc)
+ {
+ case EEtelCallNotifyHookChange:
+ case EEtelCallNotifyStatusChange:
+ case EEtelCallNotifyDurationChange:
+ case EEtelCallCapsChangeNotification:
+ mode=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately;
+ break;
+ case EEtelCallGetInfo:
+ case EEtelCallRecoverDataPort:
+ case EEtelCallGetStatus:
+ case EEtelCallGetCaps:
+ case EEtelCallTransferOwnership:
+ case EEtelCallAcquireOwnership:
+ case EEtelCallGetFaxSettings:
+ case EEtelCallGetCallParams:
+ case EEtelCallGetCallDuration:
+ case EEtelCallAnswer: // no longer obeys flow control since it may be placed long before
+ // a call arrives
+ break;
+ case EEtelCallGetOwnershipStatus:
+ case EEtelCallGetBearerServiceInfo:
+ case EEtelCallSetFaxSettings:
+ case EEtelAdoptFaxSharedHeaderFile:
+ case EEtelCallReferenceCount:
+ break;
+ case EEtelCallLoanDataPort:
+ case EEtelCallDial:
+ case EEtelCallConnect:
+ case EEtelCallHangUp:
+
+ mode=KReqModeFlowControlObeyed;
+ break;
+
+ default:
+ User::Leave(KErrNotSupported);
+ break;
+ }
+ return mode;
+ }
+
+EXPORT_C TInt CCallBase::NumberOfSlotsL(const TInt aIpc)
+ {
+ switch (aIpc)
+ {
+ case EEtelCallNotifyHookChange:
+ case EEtelCallNotifyDurationChange:
+ break;
+ case EEtelCallNotifyStatusChange:
+ return KSlotNumbersCallStatusChange;
+ case EEtelCallCapsChangeNotification:
+ return KSlotNumbersCallCapsChange;
+ default:
+ User::Leave(KErrNotSupported);
+ break;
+ }
+ return KSlotNumbersDefault;
+ }
+
+//
+//
+// CLineBase
+//
+//
+EXPORT_C CLineBase::CLineBase()
+//
+// C'Tor
+//
+ {
+ __DECLARE_NAME(_S("CLineBase"));
+ }
+
+EXPORT_C CLineBase::~CLineBase()
+//
+// D'Tor
+//
+ {
+ LOGTEXT("~CLineBase");
+ }
+
+EXPORT_C TInt CLineBase::CancelService(const TInt aIpc,const TTsyReqHandle aTsyReqHandle)
+//
+// Cancel Service for Line
+//
+ {
+ __ASSERT_ALWAYS(( aIpc==EEtelLineNotifyIncomingCall ||
+ aIpc==EEtelLineNotifyHookChange ||
+ aIpc==EEtelLineNotifyStatusChange ||
+ aIpc==EEtelLineNotifyCallAdded ||
+ aIpc==EETelLineCapsChangeNotification)
+ ,Fault(EEtelFaultInvalidIpcForCancel));
+ switch (aIpc)
+ {
+ case EEtelLineNotifyIncomingCall:
+ return NotifyIncomingCallCancel(aTsyReqHandle);
+ case EEtelLineNotifyHookChange:
+ return NotifyHookChangeCancel(aTsyReqHandle);
+ case EEtelLineNotifyStatusChange:
+ return NotifyStatusChangeCancel(aTsyReqHandle);
+ case EEtelLineNotifyCallAdded:
+ return NotifyCallAddedCancel(aTsyReqHandle);
+ case EETelLineCapsChangeNotification:
+ return NotifyCapsChangeCancel(aTsyReqHandle);
+ default:
+ return KErrGeneral; // should never reaches here
+ }
+ }
+
+EXPORT_C TInt CLineBase::Service(const RMessage2& aMessage, CReqEntry* aReqEntry)
+//
+// The ServiceL Functionality for the Line
+//
+ {
+ __ASSERT_ALWAYS(aReqEntry!=NULL,Fault(EEtelFaultCallTsyServiceWithoutReqPackage));
+ aReqEntry->iPlacedRequest=ETrue;
+ TTsyReqHandle tsyReqHandle=aReqEntry->iTsyReqHandle;
+ TDes8* des1 = BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotWrite);
+ TUint8* ptr1=Ptr1(des1);
+
+ switch (aReqEntry->iFunction)
+ {
+ case EETelLineCapsChangeNotification:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return NotifyCapsChange(tsyReqHandle,REINTERPRET_CAST(RLine::TCaps*,ptr1));
+ case EETelLineCapsChangeNotificationCancel:
+ return NotifyCapsChangeCancel(tsyReqHandle);
+ case EEtelLineNotifyIncomingCall:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return NotifyIncomingCall(tsyReqHandle,REINTERPRET_CAST(TName*,ptr1));
+ case EEtelLineNotifyIncomingCallCancel:
+ return NotifyIncomingCallCancel(tsyReqHandle);
+
+ case EEtelLineNotifyHookChange:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return NotifyHookChange(tsyReqHandle,REINTERPRET_CAST(RCall::THookStatus*,ptr1));
+ case EEtelLineNotifyHookChangeCancel:
+ return NotifyHookChangeCancel(tsyReqHandle);
+ case EEtelLineNotifyStatusChange:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return NotifyStatusChange(tsyReqHandle,REINTERPRET_CAST(RCall::TStatus*,ptr1));
+ case EEtelLineNotifyStatusChangeCancel:
+ return NotifyStatusChangeCancel(tsyReqHandle);
+ case EEtelLineNotifyCallAdded:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return NotifyCallAdded(tsyReqHandle,REINTERPRET_CAST(TName*,ptr1));
+ case EEtelLineNotifyCallAddedCancel:
+ return NotifyCallAddedCancel(tsyReqHandle);
+
+ case EEtelLineGetHookStatus:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return GetHookStatus(tsyReqHandle,REINTERPRET_CAST(RCall::THookStatus*,ptr1));
+
+ case EEtelLineGetInfo:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return GetInfo(tsyReqHandle,REINTERPRET_CAST(RLine::TLineInfo*,ptr1));
+ case EEtelLineGetCaps:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return GetCaps(tsyReqHandle,REINTERPRET_CAST(RLine::TCaps*,ptr1));
+ case EEtelLineGetStatus:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return GetStatus(tsyReqHandle,REINTERPRET_CAST(RCall::TStatus*,ptr1));
+ case EEtelLineEnumerateCall:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return EnumerateCall(tsyReqHandle,REINTERPRET_CAST(TInt*,ptr1));
+ case EEtelLineGetCallInfo:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return GetCallInfo(tsyReqHandle,REINTERPRET_CAST(TCallInfoIndex*,ptr1));
+ default:
+ return ServiceExtFunc(aMessage,aReqEntry);
+ }
+ }
+
+EXPORT_C void CLineBase::Init()
+//
+// not used for Line
+//
+ {}
+
+EXPORT_C void CLineBase::OpenPostProcessing(CTelSession*,const TInt)
+//
+// Perform post-processing after object has been added to session's CObjectIx.
+//
+ {}
+
+EXPORT_C void CLineBase::CloseSubSessionPreProcessing(CTelSession* aSession,const TInt aSubSessionHandle)
+//
+//
+//
+ {
+ LOGTEXT("CLineBase::CloseSubSessionPreProcessing() - about to create dummy session");
+ CreateDummySession(aSession,aSubSessionHandle);
+ FlushReqs(aSession,aSubSessionHandle);
+ }
+
+EXPORT_C CTelObject::TReqMode CLineBase::ReqModeL(const TInt aIpc)
+//
+// Mode Request Inquiry Functions
+//
+ {
+ CTelObject::TReqMode mode=0;
+ switch (aIpc)
+ {
+ case EEtelLineGetCaps:
+ case EEtelLineGetStatus:
+ case EEtelLineGetHookStatus:
+ case EEtelLineEnumerateCall:
+ case EEtelLineGetCallInfo:
+ case EEtelLineGetInfo:
+ case EEtelLineNotifyIncomingCall: // 3/12/98 Removed Repost ability.
+ mode=KReqModeMultipleCompletionEnabled;
+ break;
+ case EEtelLineNotifyHookChange:
+ case EEtelLineNotifyStatusChange:
+ case EEtelLineNotifyCallAdded:
+ case EETelLineCapsChangeNotification:
+ mode=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately;
+ break;
+ default:
+ User::Leave(KErrNotSupported);
+ break;
+ }
+ return mode;
+ }
+
+EXPORT_C TInt CLineBase::NumberOfSlotsL(const TInt aIpc)
+ {
+ switch (aIpc)
+ {
+ case EEtelLineNotifyHookChange:
+ case EETelLineCapsChangeNotification:
+ break;
+ case EEtelLineNotifyStatusChange:
+ return KSlotNumbersLineStatusChange;
+ case EEtelLineNotifyCallAdded:
+ return KSlotNumbersLineCallAddedChange;
+ default:
+ User::Leave(KErrNotSupported);
+ break;
+ }
+ return KSlotNumbersDefault;
+ }
+
+//
+//
+// CPhoneBase
+//
+//
+EXPORT_C CPhoneBase::CPhoneBase()
+//
+// CPhoneBase constructor
+//
+ {
+ __DECLARE_NAME(_S("CPhoneBase"));
+ iReqWaitList.SetOffset(_FOFF(CReqEntry,iLink));
+ iReqActiveList.SetOffset(_FOFF(CReqEntry,iLink));
+ iTsyReqHandleCnt=TSY_HANDLE_INIT_VALUE;
+ }
+
+EXPORT_C CPhoneBase::~CPhoneBase()
+//
+// CPhone destructor.
+// Attual closing of the owner is done in CSubSessionBase destructor
+// This is for all object inherit fron CSubSesissionBase
+//
+ {
+ LOGTEXT("~CPhoneBase");
+ }
+
+//
+// Request List Manipulation Functions
+//
+CReqEntry* CPhoneBase::ActivateNextWaitingReq()
+//
+// Use: during completion to Activate the next waiting request
+// Action: Find next Waiting Req, move to active, and return.
+//
+ {
+ if(iReqWaitList.IsEmpty())
+ return NULL;
+
+ CReqEntry* reqEntry=iReqWaitList.First();
+ if(reqEntry==NULL)
+ return NULL;
+ reqEntry->iLink.Deque();
+ iReqActiveList.AddLast(*reqEntry);
+ if (reqEntry->iReqMode & KReqModeMultipleCompletionEnabled | KReqModeMultipleCompletionWithInterestLevel)
+ {
+ CReqEntry* otherClientsEntry;
+ TDblQueIter<CReqEntry> iter(iReqWaitList);
+ while(otherClientsEntry=iter++, otherClientsEntry!=NULL)
+ {
+ if(otherClientsEntry->iTsyReqHandle==reqEntry->iTsyReqHandle)
+ {
+ otherClientsEntry->iLink.Deque();
+ iReqActiveList.AddLast(*otherClientsEntry);
+ }
+ }
+ }
+ return reqEntry;
+ }
+
+CReqEntry* CPhoneBase::FindByTsyHandleAndPlacedRequest(const TTsyReqHandle aTsyReqHandle)
+//
+// Use: to search active req list for a single req, remove and then return it. Can be called repeatedly for Notification
+//
+ {
+ CReqEntry* reqEntry;
+ TDblQueIter<CReqEntry> iter(iReqActiveList);
+ while(reqEntry=iter++, reqEntry!=NULL)
+ {
+ if(reqEntry->iTsyReqHandle==aTsyReqHandle && reqEntry->iPlacedRequest)
+ return reqEntry;
+ }
+ return NULL;
+ }
+
+CReqEntry* CPhoneBase::FindByTsyHandle(const TTsyReqHandle aTsyReqHandle)
+//
+// Use: to search active req list for a single req, remove and then return it. Can be called repeatedly for Notification
+//
+ {
+ CReqEntry* reqEntry;
+ TDblQueIter<CReqEntry> iter(iReqActiveList);
+ while(reqEntry=iter++, reqEntry!=NULL)
+ {
+ if(reqEntry->iTsyReqHandle==aTsyReqHandle)
+ return reqEntry;
+ }
+ return NULL;
+ }
+
+/*
+EXPORT_C TInt CPhoneBase::FindSessionByTsyHandle(const TTsyReqHandle aTsyReqHandle)
+ {
+ CReqEntry* reqEntry = FindByTsyHandle(aTsyReqHandle);
+ if (!reqEntry)
+ {
+ // TODO we'd need to ensure the subsession handle was positive
+ // to be able to return an error. Shifting the pointer >>1
+ // would ensure this.
+ return KErrNotFound;
+ }
+ return reinterpret_cast<TInt>(reqEntry->iSession);
+ }
+
+EXPORT_C TInt CPhoneBase::FindSubSessionByTsyHandle(const TTsyReqHandle aTsyReqHandle)
+ {
+ CReqEntry* reqEntry = FindByTsyHandle(aTsyReqHandle);
+ if (!reqEntry)
+ {
+ return KErrNotFound;
+ }
+ return reqEntry->iMessage.Int3();
+ }
+*/
+void CPhoneBase::UpdateBuffer(CReqEntry* aUpdatedReqEntry,CReqEntry* aReqEntry)
+//
+// Is passed both the TSY-updated request entry (which may be multi-buffered or not)
+// and another request entry which is to have the data copied into it (which again may or may
+// not be multi-buffered) copies the latest data into the target request entry.
+//
+ {
+ __ASSERT_ALWAYS(aUpdatedReqEntry->iFunction==aReqEntry->iFunction,Fault(EEtelFaultUpdatingBufferOfDifferentIpc));
+ TInt msgType = aReqEntry->iMessage.Int1();
+ if (msgType==EIsaNarrowAndUnicodeDoubleDesTobeRead)
+ {
+ TDes8* targetDes1 = BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotWrite);
+ TDes16* targetDes2 = BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotWrite);
+ TDes8* sourceDes1 = BufferDes1(aUpdatedReqEntry->iBuffer,CBuffer::ESlotWrite);
+ TDes16* sourceDes2 = BufferDes2u(aUpdatedReqEntry->iBuffer,CBuffer::ESlotWrite);
+ if (sourceDes1!=targetDes1)
+ {
+ targetDes1->Copy(*sourceDes1);
+ if (targetDes2)
+ targetDes2->Copy(*sourceDes2);
+ aReqEntry->iBuffer->IncWrite();
+ }
+ return;
+ }
+ if (aUpdatedReqEntry->iSession->IsUnicodeReq(msgType))
+ {
+ TDes16* targetDes1 = BufferDes1u(aReqEntry->iBuffer,CBuffer::ESlotWrite);
+ TDes16* targetDes2 = BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotWrite);
+ TDes16* sourceDes1 = BufferDes1u(aUpdatedReqEntry->iBuffer,CBuffer::ESlotWrite);
+ TDes16* sourceDes2 = BufferDes2u(aUpdatedReqEntry->iBuffer,CBuffer::ESlotWrite);
+ if (sourceDes1!=targetDes1)
+ {
+ targetDes1->Copy(*sourceDes1);
+ if (targetDes2)
+ targetDes2->Copy(*sourceDes2);
+ aReqEntry->iBuffer->IncWrite();
+ }
+ }
+ else // this is narrow
+ {
+ TDes8* targetDes1 = BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotWrite);
+ TDes8* targetDes2 = BufferDes2(aReqEntry->iBuffer,CBuffer::ESlotWrite);
+ TDes8* sourceDes1 = BufferDes1(aUpdatedReqEntry->iBuffer,CBuffer::ESlotWrite);
+ TDes8* sourceDes2 = BufferDes2(aUpdatedReqEntry->iBuffer,CBuffer::ESlotWrite);
+ if (sourceDes1!=targetDes1)
+ {
+ targetDes1->Copy(*sourceDes1);
+ if (targetDes2)
+ targetDes2->Copy(*sourceDes2);
+ aReqEntry->iBuffer->IncWrite();
+ }
+ }
+ }
+
+CReqEntry* CPhoneBase::FindClientInWaiting(CTelSession* aSession,const TInt aSubSessionHandle,const TInt aIpc)
+//
+// Used to search waiting list for a req that's to be cancelled.
+// If non-Null is returned it will have been removed by this function and can be completed by the caller.
+//
+ {
+ CReqEntry* reqEntry;
+ TDblQueIter<CReqEntry> iter(iReqWaitList);
+ while(reqEntry = iter++, reqEntry!=NULL)
+ {
+ if((reqEntry->iSession==aSession)&&(reqEntry->iMessage.Int3()==aSubSessionHandle)&&(reqEntry->iFunction==aIpc))
+ return reqEntry;
+ }
+ return NULL;
+ }
+
+CReqEntry* CPhoneBase::FindClientInActive(CTelSession* aSession,const TInt aSubSessionHandle,const TInt aIpc)
+//
+// Used to search the active req list for a req that's to be cancelled.
+// The function will return any req entry found, by the caller does not know to pass the cancel down until a search has been done just on the aIpc
+//
+ {
+ CReqEntry* reqEntry;
+ TDblQueIter<CReqEntry> iter(iReqActiveList);
+ while(reqEntry = iter++, reqEntry!=NULL)
+ {
+ if((reqEntry->iSession==aSession)&&(reqEntry->iMessage.Int3()==aSubSessionHandle)&&(reqEntry->iFunction==aIpc))
+ return reqEntry;
+ }
+ return NULL;
+ }
+
+CReqEntry* CPhoneBase::FindByIpcAndTelObject(const TInt aIpc, const CTelObject* aTelObject, const TUint aBufSize)
+//
+// Finds an active request by both IPC and by the TelObject it was placed on
+//
+ {
+ CReqEntry* reqEntry;
+ TDblQueIter<CReqEntry> iter(iReqActiveList);
+ while(reqEntry = iter++, reqEntry!=NULL)
+ {
+ if(reqEntry->iFunction==aIpc && reqEntry->iTelObject==aTelObject
+ && reqEntry->iBuffer->Size() == aBufSize)
+ return reqEntry;
+ }
+ return NULL;
+ }
+
+CReqEntry* CPhoneBase::FindByIpcAndTelObjectInWaiting(const TInt aIpc, const CTelObject* aTelObject, const TUint aBufSize)
+//
+// Finds a waiting request by both IPC and by the TelObject it was placed on
+//
+ {
+ CReqEntry* reqEntry;
+ TDblQueIter<CReqEntry> iter(iReqWaitList);
+ while(reqEntry = iter++, reqEntry!=NULL)
+ {
+ if(reqEntry->iFunction==aIpc && reqEntry->iTelObject==aTelObject
+ && reqEntry->iBuffer->Size() == aBufSize)
+ return reqEntry;
+ }
+ return NULL;
+ }
+
+void CPhoneBase::AddReqToActive(CReqEntry* aReqEntry)
+//
+// Add reqEntry to the 'active list'
+//
+ {
+ LOGTEXT2("CPhoneBase::AddReqToActive with TsyHandle of %d", aReqEntry->iTsyReqHandle);
+ iReqActiveList.AddLast(*aReqEntry);
+ }
+
+void CPhoneBase::AddReqToWaiting(CReqEntry* aReqEntry)
+//
+// Add entry to the 'wait list'
+//
+ {
+ LOGTEXT2("CPhoneBase::AddReqToWaiting with TsyHandle of %d", aReqEntry->iTsyReqHandle);
+ iReqWaitList.AddLast(*aReqEntry);
+ }
+
+TTsyReqHandle CPhoneBase::TsyReqHandle()
+//
+// Return the request handle if wrap round avoid assigned to TSY_HANDLE_INIT_VALUE
+//
+ {
+ iTsyReqHandleCnt++ ;
+ if (iTsyReqHandleCnt==TSY_HANDLE_INIT_VALUE)
+ iTsyReqHandleCnt=(TSY_HANDLE_INIT_VALUE+1);
+ return iTsyReqHandleCnt;
+ }
+
+CReqEntry* CPhoneBase::NewReqL(const RMessage2& aMessage, CTelSession* aSession,CBuffer* aBuffer,
+ const CTelObject* aTelObject,TInt aFunction)
+//
+// Create new req entry
+//
+ {
+ return CReqEntry::NewL(TsyReqHandle(),aMessage,aSession,aBuffer,aTelObject,aFunction,aSession->EmergencyClientHeap(aMessage.Int1()));
+ }
+
+CReqEntry* CPhoneBase::FindSameClientEntry(CTelSession* aSession,const TInt aSubSessionHandle,const TInt aIpc)
+//
+// Seaching for duplicate request and panic client is return not NULL
+//
+ {
+ CReqEntry* reqEntry=FindClientInWaiting(aSession,aSubSessionHandle,aIpc);
+
+ if (reqEntry!=NULL)
+ return reqEntry;
+ else // not found in waiting
+ reqEntry=FindClientInActive(aSession,aSubSessionHandle,aIpc);
+ return reqEntry;
+
+ }
+
+EXPORT_C void CPhoneBase::OpenPostProcessing(CTelSession*,const TInt)
+//
+// Perform post-processing after object has been added to session's CObjectIx.
+//
+ {}
+
+EXPORT_C void CPhoneBase::CloseSubSessionPreProcessing(CTelSession* aSession,const TInt aSubSessionHandle)
+//
+// Find if any active request if so create a dummy session
+//
+ {
+ LOGTEXT("CPhoneBase::CloseSubSessionPreProcessing");
+ CreateDummySession(aSession,aSubSessionHandle);
+ FlushReqs(aSession,aSubSessionHandle);
+ }
+
+EXPORT_C TInt CPhoneBase::Service(const RMessage2& aMessage, CReqEntry* aReqEntry)
+//
+// The ServiceL functionality for the phone
+//
+ {
+ __ASSERT_ALWAYS(aReqEntry!=NULL,Fault(EEtelFaultCallTsyServiceWithoutReqPackage));
+ aReqEntry->iPlacedRequest=ETrue;
+ TTsyReqHandle tsyReqHandle=aReqEntry->iTsyReqHandle;
+ TDes8* des1 = BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotWrite);
+ TUint8* ptr1=Ptr1(des1);
+ switch (aReqEntry->iFunction)
+ {
+ case EETelPhoneCapsChangeNotification:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return NotifyCapsChange(tsyReqHandle,REINTERPRET_CAST(RPhone::TCaps*,ptr1));
+ case EETelPhoneCapsChangeNotificationCancel:
+ return NotifyCapsChangeCancel(tsyReqHandle);
+ case EEtelPhoneInitialise:
+ return ControlledInitialisation(tsyReqHandle);
+ case EEtelPhoneInitialiseCancel:
+ return ControlledInitialisationCancel(tsyReqHandle);
+ case EEtelPhoneNotifyModemDetected:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return NotifyModemDetected(tsyReqHandle,REINTERPRET_CAST(RPhone::TModemDetection*,ptr1) );
+ case EEtelPhoneNotifyModemDetectedCancel:
+ return NotifyModemDetectedCancel(tsyReqHandle);
+ case EEtelPhoneGetInfo:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return GetInfo(tsyReqHandle,REINTERPRET_CAST(RPhone::TPhoneInfo*,ptr1));
+ case EEtelPhoneGetCaps:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return GetCaps(tsyReqHandle,REINTERPRET_CAST(RPhone::TCaps*,ptr1));
+ case EEtelPhoneGetStatus:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return GetStatus(tsyReqHandle,REINTERPRET_CAST(RPhone::TStatus*,ptr1));
+ case EEtelPhoneEnumerateLines:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return EnumerateLines(tsyReqHandle,REINTERPRET_CAST(TInt*,ptr1));
+ case EEtelPhoneGetLineInfo:
+ __ASSERT_ALWAYS(des1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ return GetLineInfo(tsyReqHandle,REINTERPRET_CAST(TLineInfoIndex*,ptr1));
+ default:
+ return ServiceExtFunc(aMessage,aReqEntry);
+ }
+ }
+
+EXPORT_C TInt CPhoneBase::CancelService(const TInt aIpc,const TTsyReqHandle aTsyReqHandle)
+//
+// Cancel Outstanding service for the phone
+//
+ {
+ switch (aIpc)
+ {
+ case EEtelPhoneNotifyModemDetected:
+ return NotifyModemDetectedCancel(aTsyReqHandle);
+ case EETelPhoneCapsChangeNotification:
+ return NotifyCapsChangeCancel(aTsyReqHandle);
+ case EEtelPhoneInitialise:
+ return ControlledInitialisationCancel(aTsyReqHandle);
+ default:
+ return KErrGeneral;
+ }
+ }
+
+CReqEntry* CPhoneBase::FindClientReqInWaitList(CTelSession* aSession,const TInt aSubSessionHandle)
+//
+// Find first entry already logged by this client - in wait list
+//
+ {
+ CReqEntry* reqEntry;
+ TDblQueIter<CReqEntry> iter(iReqWaitList);
+ while(reqEntry = iter++, reqEntry!=NULL)
+ {
+ if(aSession==reqEntry->iSession && aSubSessionHandle==reqEntry->iMessage.Int3())
+ return reqEntry;
+ }
+ return NULL;
+ }
+
+CReqEntry* CPhoneBase::FindThisReqByAnotherClient(CTelSession* aSession,const TInt aSubSessionHandle,const TInt aIpc,const TUint aBufSize,const CTelObject* aThisTelObject)
+//
+// Find this IPC in active list, placed by a different client
+//
+ {
+ CReqEntry* reqEntry;
+ TDblQueIter<CReqEntry> iter(iReqActiveList);
+ while(reqEntry=iter++,reqEntry!=NULL)
+ {
+ if((aSession!=reqEntry->iSession || aSubSessionHandle!=reqEntry->iMessage.Int3())
+ && reqEntry->iFunction==aIpc && reqEntry->iTelObject==aThisTelObject
+ && reqEntry->iBuffer->Size()==aBufSize)
+ {
+ return reqEntry;
+ }
+ }
+ return NULL;
+ }
+
+CReqEntry* CPhoneBase::FindNonCancelledClientReq(CTelSession* aSession,const TInt aSubSessionHandle,const TInt aIpc)
+//
+// Find this IPC in active list, placed by this client but not the one which placed request on TSY
+//
+ {
+ CReqEntry* reqEntry;
+ TDblQueIter<CReqEntry> iter(iReqActiveList);
+ while(reqEntry=iter++,reqEntry!=NULL)
+ {
+ if(aSession==reqEntry->iSession && aSubSessionHandle==reqEntry->iMessage.Int3() && reqEntry->iFunction==aIpc && reqEntry->iCancelFnCalled==EFalse)
+ {
+ return reqEntry;
+ }
+ }
+ return NULL;
+ }
+
+void CPhoneBase::CheckAndCompleteAllActive(CReqEntry* aUpdatedReqEntry,const TReqMode aReqMode,const TInt aIpc,const TInt aError)
+//
+// Cycles through active list, checking for any requests with the same IPC value and if
+// registered, copying the data from the buffer that the TSY filled in to this buffer. All those
+// with the same IPC are completed up to the client (if the client is ready).
+//
+ {
+ CReqEntry* reqEntry;
+ TDblQueIter<CReqEntry> iter(iReqActiveList);
+ while(reqEntry = iter++, reqEntry!=NULL)
+ {
+ if(reqEntry->iFunction==aIpc && reqEntry!=aUpdatedReqEntry
+ && reqEntry->iTelObject==aUpdatedReqEntry->iTelObject
+ && reqEntry->iBuffer->Size()==aUpdatedReqEntry->iBuffer->Size())
+ {
+ UpdateBuffer(aUpdatedReqEntry,reqEntry);
+ TInt error = ResolveError(reqEntry->iSession,aError); // set error as either low or high byte
+ if (aReqMode & KReqModeRePostImmediately)
+ UpdateAndCompleteIfNecessary(reqEntry,error);
+ else
+ WriteBackAndCompleteReq(reqEntry,error);
+ }
+ }
+ }
+
+
+// The delivery object performs the task of delivering the request to the
+// client. It loops through the clients in priority order and gives each
+// client a fixed amount of time to either accept or reject. At the end
+// the request will either be allocated or discarded (if no one wants it).
+
+CMmDeliveryObject* CMmDeliveryObject::NewL( CTelObject& aTelObject )
+ {
+ CMmDeliveryObject* self=new(ELeave) CMmDeliveryObject( aTelObject );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+CMmDeliveryObject::CMmDeliveryObject( CTelObject& aTelObject ) :
+ CActive(EPriorityStandard), iTelObject(aTelObject)
+ {
+ CActiveScheduler::Add( this );
+ }
+
+void CMmDeliveryObject::ConstructL()
+ {
+ User::LeaveIfError( iDeliveryTimer.CreateLocal() );
+ }
+
+CMmDeliveryObject::~CMmDeliveryObject()
+ {
+ Cancel();
+ iDeliveryTimer.Close();
+ iPendingReqs.Close();
+ }
+
+void CMmDeliveryObject::DoCancel()
+ {
+ iDeliveryTimer.Cancel();
+ }
+
+// Called either when we need to attempt delivery of a request.
+// Can be due to:
+// 1) the start of the delivery process.
+// 2) a client rejecting the request which makes us try the next one.
+// 3) a client timing out which makes us try the next one.
+void CMmDeliveryObject::RunL()
+ {
+
+ if ( iStatus == KErrNone && iUpdatedReqEntry)
+ {
+
+ TInterestCategory interestCategory;
+ iCurrentReq = NULL;
+ iCurrentReq = HighestPriorityReq(interestCategory);
+
+ if ( iCurrentReq )
+ {
+ if (iUpdatedReqEntry!=iCurrentReq)
+ {
+ iTelObject.PhoneOwner()->UpdateBuffer(iUpdatedReqEntry,iCurrentReq);
+ }
+
+ // Offer incoming message to interested clients one at a time.
+ // Initially the priority client followed by Standard category clients.
+ OfferToClient( iCurrentReq );
+
+ // Client will have a certain time in which to accept/reject the message.
+ // After which it will be offered to the next client.
+ switch ( interestCategory )
+ {
+ case EInterestCategoryPriority:
+ iDeliveryTimer.After( iStatus, (KUssdOfferDialogueTimeout * KUssdPriorityTimeoutPercentage)/100 );
+ SetActive();
+ break;
+ case EInterestCategoryStandard:
+ iDeliveryTimer.After( iStatus, iTimeSlice );
+ SetActive();
+ break;
+ case EInterestCategoryDefault:
+ // wait on default client (no timeout) //TODO: What if the default client doesn't respond? (Neil)
+ break;
+ default:
+ // No more clients
+ Clear();
+ } // end switch
+ }
+ else
+ {
+ iTelObject.RepostRequest( iUpdatedReqEntry, KErrNone );
+
+ // No more clients left to check
+ Clear();
+ }
+ }
+ else
+ {
+ // Delivery has failed.
+ Clear();
+ }
+ }
+
+TInt CMmDeliveryObject::DeliverReqL( TDblQue<CReqEntry>& aArray, CReqEntry* aUpdatedReqEntry,
+ const CTelObject::TReqMode aReqMode, const TInt aIpc, TInt aError)
+ {
+ iPendingReqs.Reset();
+
+ ASSERT(aUpdatedReqEntry != NULL);
+ iUpdatedReqEntry = aUpdatedReqEntry;
+ iReqMode = aReqMode;
+ iError = aError;
+
+ CReqEntry* reqEntry = NULL;
+ TDblQueIter<CReqEntry> iter(aArray);
+ while(reqEntry = iter++, reqEntry!=NULL)
+ {
+ if(reqEntry->iFunction==aIpc
+ && reqEntry->iTelObject==iUpdatedReqEntry->iTelObject
+ && reqEntry->iBuffer->Size()==iUpdatedReqEntry->iBuffer->Size())
+ {
+ switch (reqEntry->iInterestCategory)
+ {
+ case EInterestCategoryPriority:
+ {
+ // If we don't already have a priority client registered,
+ // then add this one as the priority client.
+ if (iPriorityReq == NULL)
+ {
+ iPriorityReq = reqEntry;
+ }
+ // Otherwise if there is already a registered priority client,
+ // add this to the list of standard clients to be treated as such.
+ else
+ {
+ iPendingReqs.AppendL( reqEntry );
+ }
+ break;
+ }
+ case EInterestCategoryDefault:
+ {
+ // If we don't already have a default client registered,
+ // then add this one as the default client.
+ if (iDefaultReq == NULL)
+ {
+ iDefaultReq = reqEntry;
+ }
+ // Otherwise if there is already a registered default client,
+ // add this to the list of standard clients to be treated as such.
+ else
+ {
+ iPendingReqs.AppendL( reqEntry );
+ }
+ break;
+ }
+ default:
+ {
+ iPendingReqs.AppendL( reqEntry );
+ }
+ } //end switch
+ } //end if
+ }
+
+ // Calculate amount of time each client will get to accept the request
+ TInt count = iPendingReqs.Count();
+ if (count)
+ {
+ if (iPriorityReq)
+ {
+ iTimeSlice = (KUssdOfferDialogueTimeout * (100 - KUssdPriorityTimeoutPercentage)/(100 * count) );
+ }
+ else
+ {
+ iTimeSlice = KUssdOfferDialogueTimeout / count ;
+ }
+ }
+
+ // now start looping through clients...
+ DoStart();
+ return KErrNone;
+ }
+
+TBool CMmDeliveryObject::DeliveryInProgress() const
+ {
+ // In the case of delivery to the default client we won't be active when
+ // delivery is carried out as no timeout is used for the default client -
+ // TODO is it correct that the default client should have no timeout?
+ return (IsActive() || iCurrentReq);
+ }
+
+TInt CMmDeliveryObject::ClientsDecision( const RMessage2& aMessage, CTelSession* aSession, TBool aAccepted )
+ {
+ if (!DeliveryInProgress())
+ {
+ return KErrTimedOut;
+ }
+
+ const TInt currentreqsession = reinterpret_cast<TInt>(iCurrentReq->iSession);
+ const TInt currentreqsubsession = iCurrentReq->iMessage.Int3();
+
+ const TInt clientsession = reinterpret_cast<TInt>(aSession);
+ const TInt clientsubsession = aMessage.Int3();
+
+ if (currentreqsession != clientsession ||
+ currentreqsubsession != clientsubsession)
+ {
+ // do nothing - client took too long to reply and we've moved
+ // onto another client now
+ return KErrTimedOut;
+ }
+
+ if (aAccepted)
+ {
+ Cancel();
+ iTelObject.SetSessionOwner(clientsession, clientsubsession);
+ ASSERT(iUpdatedReqEntry != NULL);
+ // We repost the request so we don't miss the next message in the dialog
+ // in case the client is slow in calling ReceiveMessage again.
+ iTelObject.RepostRequest(iUpdatedReqEntry, KErrNone);
+ Clear();
+ }
+ else
+ {
+ Cancel();
+ DoStart();
+ }
+ return KErrNone;
+ }
+
+void CMmDeliveryObject::OfferToClient( CReqEntry* aReq )
+ {
+ iTelObject.OfferToClient(aReq, iUpdatedReqEntry, iReqMode, iError);
+ }
+
+
+// CMmDeliveryObject is being notified that a client has called cancel.
+// The relevant CReqEntry is being passed as a parameter.
+// Need to remove it from our list of interested (in Receiving messages) clients.
+
+void CMmDeliveryObject::DeletedReqEntry( CReqEntry* aReqEntry )
+ {
+ if (iCurrentReq == aReqEntry)
+ {
+ iCurrentReq = NULL;
+ }
+
+ if (iPriorityReq == aReqEntry)
+ {
+ iPriorityReq = NULL;
+ }
+
+ if (iDefaultReq == aReqEntry)
+ {
+ iDefaultReq = NULL;
+ }
+
+ if ( iPendingReqs.Count() )
+ {
+ for (TInt i = iPendingReqs.Count()-1; i>=0; --i)
+ {
+ if (aReqEntry == iPendingReqs[i])
+ {
+ iPendingReqs.Remove(i);
+ break;
+ }
+ }
+ }
+
+ if (aReqEntry == iUpdatedReqEntry)
+ {
+ // iUpdatedReqEntry is the client which cancelled.
+ // Copy data from the 'about to be destroyed' entry to
+ // one owned by the next client.
+
+ CReqEntry* req = NewUpdatedReqEntry();
+ if (req == NULL)
+ // No more clients left.
+ {
+ Cancel();
+ iPendingReqs.Close();
+ }
+ else
+ {
+ ASSERT(aReqEntry != req);
+ iTelObject.PhoneOwner()->UpdateBuffer(iUpdatedReqEntry,req);
+ iUpdatedReqEntry = req;
+ }
+ }
+ }
+
+CReqEntry* CMmDeliveryObject::NewUpdatedReqEntry()
+ {
+ if (iCurrentReq)
+ return iCurrentReq;
+
+ CReqEntry* req = NULL;
+ if (iPriorityReq)
+ {
+ req = iPriorityReq;
+ }
+ else if ( iPendingReqs.Count() )
+ {
+ req = iPendingReqs[0];
+ }
+ else if (iDefaultReq)
+ {
+ req = iDefaultReq;
+ }
+ return req;
+ }
+
+
+CReqEntry* CMmDeliveryObject::HighestPriorityReq( TInterestCategory& aInterestCategory )
+ {
+ aInterestCategory = EInterestCategoryStandard;
+ CReqEntry* req = NULL;
+ if (iPriorityReq)
+ {
+ req = iPriorityReq;
+ iPriorityReq = NULL;
+ aInterestCategory = EInterestCategoryPriority;
+ }
+ else if ( iPendingReqs.Count() )
+ {
+ req = iPendingReqs[0];
+ iPendingReqs.Remove(0);
+ aInterestCategory = EInterestCategoryStandard;
+ }
+ else if (iDefaultReq)
+ {
+ req = iDefaultReq;
+ iDefaultReq = NULL;
+ aInterestCategory = EInterestCategoryDefault;
+ }
+ return req;
+ }
+
+void CMmDeliveryObject::DoStart()
+ {
+ SetActive();
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete( status, KErrNone );
+ }
+
+void CMmDeliveryObject::Clear()
+ {
+ iPendingReqs.Reset();
+ iCurrentReq = NULL;
+ iPriorityReq = NULL;
+ iDefaultReq = NULL;
+
+ iUpdatedReqEntry = NULL;
+ iReqMode = 0;
+ iError = KErrNone;
+ }
+
+//
+// CPhoneBase performs Flow Control
+//
+TInt CPhoneBase::FlowControl() const
+//
+// Return the value of iFlowControlCnt
+//
+ {
+ return iFlowControlCnt;
+ }
+
+void CPhoneBase::FlowControlInc()
+//
+// Increase iFlowControlCnt
+//
+ {
+ LOGTEXT3("Incrementing Flow Control from %d to %d", iFlowControlCnt, iFlowControlCnt+1);
+ iFlowControlCnt++;
+ }
+
+void CPhoneBase::FlowControlDec()
+//
+// Decrease iFlowControlCnt
+//
+ {
+ __ASSERT_ALWAYS((iFlowControlCnt>0),Fault(EEtelFaultNegativeFlowcontrolCount));
+ LOGTEXT3("Decrementing Flow Control from %d to %d", iFlowControlCnt, iFlowControlCnt-1);
+ iFlowControlCnt--;
+ }
+
+EXPORT_C TBool CPhoneBase::CheckEmergencyClient(const TTsyReqHandle aTsyReqHandle) const
+ {
+ CReqEntry* reqEntry=PhoneOwner()->FindByTsyHandle(aTsyReqHandle);
+ __ASSERT_ALWAYS(reqEntry!=NULL,Fault(EEtelFaultNotRecognisedTsyHandle));
+
+ return reqEntry->iSession->TelServer()->IsEmergencyClient(reqEntry->iSession);
+ }
+
+
+EXPORT_C CTelObject::TReqMode CPhoneBase::ReqModeL(const TInt aIpc)
+//
+// Mode Request Inquiry Functions
+//
+ {
+ CTelObject::TReqMode mode=0;
+ switch (aIpc)
+ {
+ case EEtelPhoneInitialise: //test
+ mode=KReqModeFlowControlObeyed | KReqModeMultipleCompletionEnabled;
+ break;
+ case EEtelPhoneGetCaps:
+ case EEtelPhoneGetStatus:
+ case EEtelPhoneEnumerateLines:
+ case EEtelPhoneGetLineInfo:
+ case EEtelPhoneGetInfo:
+ mode=KReqModeMultipleCompletionEnabled;
+ break;
+ case EETelPhoneSetEmergencyClient:
+ mode=KReqModeFlowControlObeyed;
+ break;
+ case EEtelPhoneNotifyModemDetected:
+ case EETelPhoneCapsChangeNotification:
+ mode=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately;
+ break;
+ default:
+ User::Leave(KErrNotSupported);
+ break;
+ }
+ return mode;
+ }
+
+EXPORT_C TInt CPhoneBase::NumberOfSlotsL(const TInt aIpc)
+ {
+ switch (aIpc)
+ {
+ case EEtelPhoneNotifyModemDetected:
+ case EETelPhoneCapsChangeNotification:
+ break;
+ default:
+ User::Leave(KErrNotSupported);
+ break;
+ }
+ return KSlotNumbersDefault;
+ }
+
+TDblQue<CReqEntry>& CPhoneBase::ReqActiveList()
+ {
+ return iReqActiveList;
+ }