// 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;
}