// Copyright (c) 2001-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:
// This file contains the implementation of the Simulator TSY Data Call functionality.
// The Call classes process the Call-based requests made by ETel clients
// and passed down to the TSY by the ETel Server.
//
//
/**
@file
*/
#include <testconfigfileparser.h>
#include "CSimDataCall.h"
#include "CSimPhone.h"
#include "Simlog.h"
CSimDataCall* CSimDataCall::NewL(CSimLine* aLine,const TDesC& aName, CSimPhone* aPhone)
/**
* Standard two phase constructor.
*
* @param aLine pointer to the Line object.
* @param aName name of the call to be constructed
* @return CSimDataCall pointer to the data call object created
* @leave Leaves if no memory or object is not created for any reason
*/
{
CSimDataCall* dataCall=new(ELeave) CSimDataCall(aLine,aName,aPhone);
TCleanupItem newCallDataClose(CloseCall,dataCall);
CleanupStack::PushL(newCallDataClose);
dataCall->ConstructL();
CleanupStack::Pop();
return dataCall;
}
CSimDataCall::CSimDataCall(CSimLine* aLine,const TName& aName, CSimPhone* aPhone)
: CSimCall(aLine,aName,aPhone), iCommPortLoaned(EFalse)
/**
* Trivial constructor. Calls CSimCall to initialise its members
*/
{
iCaps=Caps();
}
void CSimDataCall::ConstructL()
/**
* Second phase of 2-Phase Constructor
* Retrieves all the pausing duration tags from the config file
*
* @param aName name of the data call to be constructed
*/
{
LOGDATA1("Starting to parse Data Call config parameters...");
iDiallingPause=iLine->CfgFile()->ItemValue(KDiallingPauseDuration,KDefaultDiallingPauseDuration);
iConnectingPause=iLine->CfgFile()->ItemValue(KConnectingPauseDuration,KDefaultConnectingPauseDuration);
iDisconnectingPause=iLine->CfgFile()->ItemValue(KDisconnectingPauseDuration,KDefaultDisconnectingPauseDuration);
iAnswerIncomingPause=iLine->CfgFile()->ItemValue(KAnswerIncomingPauseDuration,KDefaultAnswerIncomingPauseDuration);
iRemoteHangupPause=iLine->CfgFile()->ItemValue(KRemoteHangupPauseDuration,KDefaultRemoteHangupPauseDuration);
// Read in the CommPort setup
const CTestConfigItem* item=iLine->CfgFile()->Item(KDataCallCaps);
if(item)
{
TPtrC8 speedCaps, protocolCaps, serviceCaps, qosCaps, codingCaps, asymmetryCaps;
TPtrC8 rlpVersionCaps, v42bisCaps;
TBool hscsdSupport, userInitUpgrade;
TInt mClass, MaxRxTimeslots, MaxTxTimeslots, totalRxTxTimeslots;
TUint8 digit = 0;
TInt ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,speedCaps);
if(ret!=KErrNone)
{
LOGPARSERR("speedCaps",ret,0,&KDataCallCaps);
}
else
if(AsciiToNum(speedCaps, digit)==KErrNone)
iMobileCallCaps.iSpeedCaps = digit;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,protocolCaps);
if(ret!=KErrNone)
{
LOGPARSERR("protocolCaps",ret,1,&KDataCallCaps);
}
else
if(AsciiToNum(protocolCaps, digit)==KErrNone)
iMobileCallCaps.iProtocolCaps = digit;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,serviceCaps);
if(ret!=KErrNone)
{
LOGPARSERR("serviceCaps",ret,2,&KDataCallCaps);
}
else
if(AsciiToNum(serviceCaps, digit)==KErrNone)
iMobileCallCaps.iServiceCaps = digit;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,qosCaps);
if(ret!=KErrNone)
{
LOGPARSERR("qosCaps",ret,3,&KDataCallCaps);
}
else
if(AsciiToNum(qosCaps, digit)==KErrNone)
iMobileCallCaps.iQoSCaps = digit;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,4,hscsdSupport);
if(ret!=KErrNone)
{
LOGPARSERR("hscsdSupport",ret,4,&KDataCallCaps);
}
else
iMobileCallCaps.iHscsdSupport = hscsdSupport;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,5,mClass);
if(ret!=KErrNone)
{
LOGPARSERR("mClass",ret,5,&KDataCallCaps);
}
else
iMobileCallCaps.iMClass = mClass;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,6,MaxRxTimeslots);
if(ret!=KErrNone)
{
LOGPARSERR("MaxRxTimeslots",ret,6,&KDataCallCaps);
}
else
iMobileCallCaps.iMaxRxTimeSlots = MaxRxTimeslots;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,7,MaxTxTimeslots);
if(ret!=KErrNone)
{
LOGPARSERR("MaxTxTimeslots",ret,7,&KDataCallCaps);
}
else
iMobileCallCaps.iMaxTxTimeSlots = MaxTxTimeslots;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,8,totalRxTxTimeslots);
if(ret!=KErrNone)
{
LOGPARSERR("totalRxTxTimeslots",ret,8,&KDataCallCaps);
}
else
iMobileCallCaps.iTotalRxTxTimeSlots = totalRxTxTimeslots;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,9,codingCaps);
if(ret!=KErrNone)
{
LOGPARSERR("codingCaps",ret,9,&KDataCallCaps);
}
else
if(AsciiToNum(codingCaps, digit)==KErrNone)
iMobileCallCaps.iCodingCaps = digit;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,10,asymmetryCaps);
if(ret!=KErrNone)
{
LOGPARSERR("asymmetryCaps",ret,10,&KDataCallCaps);
}
else
if(AsciiToNum(asymmetryCaps, digit)==KErrNone)
iMobileCallCaps.iAsymmetryCaps = digit;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,11,userInitUpgrade);
if(ret!=KErrNone)
{
LOGPARSERR("userInitUpgrade",ret,11,&KDataCallCaps);
}
else
iMobileCallCaps.iUserInitUpgrade = userInitUpgrade;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,10,rlpVersionCaps);
if(ret!=KErrNone)
{
LOGPARSERR("rlpVersionCaps",ret,10,&KDataCallCaps);
}
else
if(AsciiToNum(rlpVersionCaps, digit)==KErrNone)
iMobileCallCaps.iRLPVersionCaps = digit;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,10,v42bisCaps);
if(ret!=KErrNone)
{
LOGPARSERR("v42bisCaps",ret,10,&KDataCallCaps);
}
else
if(AsciiToNum(v42bisCaps, digit)==KErrNone)
iMobileCallCaps.iV42bisCaps = digit;
}
else //Default Values for Caps
{
iMobileCallCaps.iSpeedCaps=RMobileCall::KCapsSpeedAutobauding;
iMobileCallCaps.iProtocolCaps=RMobileCall::KCapsProtocolV32;
iMobileCallCaps.iServiceCaps=(RMobileCall::KCapsDataCircuitAsynchronous | RMobileCall::KCapsPacketAccessSyncUDI);
iMobileCallCaps.iQoSCaps=RMobileCall::KCapsTransparentPreferred;
iMobileCallCaps.iHscsdSupport=(TBool)(ETrue);
iMobileCallCaps.iMClass=1;
iMobileCallCaps.iMaxRxTimeSlots=5;
iMobileCallCaps.iMaxTxTimeSlots=5;
iMobileCallCaps.iTotalRxTxTimeSlots=10;
iMobileCallCaps.iCodingCaps=(RMobileCall::KCapsAiurCoding48 | RMobileCall::KCapsAiurCoding96);
iMobileCallCaps.iAsymmetryCaps=(RMobileCall::EAsymmetryUplink);
iMobileCallCaps.iUserInitUpgrade=(TBool)(ETrue);
iMobileCallCaps.iRLPVersionCaps = 1;
iMobileCallCaps.iV42bisCaps = 1;
}
TInt count = iLine->CfgFile()->ItemCount(KDataRLPparams);
TMobileCallRLPItem iMobileCallRLPItem;
iMobileCallRLPList = new(ELeave) CArrayFixFlat<TMobileCallRLPItem>(5);
if(count!=0)
{
for(TInt i=0;i<count;i++)
{
item = iLine->CfgFile()->Item(KDataRLPparams,i);
if(!item)
break;
TInt iRlpVersion,iIWSMax,iIWSMin,iMWSMax,iMWSMin;
TInt iT1Max,iT1Min,iN2Max,iN2Min,iT4Max,iT4Min;
TInt ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,iRlpVersion);
if(ret!=KErrNone)
{
LOGPARSERR("iRlpVersion",ret,0,&KDataRLPparams);
}
else
iMobileCallRLPItem.iRlpVersion = iRlpVersion;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,iIWSMax);
if(ret!=KErrNone)
{
LOGPARSERR("iIWSMax",ret,0,&KDataRLPparams);
}
else
iMobileCallRLPItem.iMobileCallRLP.iIWSMax = iIWSMax;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,iIWSMin);
if(ret!=KErrNone)
{
LOGPARSERR("iIWSMin",ret,1,&KDataRLPparams);
}
else
iMobileCallRLPItem.iMobileCallRLP.iIWSMin = iIWSMin;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,iMWSMax);
if(ret!=KErrNone)
{
LOGPARSERR("iMWSMax",ret,2,&KDataRLPparams);
}
else
iMobileCallRLPItem.iMobileCallRLP.iMWSMax = iMWSMax;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,iMWSMin);
if(ret!=KErrNone)
{
LOGPARSERR("iMWSMin",ret,3,&KDataRLPparams);
}
else
iMobileCallRLPItem.iMobileCallRLP.iMWSMin = iMWSMin;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,4,iT1Max);
if(ret!=KErrNone)
{
LOGPARSERR("iT1Max",ret,4,&KDataRLPparams);
}
else
iMobileCallRLPItem.iMobileCallRLP.iT1Max = iT1Max;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,5,iT1Min);
if(ret!=KErrNone)
{
LOGPARSERR("iT1Min",ret,5,&KDataRLPparams);
}
else
iMobileCallRLPItem.iMobileCallRLP.iT1Min = iT1Min;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,6,iN2Max);
if(ret!=KErrNone)
{
LOGPARSERR("iN2Max",ret,6,&KDataRLPparams);
}
else
iMobileCallRLPItem.iMobileCallRLP.iN2Max = iN2Max;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,7,iN2Min);
if(ret!=KErrNone)
{
LOGPARSERR("iN2Min",ret,7,&KDataRLPparams);
}
else
iMobileCallRLPItem.iMobileCallRLP.iN2Min = iN2Min;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,8,iT4Max);
if(ret!=KErrNone)
{
LOGPARSERR("iT4Max",ret,8,&KDataRLPparams);
}
else
iMobileCallRLPItem.iMobileCallRLP.iT4Max = iT4Max;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,9,iT4Min);
if(ret!=KErrNone)
{
LOGPARSERR("iT4Min",ret,9,&KDataRLPparams);
}
else
iMobileCallRLPItem.iMobileCallRLP.iT4Min = iT4Min;
iMobileCallRLPList->AppendL(iMobileCallRLPItem);
}
}
else
{
iMobileCallRLPItem.iRlpVersion=1;
iMobileCallRLPItem.iMobileCallRLP.iIWSMax=10;
iMobileCallRLPItem.iMobileCallRLP.iIWSMin=5;
iMobileCallRLPItem.iMobileCallRLP.iMWSMax=8;
iMobileCallRLPItem.iMobileCallRLP.iMWSMin=4;
iMobileCallRLPItem.iMobileCallRLP.iT1Max=4;
iMobileCallRLPItem.iMobileCallRLP.iT1Min=2;
iMobileCallRLPItem.iMobileCallRLP.iN2Max=12;
iMobileCallRLPItem.iMobileCallRLP.iN2Min=1;
iMobileCallRLPItem.iMobileCallRLP.iT4Max=10;
iMobileCallRLPItem.iMobileCallRLP.iT4Min=2;
iMobileCallRLPList->AppendL(iMobileCallRLPItem);
}
item=iLine->CfgFile()->Item(KDynamicHSCSDInfo);
if(item)
{
TPtrC8 iAiur,iCodings;
TInt iRxTimeSlots,iTxTimeSlots;
TUint8 digit=0;
TInt ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,iAiur);
if(ret!=KErrNone)
{
LOGPARSERR("iAiur",ret,0,&KDynamicHSCSDInfo);
}
else
if(AsciiToNum(iAiur, digit)==KErrNone)
iHscsdInfo.iAiur = (RMobileCall::TMobileCallAiur) digit;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,iRxTimeSlots);
if(ret!=KErrNone)
{
LOGPARSERR("iRxTimeSlots",ret,1,&KDynamicHSCSDInfo);
}
else
iHscsdInfo.iRxTimeSlots = iRxTimeSlots;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,iTxTimeSlots);
if(ret!=KErrNone)
{
LOGPARSERR("iTxTimeSlots",ret,2,&KDynamicHSCSDInfo);
}
else
iHscsdInfo.iTxTimeSlots = iTxTimeSlots;
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,iCodings);
if(ret!=KErrNone)
{
LOGPARSERR("iCodings",ret,3,&KDynamicHSCSDInfo);
}
else
if(AsciiToNum(iCodings, digit)==KErrNone)
iHscsdInfo.iCodings = (RMobileCall::TMobileCallTchCoding) digit;
}
else
{
iHscsdInfo.iAiur=RMobileCall::EAiurBps9600;
iHscsdInfo.iRxTimeSlots=5;
iHscsdInfo.iTxTimeSlots=10;
iHscsdInfo.iCodings=RMobileCall::ETchCoding48;
}
item=iLine->CfgFile()->Item(KCommSetup);
if(item)
{
TPtrC8 portName,csyName;
TInt err=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,csyName); // The 3rd parameter (0) represents the index of the variable on the config file line
if (err!=KErrNone)
{
LOGPARSERR("csyName",err,0,&KCommSetup);
iCsyName.Copy(KDefaultCsyName);
}
else
iCsyName.Copy(csyName);
err=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,portName); // The 3rd parameter (1) represents the index of the variable on the config file line
if (err!=KErrNone)
{
LOGPARSERR("portName",err,1,&KCommSetup);
iPortName.Copy(KDefaultPortName);
}
else
iPortName.Copy(portName);
TInt dataRate,handshake;
err=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,dataRate); // The 3rd parameter (2) represents the index of the variable on the config file line
if (err!=KErrNone)
{
LOGPARSERR("dataRate",err,2,&KCommSetup);
iConfig.iRate=KDefaultCommPortRate;
}
else
iConfig.iRate=(TBps)dataRate;
err=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,handshake); // The 3rd parameter (3) represents the index of the variable on the config file line
if (err!=KErrNone)
{
LOGPARSERR("handshake",err,3,&KCommSetup);
iConfig.iHandshake=KDefaultHandshake;
}
else
iConfig.iHandshake=(TUint)handshake;
}
else
{
iCsyName.Copy(KDefaultCsyName);
iPortName.Copy(KDefaultPortName);
iConfig.iRate=KDefaultCommPortRate;
iConfig.iHandshake=KDefaultHandshake;
}
// Read in the Bearer Service information
item=iLine->CfgFile()->Item(KBearerService);
if(item)
{
TInt bearerCaps,bearerSpeed;
TInt err=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,bearerCaps); // The 3rd parameter (0) represents the index of the variable on the config file line
if (err!=KErrNone)
{
LOGPARSERR("bearerCaps",err,0,&KBearerService);
iBearerService.iBearerCaps=KDefaultBearerCaps;
}
else
iBearerService.iBearerCaps=bearerCaps;
err=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,bearerSpeed); // The 3rd parameter (1) represents the index of the variable on the config file line
if (err!=KErrNone)
{
LOGPARSERR("bearerSpeed",err,1,&KBearerService);
iBearerService.iBearerSpeed=KDefaultBearerSpeed;
}
else
iBearerService.iBearerSpeed=(RCall::TCallBearerSpeed)bearerSpeed;
}
else
{
iBearerService.iBearerCaps=KDefaultBearerCaps;
iBearerService.iBearerSpeed=KDefaultBearerSpeed;
}
iTimer=CSimTimer::NewL(iLine->iPhone);
iNtRas=CSimNtRas::NewL(iLine->iPhone);
CSimCall::ConstructL();
//If present read in remote party info tag
TPtrC8 callingname, remotenumber;
TInt delay=0;
item=iLine->CfgFile()->Item(KNotifyRemotePartyInfo);
TInt ret;
if (item)
{
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,delay);
if(ret!=KErrNone)
{
LOGPARSERR("delay",ret,0,&KNotifyRemotePartyInfo);
}
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,callingname);
if(ret!=KErrNone)
{
LOGPARSERR("callingname",ret,1,&KNotifyRemotePartyInfo);
}
ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,remotenumber);
if(ret!=KErrNone)
{
LOGPARSERR("remotenumber",ret,2,&KNotifyRemotePartyInfo);
}
iNotifyRemotePartyInfoTimer->iDelay = delay;
iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iDirection = RMobileCall::EDirectionUnknown;
iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iCallingName.Copy(callingname);
iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteNumber.iTelNumber.Copy(remotenumber);
iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteNumber.iTypeOfNumber = RMobilePhone::EInternationalNumber;
iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteNumber.iNumberPlan = RMobilePhone::EIsdnNumberPlan;
iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteIdStatus = RMobileCall::ERemoteIdentityAvailable;
}
else
{
iNotifyRemotePartyInfoTimer->iRemotePartyInfoV1.iRemoteIdStatus = RMobileCall::ERemoteIdentityUnknown;
}
LOGDATA1("...Finished parsing Data Call config parameters...");
}
CSimDataCall::~CSimDataCall()
/**
* Destroy all the objects constructed.
* CSimTimer and CSimSysAgent objects are destroyed here
*/
{
delete iNtRas;
delete iTimer;
if(iAnswerIncomingCall.iNotifyPending)
iLine->ResetAutoAnswerCallObject(this);
if(iMobileCallRLPList)
{
iMobileCallRLPList->Delete(0,iMobileCallRLPList->Count());
delete iMobileCallRLPList;
}
}
TInt CSimDataCall::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
*
* @param aTsyReqHandle
* @param aIpc IPc number representing the request
* @param aPackage data for the request
* @return KErrNone
*/
{
TAny* dataPtr=aPackage.Ptr1();
TAny* dataPtr2=aPackage.Ptr2();
LOGDATA2("CSimDataCall::ExtFunc: IPC Number is %d",aIpc);
// 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 EMobileCallGetMobileDataCallCaps:
return GetMobileDataCallCaps(aTsyReqHandle,aPackage.Des1n());
case EMobileCallGetMobileDataCallRLPRange:
return GetMobileDataCallRLPRange(aTsyReqHandle,
REINTERPRET_CAST(TInt*,dataPtr),
REINTERPRET_CAST(TDes8*,dataPtr2));
case EMobileCallSetDynamicHscsdParams:
return SetDynamicHSCSDParams(aTsyReqHandle,
REINTERPRET_CAST(RMobileCall::TMobileCallAiur*,dataPtr),
REINTERPRET_CAST(TInt*,dataPtr2));
case EMobileCallGetCurrentHscsdInfo:
return GetCurrentHSCSDInfo(aTsyReqHandle, aPackage.Des1n());
case EMobileCallGetMobileCallStatus:
return GetMobileCallStatus(aTsyReqHandle,
REINTERPRET_CAST(RMobileCall::TMobileCallStatus*,dataPtr));
case EMobileCallGetMobileCallInfo:
return GetMobileCallInfo(aTsyReqHandle,aPackage.Des1n());
//
// 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());
case EMobileCallNotifyMobileDataCallCapsChange:
return NotifyMobileDataCapsChange(aTsyReqHandle, aPackage.Des1n());
case EMobileCallNotifyHscsdInfoChange:
return NotifyHSCSDInfoChange(aTsyReqHandle, aPackage.Des1n());
case EMobileCallNotifyRemotePartyInfoChange:
return NotifyRemotePartyInfoChange(aTsyReqHandle, aPackage.Des1n());
default:
LOGDATA2("CSimDataCall::ExtFunc: Unsupported IPC detected - number %d",aIpc);
break;
}
return KErrNotSupported;
}
TInt CSimDataCall::CancelService(const TInt aIpc,const TTsyReqHandle aTsyReqHandle)
/**
* Cancel an outstanding request.
* @param aIpc The IPC number of the request that must be cancelled. Note: this is not the
* IPC number of the cancel request itself.
* @param aTsyReqHandle The TSY Request Handle of the request to be cancelled.
*/
{
switch(aIpc)
{
case EMobileCallNotifyMobileCallStatusChange:
return NotifyMobileCallStatusChangeCancel(aTsyReqHandle);
case EMobileCallNotifyMobileCallCapsChange:
return NotifyMobileCallCapsChangeCancel(aTsyReqHandle);
case EMobileCallNotifyMobileDataCallCapsChange:
return NotifyMobileDataCapsChangeCancel(aTsyReqHandle);
case EMobileCallSetDynamicHscsdParams:
return SetDynamicHSCSDParamsCancel(aTsyReqHandle);
case EMobileCallGetMobileDataCallCaps:
return GetMobileDataCallCapsCancel(aTsyReqHandle);
case EMobileCallGetMobileDataCallRLPRange:
return GetMobileDataCallRLPRangeCancel(aTsyReqHandle);
case EMobileCallNotifyHscsdInfoChange:
return NotifyHSCSDInfoChangeCancel(aTsyReqHandle);
case EMobileCallNotifyRemotePartyInfoChange:
return NotifyRemotePartyInfoChangeCancel();
default:
LOGDATA1("CSimDataCall::CancelService: No match for IPC, defering to base function");
break;
}
return CCallBase::CancelService(aIpc,aTsyReqHandle);
}
TInt CSimDataCall::Dial(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams,TDesC* /*aTelNumber*/)
/**
* Process a client's dial request.
*
* @param aTsyReqHandle
* @param aCallParams the call parameters
* @param aTelNumber The telephone number to dial
* @return KErrNone
*/
{
LOGDATA1(">>CSimDataCall::Dial");
iDialRequestHandle=aTsyReqHandle;
PopulateCallParams(aCallParams);
TInt err=ActionEvent(ECallEventDial,KErrNone);
if(err!=KErrNone)
ReqCompleted(aTsyReqHandle,err);
LOGDATA1("<<CSimDataCall::Dial");
return KErrNone;
}
TInt CSimDataCall::DialCancel(const TTsyReqHandle /*aTsyReqHandle*/)
/**
* Cancels a dial Request
*
* @param aTsyReqHandle
* @return KErrNone if successfully cancelled
*/
{
LOGDATA1(">>CSimDataCall::DialCancel");
switch(iState)
{
case RMobileCall::EStatusIdle:
case RMobileCall::EStatusConnected:
SimPanic(EIllegalCancelRequest); // A DialCancel should never reach the TSY in this state.
break;
case RMobileCall::EStatusDialling:
case RMobileCall::EStatusConnecting:
iTimer->Cancel();
TInt err;
err = KErrNone;
TRAP(err, ChangeStateL(RMobileCall::EStatusIdle,EFalse,EFalse));
if (err != KErrNone)
{
ReqCompleted(iDialRequestHandle, err);
}
else
{
ReqCompleted(iDialRequestHandle, KErrCancel);
}
break;
default:
LOGDATA2("CSimDataCall::DialCancel: No action taken - state: %d",iState);
break;
}
LOGDATA1("<<CSimDataCall::DialCancel");
return KErrNone;
}
TInt CSimDataCall::AnswerIncomingCall(const TTsyReqHandle aTsyReqHandle,const TDesC8* aCallParams)
/**
* Register a client's interest in answering the next incoming call.
* First register interest in incoming calls with the line, then, if a call
* is already ringing, start the answer procedure.
*
* @param aTsyReqHandle
* @param aCallParams the call parameters
* @return KErrNone
*/
{
LOGDATA1(">>CSimDataCall::AnswerIncomingCall");
TInt err=iLine->SetAutoAnswerCallObject(this);
if(err!=KErrNone)
{
ReqCompleted(aTsyReqHandle,err);
return KErrNone;
}
PopulateCallParams(aCallParams);
iAnswerIncomingCall.iNotifyPending=ETrue;
iAnswerIncomingCall.iNotifyHandle=aTsyReqHandle;
TInt ret=KErrNone;
if(iState==RMobileCall::EStatusRinging)
ActionEvent(ECallEventAnswerIncoming,KErrNone);
else if(iLine->iState==RMobileCall::EStatusRinging)
{
TRAP(ret,ret=ChangeStateL(RMobileCall::EStatusRinging,EFalse,EFalse));
if(ret == KErrNone)
{
ret = ActionEvent(ECallEventAnswerIncoming,KErrNone);
}
}
LOGDATA1("<<CSimDataCall::AnswerIncomingCall");
return ret;
}
TInt CSimDataCall::AnswerIncomingCallCancel(const TTsyReqHandle /*aTsyReqHandle*/)
/**
* Cancels a AnswerIncomingCall Request
*
* @param aTsyReqHandle
* @return KErrNone if successfully cancelled
*/
{
LOGDATA1(">>CSimDataCall::AnswerIncomingCallCancel");
if(iAnswerIncomingCall.iNotifyPending)
{
iAnswerIncomingCall.iNotifyPending=EFalse;
iLine->ResetAutoAnswerCallObject(this);
ReqCompleted(iAnswerIncomingCall.iNotifyHandle,KErrCancel);
}
LOGDATA1("<<CSimDataCall::AnswerIncomingCallCancel");
return KErrNone;
}
TInt CSimDataCall::Connect(const TTsyReqHandle aTsyReqHandle,const TDesC8* /*aCallParams*/)
{
ReqCompleted(aTsyReqHandle,KErrNotSupported);
return KErrNone;
}
TInt CSimDataCall::ConnectCancel(const TTsyReqHandle aTsyReqHandle)
{
ReqCompleted(aTsyReqHandle,KErrNotSupported);
return KErrNone;
}
TInt CSimDataCall::HangUp(const TTsyReqHandle aTsyReqHandle)
/**
* Process a client's HangUp request.
*
* @param aTsyReqHandle
* @return KErrNone
*/
{
LOGDATA1(">>CSimDataCall::HangUp");
iHangUpRequestHandle=aTsyReqHandle;
TInt err=ActionEvent(ECallEventHangUp,KErrNone);
if(err!=KErrNone)
ReqCompleted(aTsyReqHandle,err);
LOGDATA1("<<CSimDataCall::HangUp");
return KErrNone;
}
TInt CSimDataCall::HangUpCancel(const TTsyReqHandle /*aTsyReqHandle*/)
/**
* Cancels a HangUp Request
*
* @param aTsyReqHandle
* @return KErrNone if successfully cancelled
*/
{
LOGDATA1(">>CSimDataCall::HangUpCancel");
switch(iState)
{
case RMobileCall::EStatusIdle:
SimPanic(EIllegalCancelRequest); // A DialCancel should never reach the TSY in this state.
break;
case RMobileCall::EStatusDisconnecting:
iTimer->Cancel();
TInt err;
err = KErrNone;
TRAP(err, ChangeStateL(RMobileCall::EStatusIdle,EFalse,EFalse));
if (err != KErrNone)
{
ReqCompleted(iHangUpRequestHandle, err);
}
else
{
ReqCompleted(iHangUpRequestHandle, KErrCancel);
}
break;
default:
LOGDATA2("CSimDataCall::HangUpCancel: No action taken - state: %d",iState);
break;
}
LOGDATA1("<<CSimDataCall::HangUpCancel");
return KErrNone;
}
TInt CSimDataCall::RelinquishOwnership()
{
return KErrNotSupported;
}
TInt CSimDataCall::GetBearerServiceInfo(const TTsyReqHandle aTsyReqHandle,RCall::TBearerService* aBearerService)
/**
* Retrieves the bearer service info. Bearer service information is only valid
* when the call is active.
*/
{
if(iState!=RMobileCall::EStatusConnected)
{
ReqCompleted(aTsyReqHandle,KErrEtelCallNotActive);
return KErrNone;
}
*aBearerService=iBearerService;
ReqCompleted(aTsyReqHandle,KErrNone);
return KErrNone;
}
TInt CSimDataCall::GetCallParams(const TTsyReqHandle aTsyReqHandle, TDes8* aCallParams)
/**
* Retrives the call parameters. This function must handle both core and Multimode
* extension versions of the function. Call parameter information is only valid
* when the call is active.
*/
{
if(iState!=RMobileCall::EStatusConnected)
{
ReqCompleted(aTsyReqHandle,KErrEtelCallNotActive);
return KErrNone;
}
TPckg<RCall::TCallParams>* callParamPckg=(TPckg<RCall::TCallParams>*)aCallParams;
RCall::TCallParams& callParam=(*callParamPckg)();
if(callParam.ExtensionId()==RMobileCall::KETelMobileDataCallParamsV1)
{
// If the passed package is MobileParams, then we can just unpackage and copy.
RMobileCall::TMobileDataCallParamsV1Pckg* mobileCallParamPckg=(RMobileCall::TMobileDataCallParamsV1Pckg*)aCallParams;
RMobileCall::TMobileDataCallParamsV1& mobileCallParam=(*mobileCallParamPckg)();
// Check that the data structure is supported by the simulated TSY version
TInt err = iPhone->CheckSimTsyVersion(mobileCallParam);
if(err != KErrNone)
{
ReqCompleted(aTsyReqHandle, err);
return KErrNone;
}
mobileCallParam=iMobileCallParams;
}
else if(callParam.ExtensionId()==RMobileCall::KETelMobileHscsdCallParamsV1)
{
TPckg<RMobileCall::TMobileHscsdCallParamsV1>* mobileCallParamPckg=(TPckg<RMobileCall::TMobileHscsdCallParamsV1>*)aCallParams;
RMobileCall::TMobileHscsdCallParamsV1& mobileCallParam=(*mobileCallParamPckg)();
// Check that the data structure is supported by the simulated TSY version
TInt err = iPhone->CheckSimTsyVersion(mobileCallParam);
if(err != KErrNone)
{
ReqCompleted(aTsyReqHandle, err);
return KErrNone;
}
mobileCallParam=iHscsdSettings;
}
else
{
// If, however, its a core (or an unrecognised extension), we must only copy the
// core parameters.
callParam.iSpeakerControl=iMobileCallParams.iSpeakerControl;
callParam.iSpeakerVolume=iMobileCallParams.iSpeakerVolume;
callParam.iInterval=iMobileCallParams.iInterval;
callParam.iWaitForDialTone=iMobileCallParams.iWaitForDialTone;
}
ReqCompleted(aTsyReqHandle,KErrNone);
return KErrNone;
}
TInt CSimDataCall::LoanDataPort(const TTsyReqHandle aReqHandle,RCall::TCommPort* aCommPort)
/**
* Loans the comm port to a client for subsequent streaming of data.
* For the comm port to be loaned the call must be active and the port unloaned.
*/
{
if(iState!=RMobileCall::EStatusConnected)
{
ReqCompleted(aReqHandle,KErrEtelCallNotActive);
return KErrNone;
}
if(iCommPortLoaned)
{
ReqCompleted(aReqHandle,KErrEtelPortAlreadyLoaned);
return KErrNone;
}
aCommPort->iCsy.Copy(iCsyName);
aCommPort->iPort.Copy(iPortName);
iCommPortLoaned=ETrue;
ReqCompleted(aReqHandle,KErrNone);
return KErrNone;
}
TInt CSimDataCall::LoanDataPortCancel(const TTsyReqHandle)
/**
* Cancels the LoanDataPort request.
* The LoanDataPort function completes synchronously, so there is nothing to cancel.
*/
{
return KErrNone;
}
TInt CSimDataCall::RecoverDataPort(const TTsyReqHandle aReqHandle)
/**
* Recovers the comm port.
* The comm port must be loaned in order to recover it.
*/
{
if(!iCommPortLoaned)
{
ReqCompleted(aReqHandle,KErrEtelPortNotLoanedToClient);
return KErrNone;
}
iNtRas->Terminate();
iCommPortLoaned=EFalse;
ReqCompleted(aReqHandle,KErrNone);
return KErrNone;
}
TInt CSimDataCall::ActionEvent(TCallEvent aEvent,TInt aStatus)
/**
* Entry point when an event has occured that may advance the state machine.
* The aEvent parameter describes the event.
*
* This function contains the main state machine for the data call. The outer layer
* switches on the event type. Where appropriate, there are inner layer switches
* or conditional statements to handle the different responses that may be required to
* the same event occurring in different states.
*
* @param aEvent The Call event to handle
* @return value represents the error state caused by the attempted state machine jump.
*/
{
TInt ret=KErrNone;
__ASSERT_ALWAYS(iState!=RMobileCall::EStatusUnknown,SimPanic(ECallStatusUnknownIllegal));
switch(aEvent)
{
case ECallEventDial:
LOGDATA1(">>CSimDataCall::ActionEvent = [ECallEventDial]");
if(iState==RMobileCall::EStatusIdle)
{
TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusDialling,EFalse,EFalse));
if(ret==KErrNone)
iTimer->Start(iDiallingPause,this);
}
else
return KErrEtelCallAlreadyActive;
break;
case ECallEventHangUp:
{
LOGDATA1(">>CSimDataCall::ActionEvent = [ECallEventHangUp]");
switch(iState)
{
case RMobileCall::EStatusConnected:
iCommPortLoaned=EFalse;
iNtRas->Terminate();
// Note: No "break;" - fall through to the rest of the discconnecting code...
case RMobileCall::EStatusDialling:
case RMobileCall::EStatusRinging:
case RMobileCall::EStatusAnswering:
case RMobileCall::EStatusConnecting:
iTimer->Cancel();
TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusDisconnecting,EFalse,EFalse));
if(ret==KErrNone)
iTimer->Start(iDisconnectingPause,this);
break;
default:
return KErrEtelCallNotActive;
}
}
break;
case ECallEventIncomingCall:
LOGDATA1(">>CSimDataCall::ActionEvent = [ECallEventIncomingCall]");
if(iState==RMobileCall::EStatusIdle)
{
if(iAnswerIncomingCall.iNotifyPending)
{
TRAP(ret, ret=ProcessAnswerIncomingCallL());
}
else
{
TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusRinging,EFalse,EFalse));
if(ret!=KErrNone)
return ret;
}
}
else
return KErrEtelCallAlreadyActive;
break;
case ECallEventAnswerIncoming:
LOGDATA1(">>CSimDataCall::ActionEvent = [ECallEventAnswerIncoming]");
if(iState==RMobileCall::EStatusRinging)
{
TRAP(ret, ret=ProcessAnswerIncomingCallL());
}
else
SimPanic(EIllegalStateInconsistancy); // The state is checked in AnswerIncomingCall, so there's been an inconsistancy if the state is out of line.
break;
case ECallEventRemoteHangup:
LOGDATA1(">>CSimDataCall::ActionEvent = [ECallEventRemoteHangup]");
if(iState==RMobileCall::EStatusConnected)
{
TRAP(ret, ret=ProcessRemoteHangupL());
}
else
SimPanic(EIllegalStateInconsistancy); // The state is checked in RemoteHangup, so there's been an inconsistancy if the state is out of line.
break;
case ECallEventTimeOut:
{
LOGDATA1(">>CSimVoiceCall::ActionEvent = [ECallEventTimeOut]");
switch(iState)
{
case RMobileCall::EStatusDialling:
LOGDATA1(">>CSimDataCall::State = [EStatusDialling]");
TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusConnecting,EFalse,EFalse));
if(ret==KErrNone)
iTimer->Start(iConnectingPause,this);
return ret;
case RMobileCall::EStatusConnecting:
LOGDATA1(">>CSimDataCall::State = [EStatusConnecting]");
// If the config file has not spec'ed a CSY, then fail the dial...
if(iCsyName.Length()==0)
{
ReqCompleted(iDialRequestHandle,KErrEtelNoCarrier);
TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusIdle,EFalse,EFalse));
__ASSERT_ALWAYS(ret==KErrNone,SimPanic(EIllegalStateInconsistancy));
return KErrNone;
}
ret=iNtRas->Connect(iCsyName,iPortName,iConfig,this);
if(ret!=KErrNone)
ReqCompleted(iDialRequestHandle,ret);
return ret;
case RMobileCall::EStatusDisconnecting:
LOGDATA1(">>CSimDataCall::State = [EStatusDisconnecting]");
TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusIdle,EFalse,EFalse));
ReqCompleted(iHangUpRequestHandle,ret);
return ret;
case RMobileCall::EStatusAnswering:
LOGDATA1(">>CSimDataCall::State = [EStatusAnswering]");
TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusConnected,EFalse,EFalse));
ReqCompleted(iAnswerIncomingCall.iNotifyHandle,ret);
return ret;
default:
LOGDATA2(">>CSimDataCall::State = [%d]",iState);
break;
}
}
break;
case ECallEventNtRasConnected:
if(aStatus!=KErrNone)
{
ReqCompleted(iDialRequestHandle,aStatus);
TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusIdle,EFalse,EFalse));
__ASSERT_ALWAYS(ret==KErrNone,SimPanic(EIllegalStateInconsistancy));
return KErrNone;
}
else
{
TRAP(ret, ret=ChangeStateL(RMobileCall::EStatusConnected,EFalse,EFalse));
ChangeDynamicInfo();
ReqCompleted(iDialRequestHandle,ret);
return KErrNone;
}
default:
SimPanic(EIllegalStateInconsistancy);
break;
}
return ret;
}
void CSimDataCall::TimerCallBack(TInt /*aId*/)
/**
* Timer callback function. When the timer goes off, it will call back into this
* function for further processing.
*/
{
LOGDATA1(">>CSimDataCall::TimerCallBack");
TInt err=ActionEvent(ECallEventTimeOut,KErrNone);
__ASSERT_ALWAYS(err==KErrNone,SimPanic(ETimeOutEventActionFailed));
LOGDATA1("<<CSimDataCall::TimerCallBack");
}
TInt CSimDataCall::ProcessAnswerIncomingCallL()
/**
* Answers an Incoming Call.
* First the call state must be changed to "answering", then the flag indicating
* that an answer incoming call request is no longer pending. Finally, a new
* call object must be assigned to receive the details of the next incoming call.
*/
{
LOGDATA1(">>CSimDataCall::ProcessAnswerIncomingCall");
TInt ret=ChangeStateL(RMobileCall::EStatusAnswering,EFalse,EFalse);
if(ret!=KErrNone)
return ret;
iTimer->Start(iAnswerIncomingPause,this);
iAnswerIncomingCall.iNotifyPending=EFalse;
iLine->ResetAutoAnswerCallObject(this);
LOGDATA1("<<CSimDataCall::ProcessAnswerIncomingCall");
return ret;
}
TInt CSimDataCall::ProcessRemoteHangupL()
/**
* Hangs up a call from the remote end.
* First the call state must be changed to "disconnecting", then the flag indicating
* that a remote hangup request is no longer pending. Finally, a new
* call object must be assigned to be the next remotely hung up call.
*/
{
LOGDATA1(">>CSimDataCall::ProcessRemoteHangupL");
TInt ret=ChangeStateL(RMobileCall::EStatusDisconnecting,EFalse,EFalse);
if(ret!=KErrNone)
return ret;
iTimer->Start(iRemoteHangupPause,this);
iLine->ResetRemoteHangupCallObject(this);
LOGDATA1("<<CSimDataCall::ProcessRemoteHangupL");
return ret;
}
void CSimDataCall::PopulateCallParams(const TDesC8* aCallParams)
/**
* This function populates the call parameter member variable iMobileCallParams.
* The function must handle core and multimode extension call parameters.
* @param aCallParams A pointer to the call parameter variable.
*/
{
TPckg<RCall::TCallParams>* callParamPckg=(TPckg<RCall::TCallParams>*)aCallParams;
RCall::TCallParams& callParam=(*callParamPckg)();
if(callParam.ExtensionId()==RMobileCall::KETelMobileDataCallParamsV1)
{
// If the passed package is MobileParams, then we can just unpackage and copy.
RMobileCall::TMobileDataCallParamsV1Pckg* mobileCallParamPckg=(RMobileCall::TMobileDataCallParamsV1Pckg*)aCallParams;
RMobileCall::TMobileDataCallParamsV1& mobileCallParam=(*mobileCallParamPckg)();
iHscsdCall=EFalse;
iMobileCallParams=mobileCallParam;
}
else if(callParam.ExtensionId()==RMobileCall::KETelMobileHscsdCallParamsV1)
{
TPckg<RMobileCall::TMobileHscsdCallParamsV1>* mobileCallParamPckg=(TPckg<RMobileCall::TMobileHscsdCallParamsV1>*)aCallParams;
RMobileCall::TMobileHscsdCallParamsV1& mobileCallParam=(*mobileCallParamPckg)();
iHscsdCall=ETrue;
iHscsdSettings=mobileCallParam;
}
else
{
// If, however, its core (or an unrecognised extension), we must first reset the member
// member variable before copying just the core parameters.
RMobileCall::TMobileDataCallParamsV1 mobileCallParam;
iMobileCallParams=mobileCallParam;
iHscsdCall=EFalse;
iMobileCallParams.iSpeakerControl=callParam.iSpeakerControl;
iMobileCallParams.iSpeakerVolume=callParam.iSpeakerVolume;
iMobileCallParams.iInterval=callParam.iInterval;
iMobileCallParams.iWaitForDialTone=callParam.iWaitForDialTone;
}
}
void CSimDataCall::NTRasCallBack(TInt aStatus)
/**
* NTRas callback function. This function will be called when the NTRAS
* Server has responded.
* @param aStatus Standard error value, indicating the success or failure of the NTRAS
* connection.
*/
{
TInt err=ActionEvent(ECallEventNtRasConnected,aStatus);
__ASSERT_ALWAYS(err==KErrNone,SimPanic(EIllegalStateInconsistancy));
}
TUint CSimDataCall::Caps()
/**
* Return the current capabilities of this call.
* @return TUint Current call capabilities.
*/
{
TUint caps=RCall::KCapsData;
GenerateCoreCallCaps(caps);
if(iState==RMobileCall::EStatusConnected)
{
if(iCommPortLoaned)
caps|=RCall::KCapsRecoverDataPort;
else
caps|=RCall::KCapsLoanDataPort;
}
return caps;
}
TInt CSimDataCall::GetMobileDataCallCaps(const TTsyReqHandle aTsyReqHandle, TDes8* aCaps)
/**
*
* @param aTsyReqHandle specifies the request handle.
* @param aCaps is used to return the retrieved capabilities to the client.
* @return value returns the result of this operation
*/
{
TPckg<RMobileCall::TMobileCallDataCapsV1>* mobileCallCapsPckg=(TPckg<RMobileCall::TMobileCallDataCapsV1>*)aCaps;
RMobileCall::TMobileCallDataCapsV1& mobileCallCaps=(*mobileCallCapsPckg)();
// Check that the data structure is supported by the simulated TSY version
TInt err = iPhone->CheckSimTsyVersion(mobileCallCaps);
if(err != KErrNone)
{
ReqCompleted(aTsyReqHandle, err);
return KErrNone;
}
if(mobileCallCaps.ExtensionId()==KETelExtMultimodeV1)
{
mobileCallCaps=iMobileCallCaps;
ReqCompleted(aTsyReqHandle,KErrNone);
return KErrNone;
}
else
{
ReqCompleted(aTsyReqHandle,KErrNotFound);
return KErrNotFound;
}
}
TInt CSimDataCall::GetMobileDataCallCapsCancel(const TTsyReqHandle aTsyReqHandle)
/**
*
* @param aTsyReqHandle specifies the request handle to be canceled
* @return value returns the result of this operation
*/
{
ReqCompleted(aTsyReqHandle,KErrNone);
return KErrNone;
}
TInt CSimDataCall::SetDynamicHSCSDParams(const TTsyReqHandle aTsyReqHandle, RMobileCall::TMobileCallAiur* aAiur, TInt* aRxTimeslots)
/**
*
* @param aTsyReqHandle specifies the request handle.
* @param aAiur is used to dynamically change Aiur for this call
* @param aRxTimeslots is used to dynamically change RxTimeslots for this call
* @return value returns the result of this operation
*/
{
iHscsdInfo.iRxTimeSlots=*aRxTimeslots;
iHscsdInfo.iAiur=*aAiur;
iHscsdSettings.iWantedRxTimeSlots=*aRxTimeslots;
iHscsdSettings.iWantedAiur=*aAiur;
if(iNotifyInfo.iNotifyPending)
{
*(RMobileCall::TMobileCallHscsdInfoV1*)iNotifyInfo.iNotifyData=iHscsdInfo;
iNotifyInfo.iNotifyPending=EFalse;
ReqCompleted(iNotifyInfo.iNotifyHandle,KErrNone);
}
ReqCompleted(aTsyReqHandle,KErrNone);
return KErrNone;
}
TInt CSimDataCall::SetDynamicHSCSDParamsCancel(const TTsyReqHandle aTsyReqHandle)
/**
*
* @param aTsyReqHandle specifies the request handle to be canceled
* @return value returns the result of this operation
*/
{
ReqCompleted(aTsyReqHandle,KErrNone);
return KErrNone;
}
TInt CSimDataCall::GetCurrentHSCSDInfo(const TTsyReqHandle aTsyReqHandle, TDes8* aInfo)
/**
*
* @param aTsyReqHandle specifies the request handle.
* @param aInfo is used to return the current Hscsd information to the client
* @return value returns the result of this operation
*/
{
TPckg<RMobileCall::TMobileCallHscsdInfoV1>* hscsdInfoPckg=(TPckg<RMobileCall::TMobileCallHscsdInfoV1>*)aInfo;
RMobileCall::TMobileCallHscsdInfoV1& hscsdInfo=(*hscsdInfoPckg)();
// Check that the data structure is supported by the simulated TSY version
TInt err = iPhone->CheckSimTsyVersion(hscsdInfo);
if(err != KErrNone)
{
ReqCompleted(aTsyReqHandle, err);
return KErrNone;
}
if(hscsdInfo.ExtensionId()==KETelExtMultimodeV1)
{
hscsdInfo=iHscsdInfo;
ReqCompleted(aTsyReqHandle,KErrNone);
return KErrNone;
}
else
{
ReqCompleted(aTsyReqHandle,KErrNotFound);
return KErrNotFound;
}
}
TInt CSimDataCall::NotifyHSCSDInfoChange(const TTsyReqHandle aTsyReqHandle, TDes8* aHSCSDInfo)
/**
*
* @param aTsyReqHandle specifies the request handle.
* @param aInfo is used to return the current Hscsd information when the notification completes
* @return value returns the result of this operation
*/
{
__ASSERT_ALWAYS(!iNotifyInfo.iNotifyPending,SimPanic(ENotificationAlreadyPending));
iNotifyInfo.iNotifyPending = ETrue;
iNotifyInfo.iNotifyHandle = aTsyReqHandle;
TPckg<RMobileCall::TMobileCallHscsdInfoV1>* hscsdInfo = (TPckg<RMobileCall::TMobileCallHscsdInfoV1>*)aHSCSDInfo;
RMobileCall::TMobileCallHscsdInfoV1& hscsdInfoV1 = (*hscsdInfo)();
// Check that the data structure is supported by the simulated TSY version
TInt err = iPhone->CheckSimTsyVersion(hscsdInfoV1);
if(err != KErrNone)
{
ReqCompleted(aTsyReqHandle, err);
return KErrNone;
}
iNotifyInfo.iNotifyData = &hscsdInfoV1;
return KErrNone;
}
TInt CSimDataCall::NotifyHSCSDInfoChangeCancel(const TTsyReqHandle /*aTsyReqHandle*/)
/**
*
* @param aTsyReqHandle specifies the request handle to be canceled
* @return value returns the result of this operation
*/
{
if(iNotifyInfo.iNotifyPending)
{
iNotifyInfo.iNotifyPending=EFalse;
ReqCompleted(iNotifyInfo.iNotifyHandle,KErrCancel);
}
return KErrNone;
}
TInt CSimDataCall::NotifyMobileDataCapsChange(const TTsyReqHandle aTsyReqHandle, TDes8* /*aCaps*/)
{
/**
*
* @param aTsyReqHandle specifies the request handle to be canceled
* @return value returns the result of this operation
*/
ReqCompleted(aTsyReqHandle,KErrNotSupported);
return KErrNotSupported;
}
TInt CSimDataCall::NotifyMobileDataCapsChangeCancel(const TTsyReqHandle aTsyReqHandle)
/**
*
* @param aTsyReqHandle specifies the request handle to be canceled
* @return value returns the result of this operation
*/
{
ReqCompleted(aTsyReqHandle,KErrNone);
return KErrNone;
}
TInt CSimDataCall::GetMobileDataCallRLPRange(const TTsyReqHandle aTsyReqHandle, TInt* aRLPVersion, TDes8* aRLPRange)
{
/**
*
* @param aTsyReqHandle specifies the request handle to be canceled
* @param aRLPVersion specifies the version for RLP range retrieval
* @param aRLPRange is used to return the requested RLP range to the client
* @return value returns the result of this operation
*/
TInt ret=SearchRetrieveRlp(aRLPVersion,aRLPRange);
ReqCompleted(aTsyReqHandle,ret);
return ret;
}
TInt CSimDataCall::GetMobileDataCallRLPRangeCancel(const TTsyReqHandle aTsyReqHandle)
/**
*
* @param aTsyReqHandle specifies the request handle to be canceled
* @return value returns the result of this operation
*/
{
ReqCompleted(aTsyReqHandle,KErrNone);
return KErrNone;
}
void CSimDataCall::ChangeDynamicInfo()
/**
*
* Private function to alter the current Hscsd information
*/
{
if(iHscsdCall)
{
// Change to the requested settings
iHscsdInfo.iAiur=iHscsdSettings.iWantedAiur;
iHscsdInfo.iRxTimeSlots=iHscsdSettings.iWantedRxTimeSlots;
iHscsdInfo.iTxTimeSlots=iHscsdSettings.iMaxTimeSlots-iHscsdSettings.iWantedRxTimeSlots;
iHscsdInfo.iCodings=(RMobileCall::TMobileCallTchCoding) iHscsdSettings.iCodings;
// Complete a pending notification event for changes in dynamic info of HSCSD
if(iNotifyInfo.iNotifyPending)
{
*(RMobileCall::TMobileCallHscsdInfoV1*)iNotifyInfo.iNotifyData=(RMobileCall::TMobileCallHscsdInfoV1)iHscsdInfo;
ReqCompleted(iNotifyInfo.iNotifyHandle,KErrNone);
}
}
}
TInt CSimDataCall::SearchRetrieveRlp(TInt* aRLPVersion,TDes8* aRLPRange)
/**
*
* Private function to search the list of available RLP ranges per version
* and return the appropriate range.
*/
{
TInt count = iMobileCallRLPList->Count();
TMobileCallRLPItem item;
for(TInt i=0; i<count; i++)
{
item=iMobileCallRLPList->At(i);
if(item.iRlpVersion==*aRLPVersion)
{
*(RMobileCall::TMobileDataRLPRangesV1*)aRLPRange=item.iMobileCallRLP;
return KErrNone;
}
}
return KErrNotFound;
}