--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyserverplugins/multimodetsy/hayes/CALL.CPP Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,2763 @@
+// 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 <commsdattypesv1_1.h>
+#include "CALL.H" // Header file for this source file
+#include "NOTIFY.H"
+#include "FAX.H"
+#include "ATDIAL.H"
+#include "ATANSWER.H"
+#include "ATCONNCT.H"
+#include "ATHANGUP.H"
+#include "ATO.H"
+#include "ATNOCARR.H"
+#include "LINE.H"
+#include "ATINIT.H"
+#include "mSLOGGER.H" // for LOGTEXT untilities
+#include "ATIO.H" // For CATIO class
+#include "PHONE.H"
+#include <et_clsvr.h>
+#include "ATBASE.H"
+#include "Matstd.h" // For AT command string constants
+#include "set_cbst.h" // for CATSetCBST class
+#include "et_struct.h"
+
+_LIT(KFaxServerName,"FaxSvr.dll");
+
+
+//
+// CAcquireEntry class
+//
+CAcquireEntry* CAcquireEntry::NewL(const TTsyReqHandle aTsyReqHandle)
+//
+// Create new request entry
+//
+ {
+ return new(ELeave) CAcquireEntry(aTsyReqHandle);
+ }
+
+CAcquireEntry::CAcquireEntry(const TTsyReqHandle aTsyReqHandle)
+//
+// Constructor
+//
+ {
+ iTsyReqHandle=aTsyReqHandle;
+ }
+
+CAcquireEntry::~CAcquireEntry()
+//
+// Destructor
+//
+ {}
+
+void CAcquireEntry::Deque()
+//
+// Deque List
+//
+ {
+ iLink.Deque();
+ iLink.iPrev=iLink.iNext=NULL;
+ }
+
+CAcquireOwnerList::CAcquireOwnerList()
+ {}
+
+CAcquireOwnerList::~CAcquireOwnerList()
+ {}
+
+CAcquireOwnerList* CAcquireOwnerList::NewL()
+//
+// Static function to create new acquire owner list
+//
+ {
+ CAcquireOwnerList* self=new(ELeave) CAcquireOwnerList();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+void CAcquireOwnerList::ConstructL()
+ {
+ iAcquireList.SetOffset(_FOFF(CAcquireEntry,iLink));
+ }
+
+CAcquireEntry* CAcquireOwnerList::FindByTsyReqHandle(const TTsyReqHandle aTsyReqHandle)
+//
+// Searches for client interested in taking ownership of call, by its TsyReqHandle
+//
+ {
+ CAcquireEntry* entry;
+ TDblQueIter<CAcquireEntry> iter(iAcquireList);
+ while(entry = iter++, entry!=NULL)
+ {
+ if(entry->iTsyReqHandle==aTsyReqHandle)
+ return entry;
+ }
+ return NULL;
+ }
+
+void CAcquireOwnerList::Remove(CAcquireEntry* aEntry)
+ {
+ aEntry->Deque();
+ delete aEntry;
+ }
+
+//
+// CHeartbeatRunner - periodic class to count seconds from beginning of call
+//
+CHeartbeatRunner* CHeartbeatRunner::NewL(CCallHayes* aCallHayes,CNotifications* aNotificationStore)
+ {
+ CHeartbeatRunner* self=new (ELeave) CHeartbeatRunner(aCallHayes,aNotificationStore);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+CHeartbeatRunner::CHeartbeatRunner(CCallHayes* aCallHayes,CNotifications* aNotificationStore)
+ :iCallHayes(aCallHayes), iNotificationStore(aNotificationStore)
+ {}
+
+void CHeartbeatRunner::ConstructL()
+ {
+ iHeartbeat=CHeartbeat::NewL(0); // neutral priority
+ }
+
+CHeartbeatRunner::~CHeartbeatRunner()
+ {
+ if (iHeartbeat != NULL)
+ iHeartbeat->Cancel();
+ delete iHeartbeat;
+ }
+
+void CHeartbeatRunner::Start()
+ {
+ iStartTime.UniversalTime();
+ iHeartbeat->Start(ETwelveOClock,this);
+ }
+
+void CHeartbeatRunner::Stop()
+ {
+ iHeartbeat->Cancel();
+ iTicks=0;
+ }
+
+TTimeIntervalSeconds CHeartbeatRunner::CallDuration() const
+ {
+ TTimeIntervalSeconds duration(iTicks);
+ return duration;
+ }
+
+// private functions
+
+void CHeartbeatRunner::Beat()
+ {
+ iTicks++;
+ iNotificationStore->CheckNotification(iCallHayes,ETimePeriodElapsed);
+ }
+
+void CHeartbeatRunner::Synchronize()
+ {
+ TInt ticksMissed = 0;
+ TTime desiredTime = iStartTime + TTimeIntervalMicroSeconds(iTicks * KCallTimerInterval);
+ TTime currentTime; // set current time to now
+ currentTime.UniversalTime();
+ TTimeIntervalMicroSeconds missedTime = currentTime.MicroSecondsFrom(desiredTime);
+ // Calculate the ticks missed (quickly!)
+ TInt64 missedTimeInt = missedTime.Int64(); // convert the missed time interval to an Int64
+ ticksMissed = I64INT(missedTimeInt / KCallTimerInterval);
+ // The following loop increments the ticks missed by the same amount, but takes much longer
+ // while (desiredTime < currentTime)
+ // {
+ // desiredTime = desiredTime - TTimeIntervalMicroSeconds(iTickInterval);
+ // ticksMissed++;
+ // }
+ iTicks = iTicks + ticksMissed;
+ LOGTEXT3(_L8("Heartbeat function synchronising - from %d to %d"),iTicks-ticksMissed,iTicks);
+ if (ticksMissed!=0)
+ iNotificationStore->CheckNotification(iCallHayes,ETimePeriodElapsed);
+ }
+
+//
+// CCallHayes - General Call Functionality
+//
+void CCallHayes::CloseCall(TAny* aObj)
+//
+// Utility func for cleanup stack
+//
+ {
+ ((CObject*)aObj)->Close();
+ }
+
+CCallHayes::CCallHayes(CATIO* aIo,CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
+ : iPhoneGlobals(aPhoneGlobals),iIo(aIo),iInit(aInit)
+ {}
+
+void CCallHayes::ConstructL(const TName& aName)
+//
+// Initialise Call Information
+//
+ {
+ LOGTEXT(_L8("Entered CCallHayes::ConstructL()"));
+ iCallInfo.iCallName = aName;
+ iCallInfo.iBearerService.iBearerCaps = RCall::KBearerCapsCompressionUnknown | RCall::KBearerCapsProtocolUnknown;
+ iCallInfo.iBearerService.iBearerSpeed = RCall::EBearerDataUnknown;
+ iCallInfo.iHookStatus = RCall::EHookStatusOn;
+ iCallInfo.iClientPanicOccurred = ENoPanicOccurred;
+ // Read default call preferences from database
+ GetDefaultCallParams();
+ iCallInfo.iLoanedToClient = EFalse;
+ if (iPhoneGlobals->iPhoneStatus.iLineStatus == RCall::EStatusRinging)
+ {
+ iCallInfo.iMobileStatus = RMobileCall::EStatusRinging;
+ }
+ else
+ {
+ iCallInfo.iMobileStatus = RMobileCall::EStatusIdle;
+ }
+
+ iQuickInit=CATQuickInit::NewL(iIo,this,iPhoneGlobals);
+ iWaitForNoCarrier=CATWaitForNoCarrier::NewL(iIo,this,iPhoneGlobals);
+ iList=CAcquireOwnerList::NewL();
+ iCallTimer = CHeartbeatRunner::NewL(this,iPhoneGlobals->iNotificationStore);
+ LOGTEXT2(_L8("iCallTimer = %x"),iCallTimer);
+ }
+
+CCallHayes::~CCallHayes()
+ {
+ LOGTEXT(_L8("Entered CCallHayes destructor"));
+ if (Owner())
+ REINTERPRET_CAST(CLineHayes*,Owner())->RemoveCall(this);
+ iPhoneGlobals->iNotificationStore->RemoveClientFromLastEvents(this);
+ delete iWaitForNoCarrier;
+ delete iList;
+ delete iQuickInit;
+ delete iCallTimer;
+ }
+
+CTelObject::TReqMode CCallHayes::ReqModeL(const TInt aIpc)
+ {
+ TReqMode reqMode = CCallBase::ReqModeL(aIpc);
+ if ((reqMode & KReqModeFlowControlObeyed || aIpc==EEtelCallAnswer) && iPhoneGlobals->iPhoneStatus.iDataPortLoaned)
+ {
+ LOGTEXT2(_L8("ReqModeL Leaving with KErrInUse as data port is loaned (aIpc=%d)"),aIpc);
+ User::Leave(KErrInUse);
+ }
+ return reqMode;
+ }
+
+TInt CCallHayes::RegisterNotification(const TInt /*aIpc*/)
+ {
+ return KErrNone;
+ }
+TInt CCallHayes::DeregisterNotification(const TInt /*aIpc*/)
+ {
+ return KErrNone;
+ }
+
+
+void CCallHayes::Init()
+//
+// Only CPhoneHayes::Init() is implemented as that is called first
+//
+ {}
+
+
+TInt CCallHayes::NotifyCapsChange(const TTsyReqHandle aTsyReqHandle, RCall::TCaps* aCaps)
+ {
+ LOGTEXT(_L8("Call:\tCaps Change Notification lodged"));
+ iPhoneGlobals->iNotificationStore->RegisterNotification(ECallCaps,aTsyReqHandle,this,aCaps);
+ return KErrNone;
+ }
+
+TInt CCallHayes::NotifyCapsChangeCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ LOGTEXT(_L8("Call:\tCaps Change Notification cancelled"));
+ iPhoneGlobals->iNotificationStore->RemoveNotification(aTsyReqHandle);
+ return KErrNone;
+ }
+
+TInt CCallHayes::NotifyHookChange(const TTsyReqHandle aTsyReqHandle, RCall::THookStatus* aHookStatus)
+ {
+ LOGTEXT(_L8("Call:\tHook Change Notification lodged"));
+ iPhoneGlobals->iNotificationStore->RegisterNotification(ECallHookChange,aTsyReqHandle,this,aHookStatus);
+ return KErrNone;
+ }
+
+TInt CCallHayes::NotifyHookChangeCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ LOGTEXT(_L8("Call:\tHook Change Notification cancelled"));
+ iPhoneGlobals->iNotificationStore->RemoveNotification(aTsyReqHandle);
+ return KErrNone;
+ }
+
+TInt CCallHayes::NotifyStatusChange(const TTsyReqHandle aTsyReqHandle,RCall::TStatus* aStatus)
+ {
+ LOGTEXT(_L8("Call:\tStatus Change Notification lodged"));
+ iPhoneGlobals->iNotificationStore->RegisterNotification(ECallStatusChange,aTsyReqHandle,this,aStatus);
+ return KErrNone;
+ }
+
+TInt CCallHayes::NotifyStatusChangeCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ LOGTEXT(_L8("Call:\tStatus Change Notification cancelled"));
+ iPhoneGlobals->iNotificationStore->RemoveNotification(aTsyReqHandle);
+ return KErrNone;
+ }
+
+TInt CCallHayes::NotifyDurationChange(const TTsyReqHandle aTsyReqHandle,TTimeIntervalSeconds* aTime)
+ {
+ LOGTEXT(_L8("Call:\tDuration Change Notification lodged"));
+ iPhoneGlobals->iNotificationStore->RegisterNotification(ECallDurationChange,aTsyReqHandle,this,aTime);
+ return KErrNone;
+ }
+
+TInt CCallHayes::NotifyDurationChangeCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ LOGTEXT(_L8("Call:\tDuration Change Notification cancelled"));
+ iPhoneGlobals->iNotificationStore->RemoveNotification(aTsyReqHandle);
+ return KErrNone;
+ }
+
+TInt CCallHayes::GetInfo(const TTsyReqHandle aTsyReqHandle, RCall::TCallInfo* aCallInfo)
+ {
+ aCallInfo->iCallName = iCallInfo.iCallName;
+ aCallInfo->iStatus = GetCoreCallStatus();
+ aCallInfo->iHookStatus = iCallInfo.iHookStatus;
+ aCallInfo->iLineName = Owner()->Name();
+ GetCallDuration(aCallInfo->iDuration);
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+TInt CCallHayes::GetStatus(const TTsyReqHandle aTsyReqHandle, RCall::TStatus* aCallStatus)
+ {
+ LOGTEXT(_L8("Call:\tGetStatus() called"));
+ *aCallStatus = GetCoreCallStatus();
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+TInt CCallHayes::TransferOwnership(const TTsyReqHandle aTsyReqHandle)
+//
+// Transfer call ownership
+//
+ {
+ LOGTEXT(_L8("Call:\tTransferOwnership called"));
+ if (CheckOwnership(aTsyReqHandle)!=CCallBase::EOwnedTrue)
+ {
+ ReqCompleted(aTsyReqHandle,KErrEtelNotCallOwner);
+ return KErrNone;
+ }
+
+ if(iList->iAcquireList.IsEmpty()) // no one interested in this call !
+ {
+ ReqCompleted(aTsyReqHandle,KErrEtelNoClientInterestedInThisCall);
+ return KErrNone;
+ }
+
+ CAcquireEntry* entry=iList->iAcquireList.First();
+ if (entry) // someone interested in this call
+ {
+ LOGTEXT(_L8("Call:\tTransferOwnership successful"));
+ (void)SetOwnership(entry->iTsyReqHandle);
+ ReqCompleted(entry->iTsyReqHandle,KErrNone);
+ iList->Remove(entry);
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ }
+ return KErrNone;
+ }
+
+TInt CCallHayes::AcquireOwnership(const TTsyReqHandle aTsyReqHandle)
+//
+// Acquire call Ownership (server has already checked client does not own it)
+// If call is unowned and idle, this request is completed with CallNotActive.
+// A call must never be owned and idle concurrently.
+//
+ {
+ LOGTEXT(_L8("Call:\tAcquireOwnership called"));
+ if (CheckOwnership(aTsyReqHandle)==CCallBase::EOwnedUnowned)
+ {
+ LOGTEXT(_L8("Call:\tAcquireOwnership unsuccessful as call is not owned already"));
+ ReqCompleted(aTsyReqHandle,KErrEtelCallNotActive);
+ }
+ else
+ {
+ if(iList->iAcquireList.IsEmpty())
+ // List is empty. Client is the first one to request ownership of the call.
+ {
+ CAcquireEntry* entry=NULL;
+ TRAPD(err,entry=CAcquireEntry::NewL(aTsyReqHandle));
+ if(err==KErrNone)
+ iList->iAcquireList.AddLast(*entry);
+ else
+ return err;
+ }
+ else
+ // List is not empty. Another client has already requested to acquire ownership of the call.
+ // Only one client can be waiting to acquire ownership at any one time.
+ return KErrInUse;
+ }
+ return KErrNone;
+ }
+
+TInt CCallHayes::AcquireOwnershipCancel(const TTsyReqHandle aTsyReqHandle)
+//
+// Cancel Acquire call Ownership
+//
+ {
+ CAcquireEntry* entry=iList->FindByTsyReqHandle(aTsyReqHandle);
+ __ASSERT_ALWAYS(entry!=NULL,Panic(EAcquirerNotFound));
+ if (entry != NULL)
+ {
+ iList->Remove(entry);
+ ReqCompleted(aTsyReqHandle, KErrCancel);
+ }
+ else
+ {
+ ReqCompleted(aTsyReqHandle, KErrNotFound);
+ }
+ return KErrNone;
+ }
+
+TInt CCallHayes::GetBearerServiceInfo(const TTsyReqHandle aTsyReqHandle,RCall::TBearerService* aBearerService)
+ {
+ *aBearerService = iCallInfo.iBearerService;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+TInt CCallHayes::GetCallParams(const TTsyReqHandle aTsyReqHandle, TDes8* aParams)
+//
+// Call parameters are only set when connecting a call, so there have no meaning when a
+// call is not in progress.
+//
+ {
+ if (RMobileCall::EStatusIdle != iCallInfo.iMobileStatus &&
+ RMobileCall::EStatusUnknown != iCallInfo.iMobileStatus )
+ {
+ TPckg<RCall::TCallParams>* paramsPckg = (TPckg<RCall::TCallParams>*)aParams;
+ RCall::TCallParams& callparams = (*paramsPckg)();
+
+ //
+ // Configure basic TCallParams parameters
+ callparams.iSpeakerControl = iCallInfo.iSpeakerControl;
+ callparams.iSpeakerVolume = iCallInfo.iSpeakerVolume;
+ callparams.iInterval = iCallInfo.iInterval;
+ callparams.iWaitForDialTone = iCallInfo.iWaitForDialTone;
+
+ //
+ // Configure additional params as required
+ if(callparams.ExtensionId()==RMobileCall::KETelMobileCallParamsV1)
+ {
+ //
+ // Configure RMobileCall::TMobileCallParamsV1 parameters
+ RMobileCall::TMobileCallParamsV1Pckg* pckg = (RMobileCall::TMobileCallParamsV1Pckg*)aParams;
+ RMobileCall::TMobileCallParamsV1& params = (*pckg)();
+ params.iIdRestrict=iCallInfo.iCallParams.iIdRestrict;
+ params.iCug=iCallInfo.iCallParams.iCug;
+ params.iAutoRedial=iCallInfo.iCallParams.iAutoRedial;
+ }
+ else if(callparams.ExtensionId()==RMobileCall::KETelMobileDataCallParamsV1)
+ {
+ //
+ // Configure RMobileCall::TMobileDataCallParamsV1 parameters
+ RMobileCall::TMobileDataCallParamsV1Pckg* pckg = (RMobileCall::TMobileDataCallParamsV1Pckg*)aParams;
+ RMobileCall::TMobileDataCallParamsV1& params = (*pckg)();
+ params.iService=iCallInfo.iCallParams.iService;
+ params.iSpeed=iCallInfo.iCallParams.iSpeed;
+ params.iProtocol=iCallInfo.iCallParams.iProtocol;
+ params.iQoS=iCallInfo.iCallParams.iQoS;
+ params.iRLPVersion=iCallInfo.iCallParams.iRLPVersion;
+ params.iModemToMSWindowSize=iCallInfo.iCallParams.iModemToMSWindowSize;
+ params.iMSToModemWindowSize=iCallInfo.iCallParams.iMSToModemWindowSize;
+ params.iAckTimer=iCallInfo.iCallParams.iAckTimer;
+ params.iRetransmissionAttempts=iCallInfo.iCallParams.iRetransmissionAttempts;
+ params.iResequencingPeriod=iCallInfo.iCallParams.iResequencingPeriod;
+ params.iV42bisReq=iCallInfo.iCallParams.iV42bisReq;
+ params.iV42bisCodewordsNum=iCallInfo.iCallParams.iV42bisCodewordsNum;
+ params.iV42bisMaxStringLength=iCallInfo.iCallParams.iV42bisMaxStringLength;
+ }
+ else if(callparams.ExtensionId()==RMobileCall::KETelMobileHscsdCallParamsV1)
+ {
+ //
+ // Configure RMobileCall::TMobileHscsdCallParamsV1 parameters
+ RMobileCall::TMobileHscsdCallParamsV1Pckg* pckg = (RMobileCall::TMobileHscsdCallParamsV1Pckg*)aParams;
+ RMobileCall::TMobileHscsdCallParamsV1& params = (*pckg)();
+ params.iWantedAiur=iCallInfo.iCallParams.iWantedAiur;
+ params.iWantedRxTimeSlots=iCallInfo.iCallParams.iWantedRxTimeSlots;
+ params.iMaxTimeSlots=iCallInfo.iCallParams.iMaxTimeSlots;
+ params.iCodings=iCallInfo.iCallParams.iCodings;
+ params.iAsymmetry=iCallInfo.iCallParams.iAsymmetry;
+ params.iUserInitUpgrade=iCallInfo.iCallParams.iUserInitUpgrade;
+ }
+
+ //
+ // Complete the clients request
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ }
+ else
+ {
+ ReqCompleted(aTsyReqHandle,KErrUnknown);
+ }
+ return KErrNone;
+ }
+
+TInt CCallHayes::GetCallDuration(const TTsyReqHandle aTsyReqHandle, TTimeIntervalSeconds* aTime)
+ {
+ if ( RMobileCall::EStatusConnected != iCallInfo.iMobileStatus &&
+ RMobileCall::EStatusDisconnecting != iCallInfo.iMobileStatus)
+ {
+ ReqCompleted(aTsyReqHandle,KErrEtelCallNotActive);
+ return KErrNone;
+ }
+ *aTime = iCallTimer->CallDuration();
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+void CCallHayes::GetCallDuration(TTimeIntervalSeconds& aTime) const
+ {
+ aTime = iCallTimer->CallDuration();
+ }
+
+void CCallHayes::GetDefaultCallParams()
+ {
+ iPhoneGlobals->iConfiguration->GetIntervalPref(iCallInfo.iInterval);
+ iPhoneGlobals->iConfiguration->GetSpeakerSettingPref(iCallInfo.iSpeakerControl);
+ iPhoneGlobals->iConfiguration->GetSpeakerVolumePref(iCallInfo.iSpeakerVolume);
+ iPhoneGlobals->iConfiguration->GetWaitForDialTonePref(iCallInfo.iWaitForDialTone);
+ }
+
+void CCallHayes::SetCallParams(const TDesC8* aParams)
+ {
+ if ((*aParams).Length()==0)
+ // Always returns KErrNone
+ GetDefaultCallParams();
+ else
+ {
+ TPckg<RCall::TCallParams>* paramsPckg = (TPckg<RCall::TCallParams>*)aParams;
+ RCall::TCallParams& callparams = (*paramsPckg)();
+ iCallInfo.iSpeakerControl = callparams.iSpeakerControl;
+ iCallInfo.iSpeakerVolume = callparams.iSpeakerVolume;
+ iCallInfo.iInterval = callparams.iInterval;
+ iCallInfo.iWaitForDialTone = callparams.iWaitForDialTone;
+ }
+ }
+
+TInt CCallHayes::ValidateRequest(const TTsyReqHandle aTsyReqHandle, RCall::TStatus aLineStatus)
+//
+// Validating a request
+//
+ {
+ CCallBase::TCallOwnership owned = CheckOwnership(aTsyReqHandle);
+ if (owned==CCallBase::EOwnedFalse) // call owned by another client
+ {
+ return KErrEtelNotCallOwner;
+ }
+ if (iPhoneGlobals->iPhoneStatus.iLineStatus != aLineStatus)
+ {
+ if (aLineStatus==RCall::EStatusIdle)
+ // implies that this call is already active (assuming an owned call is
+ // an active call) or ringing or unknown
+ {
+ return KErrInUse;
+ }
+ else if (aLineStatus==RCall::EStatusRinging)
+ {
+ return KErrNotReady;
+ }
+ }
+ return KErrNone;
+ }
+
+
+RCall::TStatus CCallHayes::GetCoreCallStatus()
+ {
+ RCall::TStatus coreStatus;
+ if (iCallInfo.iMobileStatus <= RMobileCall::EStatusDisconnecting)
+ //coreStatus = static_cast<RCall::TStatus>(iCallInfo.iMobileStatus);
+ coreStatus = (RCall::TStatus)iCallInfo.iMobileStatus;
+ else
+ switch (iCallInfo.iMobileStatus)
+ {
+ case RMobileCall::EStatusReconnectPending:
+ case RMobileCall::EStatusHold:
+ coreStatus = RCall::EStatusConnected;
+ break;
+ case RMobileCall::EStatusWaitingAlternatingCallSwitch:
+ coreStatus = RCall::EStatusIdle;
+ break;
+ default:
+ coreStatus = RCall::EStatusUnknown;
+ break;
+ }
+ return coreStatus;
+ }
+
+TInt CCallHayes::ChangeCallStatus(RMobileCall::TMobileCallStatus aCallStatus)
+ {
+ if (iCallInfo.iMobileStatus != aCallStatus)
+ {
+ iCallInfo.iMobileStatus = aCallStatus;
+
+ if (aCallStatus == RMobileCall::EStatusIdle)
+ {
+ iCallInfo.iHookStatus = RCall::EHookStatusOn;
+ iPhoneGlobals->iNotificationStore->CheckNotification(this,EBecomeIdle);
+ }
+ else if (aCallStatus != RMobileCall::EStatusUnknown && aCallStatus != RMobileCall::EStatusRinging)
+ {
+ iCallInfo.iHookStatus = RCall::EHookStatusOff;
+ }
+ if (aCallStatus == RMobileCall::EStatusConnected)
+ {
+ iPhoneGlobals->iNotificationStore->CheckNotification(this,EConnected);
+ iIo->Cancel();
+ TCommConfig aConfigPckg;
+ TInt ret = iPhoneGlobals->iConfiguration->PortConfig(aConfigPckg,EConfigTypeConnect);
+ if (ret==KErrNone)
+ ret = iIo->ConfigurePort(aConfigPckg);
+// if (!(iIo->ReadPending()))
+// iIo->Read();
+ iCallInfo.iTimeCallBegan.UniversalTime();
+ return ret;
+ }
+ }
+ return KErrNone;
+ }
+
+void CCallHayes::ChangeLineStatus(RCall::TStatus aLineStatus)
+ {
+ iPhoneGlobals->iPhoneStatus.iLineStatus = aLineStatus;
+ }
+
+void CCallHayes::SetToIdle()
+ {
+ iWaitForNoCarrier->StopWait();
+ // Always returns KErrNone
+ (void)SetUnowned();
+ iPhoneGlobals->iPhoneStatus.iMode = RPhone::EModeIdle;
+ ChangeLineStatus(RCall::EStatusIdle); // line status should be changed first because
+ // ChangeCallStatus is the function which sends
+ // the new event to the Notification Handler,
+ // and this will complete both line and call status
+ // notifications, taking the new statuses from the
+ // CLineHayes and CCallHayes objects.
+ // EStatusIdle always results in KErrNone return value
+ (void)ChangeCallStatus(RMobileCall::EStatusIdle);
+ StopCallTicker();
+ }
+
+void CCallHayes::SetToIdleAndCompleteReq(TTsyReqHandle aTsyReqHandle,TInt aStatus)
+ {
+ SetToIdle();
+ ReqCompleted(aTsyReqHandle, aStatus);
+ }
+
+void CCallHayes::GetCallInfo(TCallInfoIndex* aCallInfoIndex)
+//
+// Copied field by field since TCallInfoTSY is different to TCallInfoIndex
+//
+ {
+ aCallInfoIndex->iInfo.iCallName = iCallInfo.iCallName;
+ aCallInfoIndex->iInfo.iStatus = GetCoreCallStatus();
+ aCallInfoIndex->iInfo.iCallCapsFlags = 0;
+ }
+
+TBool CCallHayes::CheckName(const TDesC& aName) const
+//
+// Return TRUE if name is the same as the name of this call
+ {
+ if (iCallInfo.iCallName.CompareF(aName))
+ return EFalse;
+ else
+ return ETrue;
+ }
+
+TCallInfoTSY* CCallHayes::CallInfo()
+ {
+ return &iCallInfo;
+ }
+
+void CCallHayes::StartCallTicker() const
+ {
+ iCallTimer->Start();
+ }
+
+void CCallHayes::StopCallTicker() const
+ {
+ iCallTimer->Stop();
+ }
+
+void CCallHayes::ResetIsForIncomingCall()
+ {
+ iIsForIncomingCall=EFalse;
+ }
+
+TBool CCallHayes::IsForIncomingCall() const
+ {
+ return iIsForIncomingCall;
+ }
+
+void CCallHayes::SetOwnedByTSY()
+ {
+ iIsOwnedByTSY=ETrue;
+ }
+
+void CCallHayes::SetUnownedByTSY()
+ {
+ iIsOwnedByTSY=EFalse;
+ }
+
+TBool CCallHayes::IsOwnedByTSY() const
+ {
+ return iIsOwnedByTSY;
+ }
+
+
+//
+// Functions which are supported in one line but not the other
+//
+TInt CCallHayes::LoanDataPort(const TTsyReqHandle,RCall::TCommPort*)
+ {
+ return KErrNotSupported;
+ }
+
+TInt CCallHayes::LoanDataPortCancel(const TTsyReqHandle)
+ {
+ return KErrNotSupported;
+ }
+
+TInt CCallHayes::RecoverDataPort(const TTsyReqHandle)
+ {
+ return KErrNotSupported;
+ }
+
+TInt CCallHayes::RecoverDataPortAndRelinquishOwnership()
+ {
+ return KErrNotSupported;
+ }
+
+TInt CCallHayes::GetFaxSettings(const TTsyReqHandle,RCall::TFaxSessionSettings*)
+ {
+ return KErrNotSupported;
+ }
+
+TInt CCallHayes::SetFaxSettings(const TTsyReqHandle,const RCall::TFaxSessionSettings*)
+ {
+ return KErrNotSupported;
+ }
+
+CTelObject* CCallHayes::OpenNewObjectByNameL(const TDesC& /*aName*/)
+ {
+ User::Leave(KErrNotSupported);
+ return NULL;
+ }
+
+CTelObject* CCallHayes::OpenNewObjectL(TDes& /*aNewName*/)
+ {
+ User::Leave(KErrNotSupported);
+ return NULL;
+ }
+
+TInt CCallHayes::CheckAndSetRegistrationParams(const TInt /*aIpc*/,const TDes8* /*aDes1*/,const TDes8* /*aDes2*/)
+ {
+ return KErrNone;
+ }
+
+TInt CCallHayes::ExtFunc(const TTsyReqHandle,const TInt, const TDataPackage&)
+//
+// Unsupported in this TSY
+//
+ {
+ return KErrNotSupported;
+ }
+
+/*
+ * CCallMobile class that implements Multimode ETel Mobile Call requests
+ */
+
+CCallMobile::CCallMobile(CATIO* aIo,CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
+ : CCallHayes(aIo, aInit, aPhoneGlobals)
+ {
+ }
+
+CCallMobile::~CCallMobile()
+ {
+ }
+
+CTelObject::TReqMode CCallMobile::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 EMobileCallGetMobileCallCaps:
+ case EMobileCallGetMobileCallStatus:
+ break;
+
+ case EMobileCallGetMobileDataCallCaps:
+ break;
+//
+// Multiple Completion Services with Immediate Server Repost
+// (Usually Notifications)
+//
+ case EMobileCallNotifyMobileCallStatusChange:
+ case EMobileCallNotifyMobileCallCapsChange:
+
+ ret=KReqModeMultipleCompletionEnabled | KReqModeRePostImmediately;
+ break;
+//
+//
+//
+ default:
+ ret=CCallHayes::ReqModeL(aIpc);
+ break;
+ }
+
+ return ret;
+ }
+
+
+TInt CCallMobile::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 EMobileCallNotifyMobileCallStatusChange:
+ case EMobileCallNotifyMobileCallCapsChange:
+ LOGTEXT(_L8("CCallMobile: Registered with 5 slots"));
+ numberOfSlots=5;
+ break;
+ default:
+ numberOfSlots = CCallBase::NumberOfSlotsL(aIpc);
+ break;
+ }
+ return numberOfSlots;
+ }
+
+
+TInt CCallMobile::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 EMobileCallGetMobileCallCaps:
+ return GetMobileCallCaps(aTsyReqHandle, aPackage.Des1n());
+
+ case EMobileCallGetMobileCallStatus:
+ return GetMobileCallStatus(aTsyReqHandle,
+ REINTERPRET_CAST(RMobileCall::TMobileCallStatus*,dataPtr));
+//
+// Multiple Completion Services with Immediate Server Repost
+// (Usually Notifications)
+//
+ case EMobileCallNotifyMobileCallStatusChange:
+ return NotifyMobileCallStatusChange(aTsyReqHandle,
+ REINTERPRET_CAST(RMobileCall::TMobileCallStatus*, dataPtr));
+
+ case EMobileCallNotifyMobileCallCapsChange:
+ return NotifyMobileCallCapsChange(aTsyReqHandle, aPackage.Des1n());
+
+//
+// Cancels
+//
+ case EMobileCallNotifyMobileCallStatusChangeCancel:
+ return NotifyMobileCallStatusChangeCancel(aTsyReqHandle);
+
+ case EMobileCallNotifyMobileCallCapsChangeCancel:
+ return NotifyMobileCallCapsChangeCancel(aTsyReqHandle);
+
+ default:
+ return KErrNotSupported;
+ }
+ }
+
+TInt CCallMobile::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 EMobileCallNotifyMobileCallStatusChange:
+ return NotifyMobileCallStatusChangeCancel(aTsyReqHandle);
+ case EMobileCallNotifyMobileCallCapsChange:
+ return NotifyMobileCallCapsChangeCancel(aTsyReqHandle);
+ default:
+ return CCallBase::CancelService(aIpc,aTsyReqHandle);
+ }
+ }
+
+TInt CCallMobile::GetMobileCallCaps(const TTsyReqHandle aTsyReqHandle, TDes8* aCaps)
+ {
+ LOGTEXT(_L8("CCallMobile: :GetMobileCallCaps called"));
+
+ RMobileCall::TMobileCallCapsV1Pckg *capsPckg = REINTERPRET_CAST(RMobileCall::TMobileCallCapsV1Pckg *,aCaps);
+ RMobileCall::TMobileCallCapsV1& caps = (*capsPckg)();
+ // Always returns KErrNone
+ (void)CollateCurrentMobileCaps(aTsyReqHandle, &caps.iCallControlCaps);
+ caps.iCallEventCaps=0; // no call events are supported
+
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+TInt CCallMobile::GetCaps(const TTsyReqHandle aTsyReqHandle,RCall::TCaps* aCallCaps)
+ {
+ (void)CollateCurrentCoreCaps(aTsyReqHandle, reinterpret_cast<TUint32*>(&aCallCaps->iFlags));
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+TBool CCallMobile::CollateCurrentMobileCaps(const TTsyReqHandle aTsyReqHandle, TUint32* aCallCaps)
+ {
+ CollateCoreCaps(aTsyReqHandle, aCallCaps);
+ if (iMobileCaps.iCallControlCaps != *aCallCaps)
+ {
+ iMobileCaps.iCallControlCaps = *aCallCaps;
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+TBool CCallMobile::CollateCurrentCoreCaps(const TTsyReqHandle aTsyReqHandle, TUint32* aCallCaps)
+ {
+ CollateCoreCaps(aTsyReqHandle, aCallCaps);
+ if (iCaps.iFlags != *aCallCaps)
+ {
+ iCaps.iFlags = *aCallCaps;
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+TInt CCallMobile::NotifyMobileCallCapsChange(const TTsyReqHandle aTsyReqHandle, TDes8* aCaps)
+ {
+ LOGTEXT(_L8("CCallMobile::NotifyMobileCallCapsChange lodged"));
+ iPhoneGlobals->iNotificationStore->RegisterNotification(ECallMobileCaps,aTsyReqHandle,this,aCaps);
+ return KErrNone;
+ }
+
+TInt CCallMobile::NotifyMobileCallCapsChangeCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ LOGTEXT(_L8("CCallMobile::NotifyMobileCallCapsChangeCancel called"));
+ iPhoneGlobals->iNotificationStore->RemoveNotification(aTsyReqHandle);
+ return KErrNone;
+ }
+
+TInt CCallMobile::GetMobileCallStatus(const TTsyReqHandle aTsyReqHandle,RMobileCall::TMobileCallStatus* aStatus)
+ {
+ LOGTEXT(_L8("CCallMobile::GetMobileCallStatus called"));
+ *aStatus=iCallInfo.iMobileStatus;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+TInt CCallMobile::NotifyMobileCallStatusChange(const TTsyReqHandle aTsyReqHandle,RMobileCall::TMobileCallStatus* aStatus)
+ {
+ LOGTEXT(_L8("CCallMobile::NotifyMobileCallStatusChange lodged"));
+ iPhoneGlobals->iNotificationStore->RegisterNotification(EMobileCallStatusChange,aTsyReqHandle,this,aStatus);
+ return KErrNone;
+ }
+
+TInt CCallMobile::NotifyMobileCallStatusChangeCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ LOGTEXT(_L8("CCallMobile::NotifyMobileCallStatusChangeCancel called"));
+ iPhoneGlobals->iNotificationStore->RemoveNotification(aTsyReqHandle);
+ return KErrNone;
+ }
+
+//
+// CCallMobileVoice - Voice Specific Call Functionality
+//
+
+CCallMobileVoice* CCallMobileVoice::NewL(CATIO* aATIO,CATInit* aInit,CPhoneGlobals* aPhoneGlobals,const TName& aName)
+ {
+ CCallMobileVoice* voiceCall=new(ELeave) CCallMobileVoice(aATIO,aInit,aPhoneGlobals);
+ TCleanupItem newCallVoiceHayesClose(CloseCall,voiceCall);
+ CleanupStack::PushL(newCallVoiceHayesClose);
+ voiceCall->ConstructL(aName);
+ CleanupStack::Pop();
+ return voiceCall;
+ }
+
+CCallMobileVoice::CCallMobileVoice(CATIO* aATIO,CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
+ : CCallMobile(aATIO,aInit,aPhoneGlobals)
+ {}
+
+void CCallMobileVoice::ConstructL(const TName& aName)
+ {
+ CCallHayes::ConstructL(aName);
+ iCallInfo.iLineOwnerName = KVoiceLineName;
+ iDialVoice=CATDialVoice::NewL(iIo,this,iInit,iPhoneGlobals);
+ iAnswerVoice=CATAnswerVoice::NewL(iIo,this,iInit,iPhoneGlobals);
+ iHangUpVoice=CATHangUpVoice::NewL(iIo,this,iInit,iPhoneGlobals);
+ }
+
+CCallMobileVoice::~CCallMobileVoice()
+//
+// Removes itself from array of calls in CLineMobileVoice
+//
+ {
+ delete iDialVoice;
+ delete iAnswerVoice;
+ delete iHangUpVoice;
+ }
+
+void CCallMobileVoice::CollateCoreCaps(const TTsyReqHandle /*aTsyReqHandle*/, TUint32* aCallCaps)
+ {
+ *aCallCaps = RCall::KCapsVoice;
+
+ // Voice calls can be manipulated by any client, not just owner so set as many caps as possible
+ if (iPhoneGlobals->iPhoneStatus.iModemDetected==RPhone::EDetectedPresent)
+ {
+ *aCallCaps |= (RCall::KCapsDial | RCall::KCapsConnect);
+
+ TInt ret=KErrNone;
+ if (!iIsForIncomingCall)
+ {
+ if (REINTERPRET_CAST(CPhoneHayes*,Owner()->Owner())->CheckForOutstandingAnswer())
+ ret=KErrEtelAnswerAlreadyOutstanding;
+ }
+ else
+ ret=KErrEtelAnswerAlreadyOutstanding;
+
+ if (ret==KErrNone && (iCallInfo.iMobileStatus==RMobileCall::EStatusIdle || iCallInfo.iMobileStatus==RMobileCall::EStatusRinging))
+ *aCallCaps |= RCall::KCapsAnswer;
+
+ if (iCallInfo.iMobileStatus==RMobileCall::EStatusConnected)
+ *aCallCaps |= RCall::KCapsHangUp;
+ }
+ }
+
+TInt CCallMobileVoice::Dial(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams,TDesC* aTelNumber)
+//
+// Dial a voice call
+//
+ {
+ SetCallParams(aCallParams);
+ LOGTEXT(_L8("VoiceCall:\tSubmitting Dial command for Voice call"));
+ if (iPhoneGlobals->iPhoneStatus.iLineStatus == RCall::EStatusIdle)
+ {
+ (void)SetOwnership(aTsyReqHandle);
+ iDialVoice->ExecuteCommand(aTsyReqHandle,aTelNumber,&iCallInfo);
+ return KErrNone;
+ }
+ else
+ {
+ return KErrInUse;
+ }
+ }
+
+TInt CCallMobileVoice::DialCancel(const TTsyReqHandle aTsyReqHandle)
+/**
+ * Cancel the dial request if possible
+ */
+ {
+ LOGTEXT(_L8("VoiceCall:\tSubmitting Cancel Dial command for Voice call"));
+ iDialVoice->CancelCommand(aTsyReqHandle);
+ return KErrNone;
+ }
+
+TInt CCallMobileVoice::AnswerIncomingCall(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams)
+/**
+ * If there is no waiting call, will wait for one and then answer it. If there is, it will
+ * answer immediately.
+ */
+ {
+ CCallBase::TCallOwnership owned = CheckOwnership(aTsyReqHandle);
+ TInt ret=KErrNone;
+ if (owned==CCallBase::EOwnedFalse) // call owned by another client
+ {
+ ret=KErrEtelNotCallOwner;
+ }
+ else
+ {
+ if (!iIsForIncomingCall)
+ {
+ if (REINTERPRET_CAST(CPhoneHayes*,Owner()->Owner())->CheckForOutstandingAnswer())
+ ret=KErrEtelAnswerAlreadyOutstanding;
+ }
+ else
+ ret=KErrEtelAnswerAlreadyOutstanding;
+ }
+ if (ret==KErrNone)
+ {
+ CLineHayes* line = STATIC_CAST(CLineHayes*,Owner());
+ STATIC_CAST(CPhoneHayes*,line->Owner())->CancelOtherRingingCall(line);
+ line->FreePreAllocCallIfNecessary();
+ SetCallParams(aCallParams);
+ if (iCallInfo.iMobileStatus==RMobileCall::EStatusRinging)
+ {
+ (void)SetOwnership(aTsyReqHandle);
+ LOGTEXT(_L8("VoiceCall:\tSubmitting Answer command"));
+ iAnswerVoice->ExecuteCommand(aTsyReqHandle,NULL,&iCallInfo);
+ }
+ else // This call is now a client-designated Incoming Call object.
+ {
+ iIsForIncomingCall=ETrue;
+ iAnswerTsyReqHandle = aTsyReqHandle;
+ }
+ return KErrNone;
+ }
+ ReqCompleted(aTsyReqHandle,ret);
+ return KErrNone;
+ }
+
+
+TInt CCallMobileVoice::AnswerIncomingCallCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ LOGTEXT(_L8("VoiceCall:\tSubmitting Cancel Answer command"));
+ if (iIsForIncomingCall)
+ {
+ iIsForIncomingCall=EFalse;
+ ReqCompleted(aTsyReqHandle,KErrCancel);
+ }
+ else
+ iAnswerVoice->CancelCommand(aTsyReqHandle);
+ return KErrNone;
+ }
+
+void CCallMobileVoice::AnswerImmediately()
+ {
+ (void)SetOwnership(iAnswerTsyReqHandle);
+ // EStatusRinging always results in KErrNone return value
+ (void) ChangeCallStatus(RMobileCall::EStatusRinging);
+ iPhoneGlobals->iNotificationStore->CheckNotification(this,ERingOccurred);
+ iIsForIncomingCall=EFalse;
+ // this must be after the check notification as CNotifications
+ // asks line for info about the call which Is For Incoming Call
+ LOGTEXT(_L8("VoiceCall:\tSubmitting Answer command"));
+ iAnswerVoice->ExecuteCommand(iAnswerTsyReqHandle,NULL,&iCallInfo);
+ }
+
+TInt CCallMobileVoice::Connect(const TTsyReqHandle aTsyReqHandle,const TDesC8* /*aCallParams*/)
+ {
+ ReqCompleted(aTsyReqHandle,KErrNotSupported);
+ return KErrNone;
+ }
+
+TInt CCallMobileVoice::ConnectCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ ReqCompleted(aTsyReqHandle,KErrNotSupported);
+ return KErrNone;
+ }
+
+TInt CCallMobileVoice::HangUp(const TTsyReqHandle aTsyReqHandle)
+ {
+ if (CheckOwnership(aTsyReqHandle)==CCallBase::EOwnedFalse)
+ {
+ ReqCompleted(aTsyReqHandle,KErrEtelNotCallOwner);
+ return KErrNone;
+ }
+ if ((iCallInfo.iMobileStatus!=RMobileCall::EStatusIdle) &&
+ (iCallInfo.iMobileStatus!=RMobileCall::EStatusDisconnecting))
+ {
+ LOGTEXT(_L8("VoiceCall:\tSubmitting Hang Up command"));
+ iHangUpVoice->ExecuteCommand(aTsyReqHandle,NULL,&iCallInfo);
+ return KErrNone;
+ }
+ else
+ {
+ // Call not in a state to be terminated - but return KErrNone
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+ }
+
+TInt CCallMobileVoice::HangUpCancel(const TTsyReqHandle aTsyReqHandle)
+//
+// Cancel the hang up command.
+//
+ {
+ LOGTEXT(_L8("VoiceCall:\tSubmitting Cancel Hang Up command"));
+ iHangUpVoice->Stop(aTsyReqHandle);
+ return KErrNone;
+ }
+
+TInt CCallMobileVoice::RelinquishOwnership()
+ {
+//
+// Called by server to tell TSY to either pass ownership on to another interested client
+// or hang up immediately. If call is currently connecting, RelinquishOwnershipComplete
+// will be called once cancelling has finished.
+//
+ LOGTEXT(_L8("VoiceCall:\tRelinquish Ownership"));
+ if(iList->iAcquireList.IsEmpty())
+ {
+ if (iDialVoice->IsPreConnectInProgress())
+ {
+ iCallInfo.iClientPanicOccurred = EPanicOccurredWithoutDataPortLoan;
+ return KErrNone;
+ }
+ switch(iCallInfo.iMobileStatus)
+ {
+ case RMobileCall::EStatusConnected:
+ iCallInfo.iClientPanicOccurred = EPanicOccurredWithoutDataPortLoan;
+ iHangUpVoice->ExecuteCommand(0, NULL, &iCallInfo);
+ break;
+ case RMobileCall::EStatusDialling:
+ case RMobileCall::EStatusConnecting:
+ case RMobileCall::EStatusAnswering:
+ case RMobileCall::EStatusDisconnecting:
+ iCallInfo.iClientPanicOccurred = EPanicOccurredWithoutDataPortLoan;
+ break;
+ default:
+ if (iPhoneGlobals->iPhoneStatus.iInitStatus==EPhoneInitialising)
+ iCallInfo.iClientPanicOccurred = EPanicOccurredWithoutDataPortLoan;
+ else
+ RelinquishOwnershipCompleted(KErrNone);
+ break;
+ }
+ return KErrNone;
+ }
+ CAcquireEntry* entry=iList->iAcquireList.First();
+ if (entry)
+ {
+ (void)SetOwnership(entry->iTsyReqHandle);
+ ReqCompleted(entry->iTsyReqHandle,KErrNone);
+ iList->Remove(entry);
+ }
+ RelinquishOwnershipCompleted(KErrNone);
+ return KErrNone;
+ }
+
+TInt CCallMobileVoice::RecoverDataPortAndRelinquishOwnership()
+ {
+ RecoverDataPortAndRelinquishOwnershipCompleted(KErrNotSupported);
+ return KErrNone;
+ }
+
+TInt CCallMobileVoice::LoanDataPort(const TTsyReqHandle aTsyReqHandle, RCall::TCommPort* /* aCommPort*/)
+ {
+ ReqCompleted(aTsyReqHandle,KErrNotSupported);
+ return KErrNone;
+ }
+
+TInt CCallMobileVoice::LoanDataPortCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ ReqCompleted(aTsyReqHandle,KErrNotSupported);
+ return KErrNone;
+ }
+
+TInt CCallMobileVoice::RecoverDataPort(const TTsyReqHandle aTsyReqHandle)
+ {
+ ReqCompleted(aTsyReqHandle,KErrNotSupported);
+ return KErrNone;
+ }
+
+
+//
+//
+// CCallMobileData - Data Specific Call Functionality
+//
+//
+
+CCallMobileData* CCallMobileData::NewL(CATIO* aATIO,CATInit* aInit,CPhoneGlobals* aPhoneGlobals,const TName& aName)
+ {
+ CCallMobileData* dataCall=new(ELeave) CCallMobileData(aATIO,aInit,aPhoneGlobals);
+ TCleanupItem newCallDataHayesClose(CloseCall,dataCall);
+ CleanupStack::PushL(newCallDataHayesClose);
+ dataCall->ConstructL(aName);
+ CleanupStack::Pop();
+ return dataCall;
+ }
+
+CCallMobileData::CCallMobileData(CATIO* aATIO,CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
+ : CCallMobile(aATIO,aInit,aPhoneGlobals)
+ {}
+
+void CCallMobileData::ConstructL(const TName& aName)
+ {
+ CCallHayes::ConstructL(aName);
+ iCallInfo.iLineOwnerName = KDataLineName;
+ iDialData=CATDialData::NewL(iIo,this,iInit,iPhoneGlobals);
+ iAnswerData=CATAnswerData::NewL(iIo,this,iInit,iPhoneGlobals);
+ iSetCBST=CATSetCBST::NewL(iIo,this,iInit,iPhoneGlobals);
+ iConnectData=CATConnectData::NewL(iIo,this,iInit,iPhoneGlobals);
+ iHangUpData=CATHangUpData::NewL(iIo,this,iInit,iPhoneGlobals);
+ iATSetToOnlineDataMode=CATSetToOnlineDataMode::NewL(iIo,this,iInit,iPhoneGlobals);
+ }
+
+CCallMobileData::~CCallMobileData()
+//
+// Removes itself from array of calls in CLineMobileData
+//
+ {
+ delete iDialData;
+ delete iSetCBST;
+ delete iAnswerData;
+ delete iConnectData;
+ delete iHangUpData;
+ delete iATSetToOnlineDataMode;
+ }
+
+TInt CCallMobileData::ExtFunc(const TTsyReqHandle aTsyReqHandle,const TInt aIpc,
+ const TDataPackage& aPackage)
+/**
+ * Process the IPC locally, otherwise delegate to our base class.
+ */
+ {
+ switch (aIpc)
+ {
+ case EMobileCallGetMobileDataCallCaps:
+ return GetMobileDataCallCaps(aTsyReqHandle, aPackage.Des1n());
+ default:
+ // Delegate the processing of the IPC to our base class
+ return CCallMobile::ExtFunc(aTsyReqHandle,aIpc,aPackage);
+ }
+ }
+
+
+TInt CCallMobileData::GetMobileDataCallCaps(const TTsyReqHandle aTsyReqHandle, TDes8* aCaps)
+ {
+ LOGTEXT(_L8("CCallMobileData::GetMobileDataCallCaps called"));
+
+ //
+ // This is a synchronous client request so this method must complete quickly.
+ // The call caps returned are those which were discovered during the
+ // intialisation of the TSY (see ATINIT.CPP).
+ TPckg<RMobileCall::TMobileCallDataCapsV1>* pckg = (TPckg<RMobileCall::TMobileCallDataCapsV1>*)aCaps;
+ RMobileCall::TMobileCallDataCapsV1& caps = (*pckg)();
+ caps=iPhoneGlobals->iCallDataCaps;
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+void CCallMobileData::CollateCoreCaps(const TTsyReqHandle aTsyReqHandle, TUint32* aCallCaps)
+ {
+ *aCallCaps = RCall::KCapsData;
+ if (iPhoneGlobals->iPhoneStatus.iModemDetected==RPhone::EDetectedPresent)
+ {
+ CCallBase::TCallOwnership owner = CheckOwnership(aTsyReqHandle);
+ if (ValidateRequest(aTsyReqHandle,RCall::EStatusIdle)==KErrNone)
+ *aCallCaps |= (RCall::KCapsDial | RCall::KCapsConnect);
+ TInt ret=KErrNone;
+ if (owner==CCallBase::EOwnedFalse) // call owned by another client
+ ret=KErrEtelNotCallOwner;
+ else
+ {
+ if (!iIsForIncomingCall)
+ {
+ if (REINTERPRET_CAST(CPhoneHayes*,Owner()->Owner())->CheckForOutstandingAnswer())
+ ret=KErrEtelAnswerAlreadyOutstanding;
+ }
+ else
+ ret=KErrEtelAnswerAlreadyOutstanding;
+ }
+ if (ret==KErrNone && (iCallInfo.iMobileStatus==RMobileCall::EStatusIdle || iCallInfo.iMobileStatus==RMobileCall::EStatusRinging))
+ *aCallCaps |= RCall::KCapsAnswer;
+ if ((owner==CCallBase::EOwnedTrue || owner==CCallBase::EOwnedPriorityClient)
+ && iCallInfo.iMobileStatus==RMobileCall::EStatusConnected)
+ {
+ *aCallCaps |= RCall::KCapsHangUp;
+ if (iCallInfo.iLoanedToClient==EFalse)
+ *aCallCaps |= RCall::KCapsLoanDataPort;
+ else
+ *aCallCaps |= RCall::KCapsRecoverDataPort;
+ }
+ }
+ }
+
+TInt CCallMobileData::AssembleCBSTSetString(TBuf8<KGenericBufferSize>& aTxBuffer)
+/**
+ * This funciton assembles a +CBST= string ready to be sent to the modem using
+ * the values from CCallHayes::iCallInfo.
+ * This utility funciton is used by objects created and owned by this class.
+ * This has been done to reduce code size.
+ * @return KErrNone if and only if CBST string assembled
+ */
+ {
+ TInt ret(KErrNone); // Return value of this function
+
+ TInt speed(0); // these are the names that etsi use
+ TInt name(0); // these are the names that etsi use
+ TInt ce(0); // these are the names that etsi use
+ TBool speedSet(ETrue);
+ TBool nameSet(ETrue);
+ TBool ceSet(ETrue);
+
+ switch (iCallInfo.iCallParams.iService)
+ {
+ case RMobileCall::EServiceDataCircuitAsync:
+ name = 0;
+ break;
+ case RMobileCall::EServiceDataCircuitAsyncRdi:
+ name = 4;
+ break;
+ case RMobileCall::EServiceDataCircuitSync:
+ name = 1;
+ break;
+ case RMobileCall::EServiceDataCircuitSyncRdi:
+ name = 5;
+ break;
+ case RMobileCall::EServicePADAsyncUDI:
+ name = 2;
+ break;
+ case RMobileCall::EServicePADAsyncRDI:
+ name = 6;
+ break;
+ case RMobileCall::EServicePacketAccessSyncUDI:
+ name = 3;
+ break;
+ case RMobileCall::EServicePacketAccessSyncRDI:
+ name = 7;
+ break;
+ case RMobileCall::EServiceUnspecified: // taking the default value of 0
+ default:
+ nameSet=EFalse;
+ break;
+ }
+
+ switch(iCallInfo.iCallParams.iQoS)
+ {
+ case RMobileCall::EQoSTransparent:
+ ce = 0;
+ break;
+ case RMobileCall::EQosTransparentPreferred:
+ ce = 2;
+ break;
+ case RMobileCall::EQoSNonTransparent:
+ ce = 1;
+ break;
+ case RMobileCall::EQosNonTransparentPreferred:
+ ce = 3;
+ break;
+ case RMobileCall::EQoSUnspecified:
+ default:
+ ceSet=EFalse;
+ break;
+ }
+
+ switch(iCallInfo.iCallParams.iSpeed)
+ {
+ case RMobileCall::ESpeedAutobauding:
+ speed = 0;
+ break;
+
+ case RMobileCall::ESpeed2400:
+ {
+ if (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV22bis)
+ speed = 4;
+ else if (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV120)
+ speed = 36;
+ else if ((iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV110) ||
+ (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolX31FlagStuffing))
+ speed = 68;
+ else
+ speedSet=EFalse;
+ break;
+ }
+ case RMobileCall::ESpeed4800:
+ {
+ if (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV32)
+ speed = 6;
+ else if (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV120)
+ speed = 38;
+ else if ((iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV110) ||
+ (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolX31FlagStuffing))
+ speed = 70;
+ else
+ speedSet=EFalse;
+ break;
+ }
+ case RMobileCall::ESpeed9600:
+ {
+ if (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV32)
+ speed = 7;
+ else if (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV34)
+ speed = 12;
+ else if (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV120)
+ speed = 39;
+ else if ((iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV110) ||
+ (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolX31FlagStuffing))
+ speed = 71;
+ else
+ speedSet=EFalse;
+ break;
+ }
+ case RMobileCall::ESpeed14400:
+ {
+ if (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV34)
+ speed = 14;
+ else if (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV120)
+ speed = 43;
+ else if ((iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV110) ||
+ (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolX31FlagStuffing))
+ speed = 75;
+ else
+ speedSet=EFalse;
+ break;
+ }
+ case RMobileCall::ESpeed19200:
+ {
+ if (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV34)
+ speed = 15;
+ else if (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV120)
+ speed = 47;
+ else if ((iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV110) ||
+ (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolX31FlagStuffing))
+ speed = 79;
+ else
+ speedSet=EFalse;
+ break;
+ }
+ case RMobileCall::ESpeed28800:
+ {
+ if (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV34)
+ speed = 16;
+ else if (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV120)
+ speed = 48;
+ else if ((iCallInfo.iCallParams.iProtocol ==RMobileCall:: EProtocolV110) ||
+ (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolX31FlagStuffing))
+ speed = 80;
+ else
+ speedSet=EFalse;
+ break;
+ }
+ case RMobileCall::ESpeed38400:
+ {
+ if ((iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV110) ||
+ (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolX31FlagStuffing))
+ speed = 81;
+ else if (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV120)
+ speed = 49;
+ else
+ speedSet=EFalse;
+ break;
+ }
+ case RMobileCall::ESpeed48000:
+ if (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV120)
+ speed = 50;
+ else if ((iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV110) ||
+ (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolX31FlagStuffing))
+ speed = 82;
+ else
+ speedSet=EFalse;
+ break;
+ case RMobileCall::ESpeed56000:
+ if (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV120)
+ speed = 51;
+ else if ((iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolV110) ||
+ (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolX31FlagStuffing))
+ speed = 83;
+ else if (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolBitTransparent)
+ speed = 115;
+ else
+ speedSet=EFalse;
+ break;
+ case RMobileCall::ESpeed64000:
+ if (iCallInfo.iCallParams.iProtocol == RMobileCall::EProtocolBitTransparent)
+ speed = 116;
+ else
+ speedSet=EFalse;
+ break;
+
+ case RMobileCall::ESpeed33600: // this baud rate is not currently used in the etsi table
+ case RMobileCall::ESpeedUnspecified:
+ default:
+ speedSet=EFalse;
+ break;
+ }
+
+ //
+ // Try to assemble as much of the +CBST= command as we can.
+ // If we do not have a <speed> value we can not send the command.
+ // If we do not have a <ce> value then we can send a command giving only <speed> and <name>.
+ // etc...
+ if(speedSet)
+ {
+ aTxBuffer.Zero(); // Clear tx buffer
+
+ // Append +CBST= and the <speed> parameter
+ aTxBuffer.Append(KDataCallBearerServiceType);
+ aTxBuffer.AppendNum(speed);
+
+ if(nameSet)
+ {
+ // Append the <name> parameter
+ aTxBuffer.Append(TChar(','));
+ aTxBuffer.AppendNum(name);
+
+ if(ceSet)
+ {
+ // Append the <ce> parameter
+ aTxBuffer.Append(TChar(','));
+ aTxBuffer.AppendNum(ce);
+ }
+ }
+
+ // Append final \r char to AT command
+ aTxBuffer.Append(TChar('\r'));
+ }
+ else
+ {
+ // We have not have enough info to create a +CBST= string
+ ret=KErrArgument;
+ }
+
+ return ret;
+ }
+
+
+
+TInt CCallMobileData::Dial(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams,TDesC* aTelNumber)
+//
+// Dial a data call
+//
+ {
+ TInt ret(KErrNone);
+
+ SetDataCallParams(aCallParams);
+
+ ret=ValidateRequest(aTsyReqHandle,RCall::EStatusIdle);
+ if (ret==KErrNone)
+ {
+ (void)SetOwnership(aTsyReqHandle);
+ LOGTEXT(_L8("DataCall:\tSubmitting Dial command for Data call"));
+ iDialData->ExecuteCommand(aTsyReqHandle,aTelNumber,&iCallInfo);
+ }
+ else
+ ReqCompleted(aTsyReqHandle,ret); // An error occurred
+
+ return KErrNone; // Real return code is returned to client thru request completion
+ }
+
+
+TInt CCallMobileData::DialCancel(const TTsyReqHandle aTsyReqHandle)
+//
+// Cancel the dial request if possible
+//
+ {
+ LOGTEXT(_L8("DataCall:\tSubmitting Cancel Dial command for Data call"));
+ iDialData->CancelCommand(aTsyReqHandle);
+ return KErrNone;
+ }
+
+
+void CCallMobileData::SetDataCallParams(const TDesC8* aCallParams)
+/**
+ * Utility function which unpacks the call parameters supplied by the client
+ * and saves their values in iPhoneGlobals.
+ * If the client did not supply parameters then default ones are used.
+ */
+ {
+ if(aCallParams->Length()==0)
+ {
+ //
+ // Client did not supply parameters, so we use default ones
+ LOGTEXT(_L8("CCallMobileData::SetDataCallParams Using default parameters"));
+ CCallHayes::SetCallParams(aCallParams);
+
+ //
+ // Ensure the speed parameter is undefined so that we prevent the
+ // +CBST=... command being sent to the phone when dialling a CSD data call.
+ iCallInfo.iCallParams.iService = RMobileCall::EServiceUnspecified;
+ }
+ else
+ {
+ //
+ // Use call parameters that client supplied us
+ LOGTEXT(_L8("CCallMobileData::SetDataCallParams Using clients parameters"));
+ RCall::TCallParamsPckg* paramsPckgV1 = (RCall::TCallParamsPckg*)aCallParams;
+ RCall::TCallParams& paramsV1 = (*paramsPckgV1)();
+
+ CCallHayes::SetCallParams(aCallParams);
+ if (paramsV1.ExtensionId()==RMobileCall::KETelMobileCallParamsV1)
+ {
+ RMobileCall::TMobileCallParamsV1Pckg* mmParamsPckgV1 = (RMobileCall::TMobileCallParamsV1Pckg*)aCallParams;
+ RMobileCall::TMobileCallParamsV1& mmParamsV1 = (*mmParamsPckgV1)();
+ iCallInfo.iCallParams.iIdRestrict = mmParamsV1.iIdRestrict;
+ iCallInfo.iCallParams.iCug = mmParamsV1.iCug;
+ iCallInfo.iCallParams.iAutoRedial = mmParamsV1.iAutoRedial;
+ }
+
+ if((paramsV1.ExtensionId()==RMobileCall::KETelMobileDataCallParamsV1) ||
+ (paramsV1.ExtensionId()==RMobileCall::KETelMobileHscsdCallParamsV1))
+ {
+ RMobileCall::TMobileDataCallParamsV1Pckg* dataParamsPckgV1 = (RMobileCall::TMobileDataCallParamsV1Pckg*)aCallParams;
+ RMobileCall::TMobileDataCallParamsV1& dataParamsV1 = (*dataParamsPckgV1)();
+ iCallInfo.iCallParams.iService=dataParamsV1.iService;
+ iCallInfo.iCallParams.iSpeed=dataParamsV1.iSpeed;
+ iCallInfo.iCallParams.iProtocol=dataParamsV1.iProtocol;
+ iCallInfo.iCallParams.iQoS=dataParamsV1.iQoS;
+ iCallInfo.iCallParams.iRLPVersion=dataParamsV1.iRLPVersion;
+ iCallInfo.iCallParams.iModemToMSWindowSize=dataParamsV1.iModemToMSWindowSize;
+ iCallInfo.iCallParams.iMSToModemWindowSize=dataParamsV1.iMSToModemWindowSize;
+ iCallInfo.iCallParams.iAckTimer=dataParamsV1.iAckTimer;
+ iCallInfo.iCallParams.iRetransmissionAttempts=dataParamsV1.iRetransmissionAttempts;
+ iCallInfo.iCallParams.iResequencingPeriod=dataParamsV1.iResequencingPeriod;
+ iCallInfo.iCallParams.iV42bisReq=dataParamsV1.iV42bisReq;
+ iCallInfo.iCallParams.iV42bisCodewordsNum=dataParamsV1.iV42bisCodewordsNum;
+ iCallInfo.iCallParams.iV42bisMaxStringLength=dataParamsV1.iV42bisMaxStringLength;
+ }
+
+ if (paramsV1.ExtensionId()==RMobileCall::KETelMobileHscsdCallParamsV1)
+ {
+ RMobileCall::TMobileHscsdCallParamsV1Pckg* hscsdParamsPckgV1 = (RMobileCall::TMobileHscsdCallParamsV1Pckg*)aCallParams;
+ RMobileCall::TMobileHscsdCallParamsV1& hscsdParamsV1 = (*hscsdParamsPckgV1)();
+ iCallInfo.iCallParams.iWantedAiur = hscsdParamsV1.iWantedAiur;
+ iCallInfo.iCallParams.iWantedRxTimeSlots = hscsdParamsV1.iWantedRxTimeSlots;
+ iCallInfo.iCallParams.iMaxTimeSlots = hscsdParamsV1.iMaxTimeSlots;
+ iCallInfo.iCallParams.iCodings = hscsdParamsV1.iCodings;
+ iCallInfo.iCallParams.iAsymmetry = hscsdParamsV1.iAsymmetry;
+ iCallInfo.iCallParams.iUserInitUpgrade = hscsdParamsV1.iUserInitUpgrade;
+ }
+ }
+ }
+
+TInt CCallMobileData::AnswerIncomingCall(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams)
+/**
+ * If there is no waiting call, will wait for one and then answer it.
+ * If there is a waiting call, will answer immediatly.
+ * Regardless of if there is a waiting call or not, the +CBST= command is sent immediatly.
+ */
+ {
+ const CCallBase::TCallOwnership owned = CheckOwnership(aTsyReqHandle);
+ TInt ret=KErrNone;
+ if (owned==CCallBase::EOwnedFalse) // call owned by another client
+ {
+ ret=KErrEtelNotCallOwner;
+ }
+ else
+ {
+ if (!iIsForIncomingCall)
+ {
+ if (REINTERPRET_CAST(CPhoneHayes*,Owner()->Owner())->CheckForOutstandingAnswer())
+ ret=KErrEtelAnswerAlreadyOutstanding;
+ }
+ else
+ ret=KErrEtelAnswerAlreadyOutstanding;
+ }
+
+ if (ret==KErrNone)
+ {
+ CLineHayes* line = STATIC_CAST(CLineHayes*,Owner());
+ STATIC_CAST(CPhoneHayes*,line->Owner())->CancelOtherRingingCall(line);
+ line->FreePreAllocCallIfNecessary();
+ SetDataCallParams(aCallParams);
+ if (iCallInfo.iMobileStatus==RMobileCall::EStatusRinging)
+ {
+ (void)SetOwnership(aTsyReqHandle);
+ LOGTEXT(_L8("DataCall:\tSubmitting Answer command"));
+
+ // Start the 'send CBST to phone' AT machine and pass the
+ // CATAnswerData object, so that the call is answered after
+ // the CBST is sent.
+ iSetCBST->ExecuteCommand(aTsyReqHandle,iAnswerData,&iCallInfo);
+ }
+ else // This call is now a client-designated Incoming Call object.
+ {
+ iIsForIncomingCall=ETrue;
+ iAnswerTsyReqHandle = aTsyReqHandle;
+
+ // Start the 'send CBST to phone' AT machine. This state machine
+ // will not complete any client request.
+ iSetCBST->ExecuteCommand(aTsyReqHandle,NULL,&iCallInfo);
+ }
+ return KErrNone;
+ }
+
+ ReqCompleted(aTsyReqHandle,ret);
+ return KErrNone;
+ }
+
+
+TInt CCallMobileData::AnswerIncomingCallCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ LOGTEXT(_L8("DataCall:\tSubmitting Cancel Answer command"));
+ if (iIsForIncomingCall)
+ {
+ iIsForIncomingCall=EFalse;
+ ReqCompleted(aTsyReqHandle,KErrCancel);
+ }
+ else
+ iAnswerData->CancelCommand(aTsyReqHandle);
+ return KErrNone;
+ }
+
+void CCallMobileData::AnswerImmediately()
+ {
+ (void)SetOwnership(iAnswerTsyReqHandle);
+ // EStatusRinging always results in KErrNone return
+ (void) ChangeCallStatus(RMobileCall::EStatusRinging); // new 14/1/99
+ iPhoneGlobals->iNotificationStore->CheckNotification(this,ERingOccurred);
+ iIsForIncomingCall=EFalse; // this must be after the check notification as CNotifications
+ // asks line for info about the call which Is For Incoming Call
+ LOGTEXT(_L8("DataCall:\tSubmitting Answer command"));
+ iAnswerData->ExecuteCommand(iAnswerTsyReqHandle,NULL,&iCallInfo);
+ }
+
+TInt CCallMobileData::Connect(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams)
+//
+// Connect to an already dialled call
+//
+ {
+ TInt ret = ValidateRequest(aTsyReqHandle,RCall::EStatusIdle);
+ if (ret==KErrNone)
+ {
+ (void)SetOwnership(aTsyReqHandle);
+ SetCallParams(aCallParams);
+ LOGTEXT(_L8("DataCall:\tSubmitting Immediate Connect command"));
+ iConnectData->ExecuteCommand(aTsyReqHandle,NULL,&iCallInfo);
+ }
+ else
+ ReqCompleted(aTsyReqHandle,ret);
+ return KErrNone;
+ }
+
+TInt CCallMobileData::ConnectCancel(const TTsyReqHandle aTsyReqHandle)
+//
+// Cancel immediate connect command
+//
+ {
+ LOGTEXT(_L8("DataCall:\tSubmitting Cancel Connect command"));
+ iConnectData->CancelCommand(aTsyReqHandle);
+ return KErrNone;
+ }
+
+TInt CCallMobileData::HangUp(const TTsyReqHandle aTsyReqHandle)
+//
+// Terminate a data call. If someone else owns call complete with error, but if no-one owns
+// it send an ATH anyway, as the connection may have failed and the user wants to ensure
+// call has hung up. Call Start() instead of ExecuteCommand() because there is no need to
+// initialise before doing this or to send the escape sequence - the hang up sequence drops
+// DTR anyway.
+//
+ {
+ if (CheckOwnership(aTsyReqHandle)==CCallBase::EOwnedFalse)
+ {
+ ReqCompleted(aTsyReqHandle,KErrEtelNotCallOwner);
+ return KErrNone;
+ }
+ if ((iCallInfo.iMobileStatus!=RMobileCall::EStatusIdle) &&
+ (iCallInfo.iMobileStatus!=RMobileCall::EStatusDisconnecting))
+ {
+ LOGTEXT(_L8("DataCall:\tSubmitting Hang Up command"));
+ iHangUpData->ExecuteCommand(aTsyReqHandle,NULL,&iCallInfo);
+ return KErrNone;
+ }
+ else
+ {
+ // Call not in a state to be terminated - but return KErrNone
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+ }
+
+TInt CCallMobileData::HangUpCancel(const TTsyReqHandle aTsyReqHandle)
+//
+// Cancel the hang up command.
+//
+ {
+ LOGTEXT(_L8("DataCall:\tSubmitting Cancel Hang Up command"));
+ iHangUpData->Stop(aTsyReqHandle);
+ return KErrNone;
+ }
+
+TInt CCallMobileData::RelinquishOwnership()
+//
+// Called by server to tell TSY to either pass ownership on to another interested client
+// or hang up immediately. If call is currently connecting, RelinquishOwnershipComplete
+// will be called once cancelling has finished.
+//
+ {
+ LOGTEXT(_L8("DataCall:\tRelinquish Ownership"));
+ if(iList->iAcquireList.IsEmpty())
+ {
+ if (iDialData->IsPreConnectInProgress() ||
+ iConnectData->IsPreConnectInProgress() ||
+ iAnswerData->IsPreConnectInProgress())
+ {
+ iCallInfo.iClientPanicOccurred = EPanicOccurredWithoutDataPortLoan;
+ return KErrNone;
+ }
+ switch(iCallInfo.iMobileStatus)
+ {
+ case RMobileCall::EStatusConnected:
+ iCallInfo.iClientPanicOccurred = EPanicOccurredWithoutDataPortLoan;
+ //iHangUpData->ExecuteCommand(0,NULL,&iCallInfo);
+ iQuickInit->CancelAndHangUp(&iCallInfo,iHangUpData);
+ break;
+ case RMobileCall::EStatusDialling:
+ case RMobileCall::EStatusConnecting:
+ case RMobileCall::EStatusAnswering:
+ case RMobileCall::EStatusDisconnecting:
+ iCallInfo.iClientPanicOccurred = EPanicOccurredWithoutDataPortLoan;
+ break;
+ default:
+ if (iPhoneGlobals->iPhoneStatus.iInitStatus==EPhoneInitialising)
+ iCallInfo.iClientPanicOccurred = EPanicOccurredWithoutDataPortLoan;
+ else
+ RelinquishOwnershipCompleted(KErrNone);
+ break;
+ }
+ return KErrNone;
+ }
+ CAcquireEntry* entry=iList->iAcquireList.First();
+ if (entry)
+ {
+ (void)SetOwnership(entry->iTsyReqHandle);
+ ReqCompleted(entry->iTsyReqHandle,KErrNone);
+ iList->Remove(entry);
+ }
+ RelinquishOwnershipCompleted(KErrNone);
+ return KErrNone;
+ }
+
+TInt CCallMobileData::RecoverDataPortAndRelinquishOwnership()
+//
+// Called by server to tell TSY to either pass ownership on to another interested client
+// after regaining control of the port and performing a swift initialisation,
+// or hang up immediately
+//
+ {
+ LOGTEXT(_L8("DataPort Recover and Relinquish Ownership"));
+ iCallInfo.iLoanedToClient=EFalse;
+ iPhoneGlobals->iPhoneStatus.iDataPortLoaned = EFalse;
+ if(iList->iAcquireList.IsEmpty())
+ {
+ (void)SetUnowned();
+ iCallInfo.iClientPanicOccurred = EPanicOccurredDuringDataPortLoan;
+ iIo->Read();
+ iHangUpData->ExecuteCommand(0,NULL,&iCallInfo);
+ return KErrNone;
+ }
+ CAcquireEntry* entry=iList->iAcquireList.First();
+ if (entry)
+ {
+ (void)SetOwnership(entry->iTsyReqHandle);
+ ReqCompleted(entry->iTsyReqHandle,KErrNone);
+ iList->Remove(entry);
+ iQuickInit->StartQuickInit();
+ }
+ RecoverDataPortAndRelinquishOwnershipCompleted(KErrNone);
+ return KErrNone;
+ }
+
+TInt CCallMobileData::LoanDataPort(const TTsyReqHandle aTsyReqHandle, RCall::TCommPort* aCommPort)
+//
+// Get the port info
+//
+ {
+ LOGTEXT(_L8(" DataPort Loan"));
+ if (CheckOwnership(aTsyReqHandle)!=CCallBase::EOwnedTrue)
+ {
+ ReqCompleted(aTsyReqHandle,KErrEtelNotCallOwner);
+ return KErrNone;
+ }
+ if (iCallInfo.iMobileStatus != RMobileCall::EStatusConnected)
+ {
+ ReqCompleted(aTsyReqHandle,KErrEtelCallNotActive);
+ return KErrNone;
+ }
+ TInt ret = iPhoneGlobals->iConfiguration->ConfigModemString(TPtrC(KCDTypeNameCsyName),aCommPort->iCsy);
+ if (!ret)
+ {
+ ret = iPhoneGlobals->iConfiguration->ConfigModemString(TPtrC(KCDTypeNamePortName),aCommPort->iPort);
+ }
+ if (ret)
+ {
+ ReqCompleted(aTsyReqHandle,ret);
+ return KErrNone;
+ }
+ iCallInfo.iLoanedToClient = ETrue;
+ iPhoneGlobals->iPhoneStatus.iDataPortLoaned = ETrue;
+ iPhoneGlobals->iNotificationStore->CheckNotification(this,EDataPortLoaned);
+ iWaitForNoCarrier->StopWait();
+ if (iPhoneGlobals->iPhoneStatus.iMode==RPhone::EModeOnlineCommand)
+ iATSetToOnlineDataMode->ExecuteCommand(aTsyReqHandle,NULL,&iCallInfo);
+ else
+ {
+ iIo->Cancel();
+ TCommConfig aConfigPckg;
+ TInt ret = iPhoneGlobals->iConfiguration->PortConfig(aConfigPckg,EConfigTypeFull);
+ if (ret==KErrNone)
+ ret = iIo->ConfigurePort(aConfigPckg);
+ ReqCompleted(aTsyReqHandle,ret);
+ }
+ return KErrNone;
+ }
+
+TInt CCallMobileData::LoanDataPortCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ iATSetToOnlineDataMode->CancelCommand(aTsyReqHandle);
+ return KErrNone;
+ }
+
+TInt CCallMobileData::RecoverDataPort(const TTsyReqHandle aTsyReqHandle)
+//
+// Take back control of data port
+// Check that call had been loaned to client
+//
+ {
+ if (iCallInfo.iLoanedToClient==EFalse)
+ {
+ ReqCompleted(aTsyReqHandle,KErrEtelPortNotLoanedToClient);
+ return KErrNone;
+ }
+ TCallOwnership owner = CheckOwnership(aTsyReqHandle);
+ if (owner!=CCallBase::EOwnedTrue && owner!=CCallBase::EOwnedPriorityClient)
+ {
+ ReqCompleted(aTsyReqHandle,KErrEtelNotCallOwner);
+ return KErrNone;
+ }
+ LOGTEXT(_L8("DataPort Recover"));
+ iCallInfo.iLoanedToClient=EFalse;
+ iPhoneGlobals->iPhoneStatus.iDataPortLoaned = EFalse;
+ LOGTEXT2(_L8("Comm signals : %x"),iIo->Signals());
+ iIo->ResetReadAndWriteBuffers(); // in case client has left RxBuffer non-empty
+ LOGTEXT2(_L8("Comm signals after ResetBuffers : %x"),iIo->Signals());
+ FlowControlSuspend(); // Defect fix for MPO-4ZECUN
+ iQuickInit->StartQuickInit();
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+// local function needed below
+
+LOCAL_C void SetFaxSessionSettings(RCall::TFaxSessionSettings& aTrg, const RCall::TFaxSessionSettings& aSrc)
+ {
+ aTrg.iMode=aSrc.iMode;
+ aTrg.iFaxRetrieveType=aSrc.iFaxRetrieveType;
+ aTrg.iFaxClass=aSrc.iFaxClass;
+ aTrg.iFaxId=aSrc.iFaxId;
+ aTrg.iMaxSpeed=aSrc.iMaxSpeed;
+ aTrg.iMinSpeed=aSrc.iMinSpeed;
+ aTrg.iPreferredECM=aSrc.iPreferredECM;
+ aTrg.iFaxOnDemandDelay=aSrc.iFaxOnDemandDelay;
+ aTrg.iTxResolution=aSrc.iTxResolution;
+ aTrg.iTxCompression=aSrc.iTxCompression;
+ aTrg.iTxPages=aSrc.iTxPages;
+ aTrg.iRxResolution=aSrc.iRxResolution;
+ aTrg.iRxResolution=aSrc.iRxResolution;
+ }
+
+//
+// CCallMobileFax - fax call functionality
+// At construction, phone init sequence may not have yet determined phone's capabilities so
+// create object anyway and check in the function calls whether fax is supported by phone
+//
+
+CCallMobileFax* CCallMobileFax::NewL(CATIO* aATIO,CATInit* aInit,CPhoneGlobals* aPhoneGlobals,const TName& aName)
+ {
+ CCallMobileFax* faxCall=new(ELeave) CCallMobileFax(aATIO,aInit,aPhoneGlobals);
+ TCleanupItem newCallFaxHayesClose(CloseCall,faxCall);
+ CleanupStack::PushL(newCallFaxHayesClose);
+ faxCall->ConstructL(aName);
+ CleanupStack::Pop();
+ return faxCall;
+ }
+
+CCallMobileFax::CCallMobileFax(CATIO* aATIO,CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
+ : CCallMobile(aATIO,aInit,aPhoneGlobals),iFaxSession(NULL),iFax(NULL)
+ {}
+
+void CCallMobileFax::ConstructL(const TName& aName)
+ {
+ CCallHayes::ConstructL(aName);
+ iCallInfo.iLineOwnerName = KFaxLineName;
+ iDialFax=CATDialFax::NewL(iIo,this,iInit,iPhoneGlobals);
+ iConnectFax=CATConnectFax::NewL(iIo,this,iInit,iPhoneGlobals);
+ iAnswerFax=CATAnswerFax::NewL(iIo,this,iInit,iPhoneGlobals);
+ iHangUpFax=CATHangUpFax::NewL(iIo,this,iInit,iPhoneGlobals);
+ iFaxSettings.iMode = RCall::ETransmit;
+ iFaxSettings.iFaxRetrieveType = RCall::EFaxOnDemand;
+ iFaxSettings.iFaxClass = EClassAuto;
+ iFaxSettings.iMaxSpeed = 9600;
+ iFaxSettings.iMinSpeed = 2400;
+ iFaxSettings.iPreferredECM = EFalse;
+ iFaxSettings.iFaxOnDemandDelay = 20;
+ iFaxSettings.iTxResolution = EFaxNormal;
+ iFaxSettings.iTxCompression = EModifiedHuffman;
+ iFaxSettings.iTxPages = 0;
+ iFaxSettings.iRxResolution = EFaxNormal;
+ iFaxSettings.iRxCompression = EModifiedHuffman;
+ iFaxCompletion = new (ELeave) CFaxCompletion();
+ iFaxProgress=CreateFaxProgressChunk();
+ if(iFaxProgress==NULL)
+ User::Leave(KErrEtelFaxChunkNotCreated);
+ }
+
+CCallMobileFax::~CCallMobileFax()
+//
+// Removes itself from array of calls in CLineMobileData
+//
+ {
+ __ASSERT_DEBUG(iFaxSession==NULL,Panic(EFaxServerNotNull));
+ DeleteFaxProgressChunk(); // This deallocates the memory pointed to by iFaxProgress
+ delete iDialFax;
+ delete iConnectFax;
+ delete iAnswerFax;
+ delete iHangUpFax;
+ delete iFaxCompletion;
+ delete iFileHandles;
+ }
+
+void CCallMobileFax::CollateCoreCaps(const TTsyReqHandle aTsyReqHandle, TUint32* aCallCaps)
+ {
+ *aCallCaps = RCall::KCapsFax;
+ if (ValidateFaxClass(iFaxSettings.iFaxClass)==KErrNone
+ && (!(REINTERPRET_CAST(CLineMobileFax*,Owner())->iFaxOpened==TRUE && iFax==NULL))
+ && iPhoneGlobals->iPhoneStatus.iModemDetected==RPhone::EDetectedPresent)
+ // check that fax class is OK and that no other fax call has opened a fax object
+ {
+ TCallOwnership owner = CheckOwnership(aTsyReqHandle);
+ if (ValidateRequest(aTsyReqHandle,RCall::EStatusIdle)==KErrNone)
+ *aCallCaps |= (RCall::KCapsDial | RCall::KCapsConnect);
+ TInt ret=KErrNone;
+ if (owner==CCallBase::EOwnedFalse) // call owned by another client
+ ret=KErrEtelNotCallOwner;
+ else
+ {
+ if (!iIsForIncomingCall)
+ {
+ if (REINTERPRET_CAST(CPhoneHayes*,Owner()->Owner())->CheckForOutstandingAnswer())
+ ret=KErrEtelAnswerAlreadyOutstanding;
+ }
+ else
+ ret=KErrEtelAnswerAlreadyOutstanding;
+ }
+ if (ret==KErrNone && (iCallInfo.iMobileStatus==RMobileCall::EStatusIdle || iCallInfo.iMobileStatus==RMobileCall::EStatusRinging))
+ *aCallCaps |= RCall::KCapsAnswer;
+ if (owner==CCallBase::EOwnedTrue && iCallInfo.iMobileStatus==RMobileCall::EStatusConnected)
+ {
+ *aCallCaps |= RCall::KCapsHangUp;
+ }
+ }
+ }
+
+TInt CCallMobileFax::OpenFax(TDesC* aTelNumber,TFaxMode aFaxMode)
+//
+// Open CETelFaxHayes object with desired settings
+//
+ {
+ TFaxServerSessionSettings faxSettings;
+ faxSettings.iPhoneNumber.Copy(*aTelNumber);
+ faxSettings.iLogging = ETrue;
+ TInt ret = iPhoneGlobals->iConfiguration->ConfigModemString(TPtrC(KCDTypeNameFaxInitString),faxSettings.iFaxInitString);
+ if (!ret)
+ {
+ ret = iPhoneGlobals->iConfiguration->ConfigModemString(TPtrC(KCDTypeNameCsyName),faxSettings.iPortDriverName);
+ }
+ if (!ret)
+ {
+ ret = iPhoneGlobals->iConfiguration->ConfigModemString(TPtrC(KCDTypeNamePortName),faxSettings.iCommPortName);
+ }
+ if (ret)
+ return ret;
+ if(faxSettings.iFaxInitString.Length()==0)
+ faxSettings.iFaxInitString=KAT2Command;
+ faxSettings.iMode = aFaxMode;
+ faxSettings.iFaxClass = iFaxSettings.iFaxClass;
+ faxSettings.iFaxId = iFaxSettings.iFaxId;
+ faxSettings.iMaxSpeed = iFaxSettings.iMaxSpeed;
+ faxSettings.iMinSpeed = iFaxSettings.iMinSpeed;
+ faxSettings.iPreferredECM = iFaxSettings.iPreferredECM;
+ faxSettings.iFaxOnDemandDelay = iFaxSettings.iFaxOnDemandDelay;
+ faxSettings.iTxResolution = iFaxSettings.iTxResolution;
+ faxSettings.iTxCompression = iFaxSettings.iTxCompression;
+ faxSettings.iTxPages = iFaxSettings.iTxPages;
+ faxSettings.iRxResolution = iFaxSettings.iRxResolution;
+ faxSettings.iRxCompression = iFaxSettings.iRxCompression;
+ return iFaxSession->FxOpen(faxSettings,iFaxProgress);
+ }
+
+TInt CCallMobileFax::ValidateFaxClass(TFaxClass& aFaxClass)
+ {
+ if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & KFaxCaps) == 0)
+ {
+ return KErrNotSupported;
+ }
+ switch (aFaxClass)
+ {
+ case EClassAuto: // TSY decides what class "AUTO" refers to!
+ {
+ if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & RPhone::KCapsFaxClassTwoPointZero))
+ aFaxClass = EClass2point0;
+ else if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & RPhone::KCapsFaxClassTwo))
+ aFaxClass = EClass2;
+ else if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & RPhone::KCapsFaxClassOne))
+ aFaxClass = EClass1;
+ break;
+ }
+ case EClass1:
+ if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & RPhone::KCapsFaxClassOne)==0)
+ return KErrEtelWrongModemType;
+ break;
+ case EClass1point0:
+ if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & RPhone::KCapsFaxClassOnePointZero)==0)
+ return KErrEtelWrongModemType;
+ break;
+ case EClass2:
+ if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & RPhone::KCapsFaxClassTwo)==0)
+ return KErrEtelWrongModemType;
+ break;
+ case EClass2point0:
+ if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & RPhone::KCapsFaxClassTwoPointZero)==0)
+ return KErrEtelWrongModemType;
+ break;
+ case EClass2point1:
+ if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & RPhone::KCapsFaxClassTwoPointOne)==0)
+ return KErrEtelWrongModemType;
+ break;
+ default:
+ return KErrEtelWrongModemType;
+ }
+ return KErrNone;
+ }
+
+typedef CFaxSession* (*TFaxServerEntry)();
+void CCallMobileFax::GetFaxBaseL()
+ {
+ __ASSERT_DEBUG(iFaxCompletion,Panic(EFaxCompletionPtrNull));
+ RFs fs;
+ (void)User::LeaveIfError(fs.Connect());
+
+ TInt r=iFaxServerLib.Load(KFaxServerName);
+ if (r==KErrNone)
+ {
+ // Check the Uid2
+#if defined (_UNICODE)
+ if(iFaxServerLib.Type()[1]!=TUid::Uid(KUidUnicodeDynamicFaxServer))
+ r = KErrBadLibraryEntryPoint;
+#else
+ if(iFaxServerLib.Type()[1]!=TUid::Uid(KUidDynamicFaxServer))
+ r = KErrBadLibraryEntryPoint;
+#endif
+ if (r==KErrNone)
+ {
+ TFaxServerEntry libEntry=(TFaxServerEntry)iFaxServerLib.Lookup(1);
+ if (libEntry!=NULL)
+ {
+ TRAP(r,iFaxSession=(*libEntry)()); // libEntry may leave.
+ if (r==KErrNone)
+ {
+ LOGTEXT(_L8("Loaded Fax Server"));
+ iFaxSession->SetCallBack(iFaxCompletion);
+ }
+ else
+ iFaxServerLib.Close();
+ }
+ else
+ {
+ r = KErrBadLibraryEntryPoint;
+ iFaxServerLib.Close();
+ }
+ }
+ else
+ iFaxServerLib.Close();
+ }
+ fs.Close();
+ (void)User::LeaveIfError(r);
+ }
+
+TInt CCallMobileFax::FaxConnectHandler(const TTsyReqHandle aTsyReqHandle)
+ {
+ TInt ret = ValidateFaxClass(iFaxSettings.iFaxClass);
+ if (ret!=KErrNone)
+ {
+ (void)SetUnowned();
+ ReqCompleted(aTsyReqHandle,ret);
+ return ret;
+ }
+ if (REINTERPRET_CAST(CLineMobileFax*,Owner())->iFaxOpened==TRUE && iFax==NULL)
+ {
+ (void)SetUnowned();
+ ReqCompleted(aTsyReqHandle,KErrEtelNotFaxOwner);
+ return ret;
+ }
+
+ TRAPD(res,GetFaxBaseL());
+ if (res!=KErrNone)
+ {
+ (void)SetUnowned();
+ ReqCompleted(aTsyReqHandle,res);
+ }
+ iPhoneGlobals->iEventSignalActive = EFalse;
+ return res;
+ }
+
+void CCallMobileFax::FaxDial(const TTsyReqHandle aTsyReqHandle,TDesC* aTelNumber)
+//
+// Called once any initialising has been done. Checks here that modem supports fax,
+// and that no other CCallHayes has opened a fax object
+//
+ {
+ if (FaxConnectHandler(aTsyReqHandle)!=KErrNone) // ReqCompleted is called inside FaxConnectHandler
+ // if there is an error
+ return;
+ TFaxMode faxMode;
+ if (iFaxSettings.iMode==RCall::ETransmit)
+ {
+ faxMode = EDialAndTransmit;
+ }
+ else // we're receiving
+ {
+ if (iFaxSettings.iFaxRetrieveType==RCall::EFaxPoll)
+ faxMode = EDialAndReceivePoll;
+ else
+ faxMode = EDialAndReceiveFaxBack;
+ }
+ TInt res = OpenFax(aTelNumber,faxMode);
+ if (res!=KErrNone) // make sure cleaned up.
+ {
+ ReqCompleted(aTsyReqHandle,res);
+ return;
+ }
+ ChangeLineStatus(RCall::EStatusDialling);
+ // EStatusDialling always results in KErrNone return
+ (void) ChangeCallStatus(RMobileCall::EStatusDialling);
+ iPhoneGlobals->iNotificationStore->CheckNotification(this,EBegunConnecting);
+ iFaxCompletion->Configure(aTsyReqHandle,this);
+ iIo->Cancel();
+ iPhoneGlobals->iPhoneStatus.iPortAccess = EPortAccessDenied; // so CATIO won't queue a read
+
+ if (faxMode == EDialAndTransmit)
+ {
+ LOGTEXT(_L8("About to call CETelFaxBase::TxConnect"));
+ //this transfers ownership of the file handles object to the fax session object.
+ iFaxSession->SetFaxHeaderFile(iFileHandles);
+ //we now aren't resonsible for its deletion.
+ iFileHandles = NULL;
+ iFaxSession->TxConnect();
+ }
+ else
+ {
+ LOGTEXT(_L8("About to call CETelFaxBase::RxConnect"));
+ iFaxSession->RxConnect();
+ }
+ }
+
+TInt CCallMobileFax::Dial(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams,TDesC* aTelNumber)
+//
+// Dial a fax call
+// Check that call is not owned by another client, and line is idle
+//
+ {
+ TInt ret = ValidateRequest(aTsyReqHandle,RCall::EStatusIdle);
+ if (ret==KErrNone)
+ {
+ (void)SetOwnership(aTsyReqHandle);
+ SetCallParams(aCallParams);
+ LOGTEXT(_L8("FaxCall:\tSubmitting Dial Command"));
+ iDialFax->ExecuteCommand(aTsyReqHandle,aTelNumber,&iCallInfo);
+ }
+ else
+ ReqCompleted(aTsyReqHandle,ret);
+ return KErrNone;
+ }
+
+void CCallMobileFax::FaxCancelCommand(const TTsyReqHandle aTsyReqHandle)
+//
+// Cancels the fax session (for ConnectCancel and AnswerCancel as well)
+//
+ {
+ LOGTEXT(_L8("FaxCall:\tCancel Fax call and Unload module"));
+ if(!iFaxSession) // if iFaxSession is NULL
+ { // then CleanUpFaxServer has already been called
+ LOGTEXT(_L8("FaxCall:\tModule already unloaded, completing..."));
+ ReqCompleted(aTsyReqHandle,KErrCancel); // so return without further processing
+ return;
+ }
+
+ LOGTEXT(_L8("FaxCall:\tClosing down fax server module"));
+ iFaxSession->Cancel();
+ CleanUpFaxServer();
+ iIo->Read();
+ SetToIdle();
+ ReqCompleted(aTsyReqHandle,KErrCancel);
+ }
+
+TInt CCallMobileFax::DialCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ LOGTEXT2(_L8("FaxCall:\tDialCancel(%d) called"),aTsyReqHandle);
+ iDialFax->CancelCommand(aTsyReqHandle);
+ return KErrNone;
+ }
+
+void CCallMobileFax::FaxConnect(const TTsyReqHandle aTsyReqHandle)
+//
+// Called once any initialising has been done. Checks here that modem supports fax.
+//
+ {
+ if (FaxConnectHandler(aTsyReqHandle)!=KErrNone)
+ return;
+ TFaxMode faxMode;
+ if (iFaxSettings.iMode==RCall::ETransmit)
+ faxMode = EImmediateTransmit;
+ else
+ faxMode = EImmediateReceive;
+ TBuf<1> null;
+ null.Zero();
+ TInt res = OpenFax(&null,faxMode);
+ if (res!=KErrNone)
+ {
+ ReqCompleted(aTsyReqHandle,res);
+ return;
+ }
+ ChangeLineStatus(RCall::EStatusConnecting);
+ // EStatusConnecting always returns KErrNone
+ (void)ChangeCallStatus(RMobileCall::EStatusConnecting);
+ iPhoneGlobals->iNotificationStore->CheckNotification(this,EBegunConnecting);
+ iFaxCompletion->Configure(aTsyReqHandle,this);
+ iIo->Cancel();
+ iPhoneGlobals->iPhoneStatus.iPortAccess = EPortAccessDenied; // so CATIO won't queue a read
+ if (faxMode == EImmediateTransmit)
+ iFaxSession->TxConnect();
+ else
+ iFaxSession->RxConnect();
+ }
+
+TInt CCallMobileFax::Connect(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams)
+//
+// Immediate connect to a fax call
+// Check that call is not owned by another client, and line is idle
+//
+ {
+ TInt ret = ValidateRequest(aTsyReqHandle,RCall::EStatusIdle);
+ if (ret==KErrNone)
+ {
+ (void)SetOwnership(aTsyReqHandle);
+ SetCallParams(aCallParams);
+ LOGTEXT(_L8("FaxCall:\tSubmitting Connect Command"));
+ iConnectFax->ExecuteCommand(aTsyReqHandle,NULL,&iCallInfo);
+ }
+ else
+ ReqCompleted(aTsyReqHandle,ret);
+ return KErrNone;
+ }
+
+TInt CCallMobileFax::ConnectCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ LOGTEXT2(_L8("FaxCall:\tConnectCancel(%d) called"),aTsyReqHandle);
+ iConnectFax->CancelCommand(aTsyReqHandle);
+ return KErrNone;
+ }
+
+void CCallMobileFax::FaxAnswer(const TTsyReqHandle aTsyReqHandle)
+ {
+ if (FaxConnectHandler(aTsyReqHandle)!=KErrNone)
+ return;
+ TFaxMode faxMode;
+ if (iFaxSettings.iMode==RCall::ETransmit)
+ faxMode = EWaitForRingAndTransmit;
+ else
+ faxMode = EWaitForRingAndReceive;
+ TBuf<1> null;
+ null.Zero();
+ TInt res = OpenFax(&null,faxMode);
+ if (res!=KErrNone)
+ {
+ ReqCompleted(aTsyReqHandle,res);
+ return;
+ }
+ LOGTEXT(_L8("FaxCall:\tAnswering Fax call"));
+ ChangeLineStatus(RCall::EStatusAnswering);
+ // EStatusAnswering always results in KerrNone return
+ (void)ChangeCallStatus(RMobileCall::EStatusAnswering);
+ CPhoneHayes* phone=STATIC_CAST(CPhoneHayes*,Owner()->Owner());
+ phone->StopRingCounter(); // RING should no longer come in
+ iPhoneGlobals->iNotificationStore->CheckNotification(this,EBegunConnecting);
+ iFaxCompletion->Configure(aTsyReqHandle,this);
+ iIo->Cancel();
+ iPhoneGlobals->iPhoneStatus.iPortAccess = EPortAccessDenied; // so CATIO won't queue a read
+ if (faxMode == EWaitForRingAndTransmit)
+ iFaxSession->TxConnect();
+ else
+ iFaxSession->RxConnect();
+ }
+
+TInt CCallMobileFax::AnswerIncomingCall(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams)
+//
+// Answer a fax call
+//
+ {
+ TInt ret=KErrNone;
+ CCallBase::TCallOwnership owned = CheckOwnership(aTsyReqHandle);
+ if (owned==CCallBase::EOwnedFalse) // call owned by another client
+ {
+ ret=KErrEtelNotCallOwner;
+ }
+ else if (REINTERPRET_CAST(CPhoneHayes*,Owner()->Owner())->CheckForOutstandingAnswer())
+ ret=KErrEtelAnswerAlreadyOutstanding;
+
+ if (ret==KErrNone)
+ {
+ CLineHayes* line = STATIC_CAST(CLineHayes*,Owner());
+ CPhoneHayes* phone=STATIC_CAST(CPhoneHayes*,line->Owner());
+ phone->CancelOtherRingingCall(line);
+ line->FreePreAllocCallIfNecessary();
+ SetCallParams(aCallParams);
+ if (iCallInfo.iMobileStatus==RMobileCall::EStatusRinging)
+ {
+ LOGTEXT(_L8("FaxCall:\tSubmitting Answer Command"));
+ iAnswerFax->ExecuteCommand(aTsyReqHandle,NULL,&iCallInfo);
+ }
+ else // This call is now a client-designated Incoming Call object.
+ {
+ iIsForIncomingCall=ETrue;
+ iAnswerTsyReqHandle = aTsyReqHandle;
+ }
+ return KErrNone;
+ }
+ ReqCompleted(aTsyReqHandle,ret);
+ return KErrNone;
+ }
+
+TInt CCallMobileFax::AnswerIncomingCallCancel(const TTsyReqHandle aTsyReqHandle)
+//
+// Cancel the answer command if possible
+//
+ {
+ LOGTEXT2(_L8("FaxCall:\tAnswerCancel(%d) called"),aTsyReqHandle);
+ if (iIsForIncomingCall)
+ {
+ iIsForIncomingCall=EFalse;
+ ReqCompleted(aTsyReqHandle,KErrCancel);
+ }
+ else
+ iAnswerFax->CancelCommand(aTsyReqHandle);
+ return KErrNone;
+ }
+
+void CCallMobileFax::AnswerImmediately()
+ {
+ (void)SetOwnership(iAnswerTsyReqHandle);
+ // EStatusRinging always results in KErrNone return
+ (void)ChangeCallStatus(RMobileCall::EStatusRinging);// new 14/1/99
+ iPhoneGlobals->iNotificationStore->CheckNotification(this,ERingOccurred);
+ iIsForIncomingCall=EFalse;
+ LOGTEXT(_L8("FaxCall:\tSubmitting Answer command"));
+ iAnswerFax->ExecuteCommand(iAnswerTsyReqHandle,NULL,&iCallInfo);
+ }
+
+void CCallMobileFax::FaxHangUp(const TTsyReqHandle aTsyReqHandle)
+//
+// Fax server reconfigures port so no need to here.
+//
+ {
+ if (iFaxSession)
+ {
+ // EStatusDisconnecting always results in KErrNone return
+ (void)ChangeCallStatus(RMobileCall::EStatusDisconnecting);
+ ChangeLineStatus(RCall::EStatusHangingUp);
+ iPhoneGlobals->iNotificationStore->CheckNotification(this,EBegunHangingUp);
+ CleanUpFaxServer();
+ iIo->Read();
+ SetToIdle();
+ }
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ }
+
+TInt CCallMobileFax::HangUp(const TTsyReqHandle aTsyReqHandle)
+//
+// Terminate a fax call. Checks fax capability, call ownership and line status.
+//
+ {
+ if ((iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags & KFaxCaps) == 0)
+ {
+ ReqCompleted(aTsyReqHandle,KErrNotSupported);
+ return KErrNone;
+ }
+ if (CheckOwnership(aTsyReqHandle)==CCallBase::EOwnedFalse)
+ {
+ ReqCompleted(aTsyReqHandle,KErrEtelNotCallOwner);
+ return KErrNone;
+ }
+ if (iPhoneGlobals->iPhoneStatus.iLineStatus != RCall::EStatusConnected)
+ {
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+ LOGTEXT(_L8("FaxCall:\tHanging up"));
+ iHangUpFax->ExecuteCommand(aTsyReqHandle,NULL,&iCallInfo);
+ return KErrNone;
+ }
+
+TInt CCallMobileFax::HangUpCancel(const TTsyReqHandle aTsyReqHandle)
+ {
+ iHangUpFax->CancelCommand(aTsyReqHandle);
+ return KErrNone;
+ }
+
+TInt CCallMobileFax::RelinquishOwnership()
+//
+// Called by server to tell TSY to either pass ownership on to another interested client
+// or hang up immediately
+//
+ {
+ LOGTEXT(_L8("FaxCall:\tRelinquish Ownership"));
+ if(iList->iAcquireList.IsEmpty())
+ {
+ if (iDialFax->IsPreConnectInProgress() ||
+ iConnectFax->IsPreConnectInProgress() ||
+ iAnswerFax->IsPreConnectInProgress()) // fax server has not yet been started
+ {
+ iCallInfo.iClientPanicOccurred = EPanicOccurredWithoutDataPortLoan;
+ return KErrNone;
+ }
+ (void)SetUnowned();
+ TInt ret = KErrNone;
+ if (iCallInfo.iMobileStatus==RMobileCall::EStatusDialling ||
+ iCallInfo.iMobileStatus==RMobileCall::EStatusConnecting ||
+ iCallInfo.iMobileStatus==RMobileCall::EStatusAnswering ||
+ iCallInfo.iMobileStatus==RMobileCall::EStatusConnected ||
+ iCallInfo.iMobileStatus==RMobileCall::EStatusDisconnecting
+ )
+ {
+ LOGTEXT(_L8("FaxCall:\tHanging up"));
+ ChangeLineStatus(RCall::EStatusHangingUp);
+ // EStatusDisconnecting always results in KErrNone return
+ (void)ChangeCallStatus(RMobileCall::EStatusDisconnecting);
+ CleanUpFaxServer();
+ ChangeLineStatus(RCall::EStatusIdle);
+ // EStatusIdle always results in KErrNone return
+ (void)ChangeCallStatus(RMobileCall::EStatusIdle);
+ iPhoneGlobals->iPhoneStatus.iMode = RPhone::EModeIdle;
+ iIo->Cancel();
+ TCommConfig aConfigPckg;
+ TInt ret = iPhoneGlobals->iConfiguration->PortConfig(aConfigPckg,EConfigTypeInit);
+ if (ret==KErrNone)
+ ret = iIo->ConfigurePort(aConfigPckg);
+ if (ret)
+ iPhoneGlobals->iPhoneStatus.iInitStatus = EPhoneNotInitialised;
+ else
+ iIo->Read(); // should a read be queued in this case?
+ }
+ RelinquishOwnershipCompleted(ret);
+ return KErrNone;
+ }
+ CAcquireEntry* entry=iList->iAcquireList.First();
+ if (entry)
+ {
+ (void)SetOwnership(entry->iTsyReqHandle);
+ ReqCompleted(entry->iTsyReqHandle,KErrNone);
+ iList->Remove(entry);
+ }
+ RelinquishOwnershipCompleted(KErrNone);
+ return KErrNone;
+ }
+
+TInt CCallMobileFax::GetFaxSettings(const TTsyReqHandle aTsyReqHandle,RCall::TFaxSessionSettings* aSettings)
+//
+// Which are stored privately in CCallMobileFax
+//
+ {
+ LOGTEXT(_L8("FaxCall:\tGetting fax settings"));
+ SetFaxSessionSettings(*aSettings,iFaxSettings);
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+TInt CCallMobileFax::SetFaxSettings(const TTsyReqHandle aTsyReqHandle,const RCall::TFaxSessionSettings* aSettings)
+ {
+ LOGTEXT(_L8("FaxCall:\tSetting fax settings"));
+ TUint phoneCaps = iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags;
+ if (aSettings->iFaxClass==EClass1 && (phoneCaps&RPhone::KCapsFaxClassOne) ||
+ aSettings->iFaxClass==EClass2 && (phoneCaps&RPhone::KCapsFaxClassTwo) ||
+ aSettings->iFaxClass==EClass2point0 && (phoneCaps&RPhone::KCapsFaxClassTwoPointZero) ||
+ aSettings->iFaxClass==EClass1point0 && (phoneCaps&RPhone::KCapsFaxClassOnePointZero) ||
+ aSettings->iFaxClass==EClass2point1 && (phoneCaps&RPhone::KCapsFaxClassTwoPointOne) ||
+ aSettings->iFaxClass==EClassAuto)
+ {
+ SetFaxSessionSettings(iFaxSettings,*aSettings);
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ }
+ else if (iPhoneGlobals->iPhoneStatus.iInitStatus!=EPhoneInitialised)
+ ReqCompleted(aTsyReqHandle,KErrEtelUnknownModemCapability);
+ else
+ ReqCompleted(aTsyReqHandle,KErrNotSupported);
+ return KErrNone;
+ }
+
+TInt CCallMobileFax::SetFaxSharedHeaderFile(const TTsyReqHandle aTsyReqHandle, CFaxSharedFileHandles* aFaxSharedFileHandles)
+ {
+ //if we already own an object delete and re-point to new one.
+ if(iFileHandles)
+ {
+ delete iFileHandles;
+ iFileHandles = NULL;
+ }
+ iFileHandles = aFaxSharedFileHandles;
+
+ ReqCompleted(aTsyReqHandle,KErrNone);
+ return KErrNone;
+ }
+
+CTelObject* CCallMobileFax::OpenNewObjectByNameL(const TDesC& /*aName*/)
+//
+// Only want one CFaxHayes object to be opened per phone.
+// Previously only the connected call could open a CFaxHayes object, so it was easy to check
+// whether one had already been opened. Now a fax call can open a fax object at any time
+// making it less clear how to check that no other call has opened one.
+//
+ {
+ if (iPhoneGlobals->iPhoneStatus.iLineStatus != GetCoreCallStatus())
+ { // ie another fax call is in progress so this call cannot open a fax object
+ User::Leave(KErrEtelNotCallOwner);
+ }
+ TBool& faxOpened = REINTERPRET_CAST(CLineMobileFax*,Owner())->iFaxOpened;
+ if (faxOpened==TRUE)
+ {
+ User::Leave(KErrAlreadyExists);
+ }
+ faxOpened=ETrue;
+ iFax = CFaxHayes::NewL(this,iPhoneGlobals);
+ return iFax;
+ }
+
+void CCallMobileFax::RemoveFax(CFaxHayes* aFaxHayes)
+ {
+ if (iFax == aFaxHayes)
+ iFax=NULL;
+ REINTERPRET_CAST(CLineMobileFax*,Owner())->iFaxOpened=EFalse;
+ }
+
+void CCallMobileFax::CleanUpFaxServer()
+ {
+ LOGTEXT(_L8("Closing down Fax Server"));
+ (void)iFaxSession->FxClose();
+ iFaxServerLib.Close();
+ iFaxSession = NULL;
+ iPhoneGlobals->iPhoneStatus.iPortAccess = EPortAccessAllowed;
+ iPhoneGlobals->iEventSignalActive = EFalse;
+ }