diff -r 6b1d113cdff3 -r 6638e7f4bd8f telephonyserverplugins/multimodetsy/hayes/CALL.CPP --- a/telephonyserverplugins/multimodetsy/hayes/CALL.CPP Mon May 03 13:37:20 2010 +0300 +++ b/telephonyserverplugins/multimodetsy/hayes/CALL.CPP Thu May 06 15:10:38 2010 +0100 @@ -1,2050 +1,2050 @@ -// 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 -#include "CALL.H" // Header file for this source file -#include "NOTIFY.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 -#include "ATBASE.H" -#include "Matstd.h" // For AT command string constants -#include "set_cbst.h" // for CATSetCBST class -#include "et_struct.h" - - -// -// 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 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* paramsPckg = (TPckg*)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* paramsPckg = (TPckg*)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(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(&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* pckg = (TPckg*)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& 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 value we can not send the command. - // If we do not have a value then we can send a command giving only and . - // etc... - if(speedSet) - { - aTxBuffer.Zero(); // Clear tx buffer - - // Append +CBST= and the parameter - aTxBuffer.Append(KDataCallBearerServiceType); - aTxBuffer.AppendNum(speed); - - if(nameSet) - { - // Append the parameter - aTxBuffer.Append(TChar(',')); - aTxBuffer.AppendNum(name); - - if(ceSet) - { - // Append the 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; - } +// 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 +#include "CALL.H" // Header file for this source file +#include "NOTIFY.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 +#include "ATBASE.H" +#include "Matstd.h" // For AT command string constants +#include "set_cbst.h" // for CATSetCBST class +#include "et_struct.h" + + +// +// 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 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* paramsPckg = (TPckg*)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* paramsPckg = (TPckg*)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(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(&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* pckg = (TPckg*)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& 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 value we can not send the command. + // If we do not have a value then we can send a command giving only and . + // etc... + if(speedSet) + { + aTxBuffer.Zero(); // Clear tx buffer + + // Append +CBST= and the parameter + aTxBuffer.Append(KDataCallBearerServiceType); + aTxBuffer.AppendNum(speed); + + if(nameSet) + { + // Append the parameter + aTxBuffer.Append(TChar(',')); + aTxBuffer.AppendNum(name); + + if(ceSet) + { + // Append the 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; + }