// Copyright (c) 2000-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:+ −
// \file mnetwork.cpp+ −
// Basic GSM Network and Operator information Implementation file.+ −
// This file contains the implementation of the CATNetworkInfo, CATDetectNetwork,+ −
// CNotifyNetworkRegistrationStatusChange and CCurrentNetworkChangedNotify classes.+ −
// Find the current Network Operator in Numeric, Long and Short formats.+ −
// NB - Some phones do not fully support all the formats, if any. The commands are + −
// sent in sequence starting with the query command (AT+COPS?). All the phones currently+ −
// supported implement this command. Valid responses are set in the TMobilePhoneLocationAreaV1+ −
// and the TMobilePhoneNetworkInfoV1 structures and the Network's status is set to Current.+ −
// + −
//+ −
+ −
#include <et_phone.h>+ −
#include "mnetwork.h"+ −
#include "mSLOGGER.H"+ −
#include "ATIO.H"+ −
#include "Matstd.h"+ −
#include "mPHONE.H"+ −
+ −
const TInt KSettlingPause=1; //< This pause is used at the end of the network information queries. The Nokia 8210 has been shown to require this, if it is not to error the next command.+ −
+ −
_LIT8(KSetAndReadOperatorCommandNumeric, "AT+COPS=3,2;+COPS?\r");+ −
_LIT8(KSetAndReadOperatorCommandShort, "AT+COPS=3,1;+COPS?\r");+ −
_LIT8(KSetAndReadOperatorCommandLong, "AT+COPS=3,0;+COPS?\r");+ −
+ −
_LIT8(KGetCurrentOperatorCommand, "AT+COPS?\r");+ −
_LIT8(KOperatorResponse,"+COPS:");+ −
+ −
_LIT8(KDetectNetworkCommand,"AT+COPS=?");+ −
+ −
+ −
static TInt NetworkIdL(const TDesC8& aCode,+ −
RMobilePhone::TMobilePhoneNetworkCountryCode& aCountryCode, + −
RMobilePhone::TMobilePhoneNetworkIdentity& aNetworkIdentity)+ −
{+ −
/**+ −
* Utility function to translate the 5 digit ASCII network identification returned by the ME+ −
* into Mobile Country Code (aCountryCode) and a Mobile Network Code (aNetworkIdentity) strings.+ −
* Tbe format returned by the ME is XXXYY, where XXX represents the Mobile Country Code and YY+ −
* represents the Mobile Network Code.+ −
*/+ −
if (aCode.Length()!=5)+ −
{+ −
return KErrGeneral;+ −
}+ −
+ −
aCountryCode.SetLength(3);+ −
aCountryCode[0] = aCode[0];+ −
aCountryCode[1] = aCode[1];+ −
aCountryCode[2] = aCode[2];+ −
+ −
aNetworkIdentity.SetLength(2);+ −
aNetworkIdentity[0] = aCode[3];+ −
aNetworkIdentity[1] = aCode[4];+ −
return KErrNone;+ −
}+ −
+ −
+ −
CATNetworkInfo* CATNetworkInfo::NewL(CATIO* aIo,CTelObject* aTelObject,CATInit* aInit,CPhoneGlobals* aPhoneGlobals)+ −
/**+ −
* Standard two-phase constructor.+ −
*/+ −
{+ −
CATNetworkInfo* netInfo = new(ELeave) CATNetworkInfo(aIo, aTelObject, aInit, aPhoneGlobals);+ −
CleanupStack::PushL(netInfo);+ −
netInfo->ConstructL();+ −
CleanupStack::Pop();+ −
return netInfo;+ −
}+ −
+ −
CATNetworkInfo::CATNetworkInfo(CATIO* aIo, CTelObject* aTelObject, CATInit* aInit,CPhoneGlobals* aPhoneGlobals)+ −
: CATCommands(aIo,aTelObject,aInit,aPhoneGlobals)+ −
,iPhoneGlobals(aPhoneGlobals)+ −
{}+ −
+ −
CATNetworkInfo::~CATNetworkInfo()+ −
/**+ −
* Standard Destructor.+ −
* Note the NULLing of the iATNetworkInfo pointer. This should prevent any unwanted calling+ −
* of this function from the "end of command" sequence after the class' destruction.+ −
*/+ −
{+ −
iIo->RemoveExpectStrings(this);+ −
iPhoneGlobals->iATNetworkInfo=NULL;+ −
}+ −
+ −
void CATNetworkInfo::Start(TTsyReqHandle aTsyReqHandle,TAny* aParam)+ −
/**+ −
* This is the standard entry point for retrieving the Network Information.+ −
*/+ −
{+ −
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tStarting Operator Info."));+ −
iReqHandle = aTsyReqHandle;+ −
if (aParam!=NULL)+ −
{+ −
TTsyNetworkInfo* info = static_cast<TTsyNetworkInfo*>(aParam);+ −
iNetworkInfo.iNetworkInfoPckg = info->iNetworkInfoPckg;+ −
iNetworkInfo.iArea = info->iArea;+ −
}+ −
+ −
//+ −
// This object is not always started thru the CATBase::ExecuteCommand+ −
// So we sometimes have to manually control the flow control of iEventSignalActive+ −
iPhoneGlobals->iEventSignalActive = ETrue;+ −
iCancelled=EFalse;+ −
+ −
if (iReqHandle==0)+ −
iTelObject->FlowControlSuspend();+ −
StartGetOperator();+ −
}+ −
+ −
void CATNetworkInfo::CheckOperator()+ −
/**+ −
* This function is called whenever an EventSignal Completes. It is a second entry point for the command.+ −
* It checks CPhoneGlobals iPhoneStatus.iNetworkChanged and calls this function if it detects that the+ −
* networking information has changed and therefore the CPhoneGlobals data may be out of date and needs+ −
* to be refreshed.+ −
*/+ −
{+ −
Start(0,0);+ −
}+ −
+ −
+ −
void CATNetworkInfo::EventSignal(TEventSource aSource)+ −
/**+ −
* This function contains the state machine for the command. The states flow consecutively and are+ −
* described below.+ −
* + −
* \par EATGetCurrentOperatorWriteComplete+ −
* Wait for the "AT+COPS?" write to complete+ −
*+ −
* \par EATGetCurrentOperatorReadComplete+ −
* Parse the "AT+COPS?" response. If it gets an "ERROR" back it assume that no COPS commands are+ −
* supported, so complete the request with an error. If it is supported, parse the result and proceed+ −
* to retrieve the numeric network code with "AT+COPS=3,2;+COPS?"+ −
*+ −
* \par EATNumericOperatorWaitForWriteComplete+ −
* Wait for the "AT+COPS=3,2;+COPS?" to complete+ −
*+ −
* \par EATSetNumericOperatorReadComplete+ −
* Parse the numeric network code if available. Proceed to retrieve the short network code with+ −
* "AT+COPS=3,1;+COPS?".+ −
*+ −
* \par EATShortOperatorWaitForWriteComplete+ −
* Wait for the "AT+COPS=3,1;+COPS?" write to complete.+ −
*+ −
* \par EATSetShortOperatorReadComplete+ −
* Parse the short network name if available. Proceed to retrieve the long network name with+ −
* "AT+COPS=3,0;+COPS?".+ −
*+ −
* \par EATLongOperatorWaitForWriteComplete+ −
* Wait for the "AT+COPS=3,0;+COPS?" write to complete.+ −
*+ −
* \par EATSetLongOperatorReadComplete+ −
* Parse the long network name if available. Proceed to complete the request. + −
* Check for outstanding current network operator notifications at this point. + −
*+ −
* \par EATWaitForStopState+ −
* This state is used when stopping the state machine to ensure that a pending modem response has been+ −
* retrieved before freeing up the Multimode TSY to send more commands. Prematurely stopping the state machine+ −
* is usually forced by a client cancel request.+ −
*+ −
* \par EATWaitForSettlingTimeout+ −
* This state is used to provide a pause at the end of the network information queries. The Nokia 8210+ −
* has been shown to require this, if it is not to arbitrarily error the next command.+ −
*/+ −
{+ −
if ((aSource==ETimeOutCompletion)&&(iState!=EATWaitForSettlingTimeout))+ −
{+ −
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tTimeout Error during Operator read"));+ −
RemoveStdExpectStrings();+ −
Complete(KErrTimedOut,aSource);+ −
return;+ −
}+ −
+ −
switch(iState)+ −
{+ −
case EATGetCurrentOperatorWriteComplete:+ −
__ASSERT_ALWAYS(aSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected));+ −
{+ −
iIo->WriteAndTimerCancel(this);+ −
StandardWriteCompletionHandler(aSource, 5);+ −
iState=EATGetCurrentOperatorReadComplete;+ −
}+ −
break;+ −
+ −
case EATGetCurrentOperatorReadComplete:+ −
__ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));+ −
{+ −
iIo->WriteAndTimerCancel(this);+ −
TInt ret(ValidateExpectString());+ −
RemoveStdExpectStrings();+ −
if (ret != KErrNone)+ −
{+ −
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\t+COPS? not supported"));+ −
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tSet Operator Command not supported")); // An assumption+ −
Complete(ret, aSource); // No point in sending the Set Command.+ −
}+ −
else if (iCancelled)+ −
{+ −
Complete(KErrCancel, aSource); // Cancel state machine in safe place+ −
}+ −
else+ −
{+ −
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\t+COPS? supported"));+ −
TRAPD(ret,ParseOperatorResponseL());+ −
if (ret != KErrNone)+ −
{+ −
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tError parsing +COPS?"));+ −
} + −
iTxBuffer.Copy(KSetAndReadOperatorCommandNumeric); // AT+COPS=3,2;+COPS?+ −
iIo->Write(this, iTxBuffer);+ −
iIo->SetTimeOut(this, 5000);+ −
iState=EATNumericOperatorWaitForWriteComplete;+ −
}+ −
}+ −
break; + −
+ −
case EATNumericOperatorWaitForWriteComplete:+ −
__ASSERT_ALWAYS(aSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected));+ −
{+ −
iIo->WriteAndTimerCancel(this);+ −
StandardWriteCompletionHandler(aSource, 5);+ −
iState=EATSetNumericOperatorReadComplete;+ −
}+ −
break;+ −
+ −
case EATSetNumericOperatorReadComplete:+ −
__ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));+ −
{+ −
iIo->WriteAndTimerCancel(this);+ −
TInt ret(ValidateExpectString());+ −
RemoveStdExpectStrings();+ −
if (iCancelled)+ −
{+ −
Complete(KErrCancel, aSource); // Cancel state machine in safe place+ −
return;+ −
}+ −
else if (ret != KErrNone) + −
{+ −
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tAT+COPS=3,2 not supported")); + −
} + −
else // Set Operator Command was successful, Read the Current Operator+ −
{+ −
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\t AT+COPS=3,2 supported"));+ −
TRAPD(ret,ParseOperatorResponseL());+ −
if (ret != KErrNone)+ −
{+ −
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tError parsing +COPS=3,2"));+ −
} + −
}+ −
iTxBuffer.Copy(KSetAndReadOperatorCommandShort); // AT+COPS=3,1;+COPS?+ −
iIo->Write(this, iTxBuffer);+ −
iIo->SetTimeOut(this, 5000);+ −
iState=EATShortOperatorWaitForWriteComplete; + −
}+ −
break;+ −
+ −
case EATShortOperatorWaitForWriteComplete:+ −
__ASSERT_ALWAYS(aSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected));+ −
{+ −
iIo->WriteAndTimerCancel(this);+ −
StandardWriteCompletionHandler(aSource, 5);+ −
iState=EATSetShortOperatorReadComplete;+ −
}+ −
break;+ −
+ −
case EATSetShortOperatorReadComplete:+ −
__ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));+ −
{+ −
iIo->WriteAndTimerCancel(this);+ −
TInt ret(ValidateExpectString());+ −
RemoveStdExpectStrings();+ −
if (iCancelled)+ −
{+ −
Complete(KErrCancel, aSource); // Cancel state machine in safe place+ −
return;+ −
}+ −
else if (ret != KErrNone)+ −
{+ −
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tAT+COPS=3,1 not supported")); + −
}+ −
else// Set Operator Command was successful, Read the Current Operator+ −
{ + −
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\t AT+COPS=3,1 supported"));+ −
TRAPD(ret,ParseOperatorResponseL());+ −
if (ret != KErrNone)+ −
{+ −
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tError parsing +COPS=3,1"));+ −
} + −
}+ −
iTxBuffer.Copy(KSetAndReadOperatorCommandLong); // AT+COPS=3,0;+COPS?+ −
iIo->Write(this, iTxBuffer);+ −
iIo->SetTimeOut(this, 5000);+ −
iState=EATLongOperatorWaitForWriteComplete; + −
}+ −
break;+ −
+ −
case EATLongOperatorWaitForWriteComplete:+ −
__ASSERT_ALWAYS(aSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected));+ −
{+ −
iIo->WriteAndTimerCancel(this);+ −
StandardWriteCompletionHandler(aSource, 5);+ −
iState=EATSetLongOperatorReadComplete;+ −
}+ −
break;+ −
+ −
case EATSetLongOperatorReadComplete:+ −
__ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));+ −
{+ −
iIo->WriteAndTimerCancel(this);+ −
TInt ret(ValidateExpectString());+ −
RemoveStdExpectStrings();+ −
if (ret != KErrNone)+ −
{+ −
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\t+COPS=3,0 not supported"));+ −
}+ −
else // Set Operator cmd was successful, Read the Current Operator+ −
{+ −
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tAT+COPS=3,0 supported"));+ −
TRAPD(ret,ParseOperatorResponseL());+ −
if (ret != KErrNone)+ −
{+ −
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tError parsing +COPS=3,0"));+ −
} + −
}+ −
+ −
// Check outstanding current network operator notifications+ −
iPhoneGlobals->iNotificationStore->CheckNotification(iTelObject,ECurrentNetworkChanged);+ −
+ −
iIo->SetTimeOut(this, KSettlingPause*1000);+ −
iState=EATWaitForSettlingTimeout;+ −
}+ −
break;+ −
+ −
case EATWaitForSettlingTimeout:+ −
__ASSERT_ALWAYS((aSource==ETimeOutCompletion),Panic(EATCommand_IllegalCompletionWriteExpected));+ −
Complete(KErrNone,aSource);+ −
break;+ −
+ −
case EATWaitForStopState:+ −
__ASSERT_ALWAYS(aSource==EReadCompletion, Panic(EATCommand_IllegalCompletionReadExpected));+ −
{+ −
iIo->WriteAndTimerCancel(this);+ −
Complete(KErrCancel, aSource);+ −
}+ −
break;+ −
+ −
default:+ −
break;+ −
}//switch+ −
}//EventSignal+ −
+ −
void CATNetworkInfo::Stop(TTsyReqHandle aTsyReqHandle)+ −
/**+ −
* This function is used to prematurely stop the state machine. This would usually occur following a+ −
* client cancel request.+ −
*/+ −
{+ −
__ASSERT_ALWAYS(aTsyReqHandle == iReqHandle, Panic(EIllegalTsyReqHandle));+ −
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tCancel called."));+ −
iCancelled=ETrue;+ −
}+ −
+ −
+ −
void CATNetworkInfo::Complete(TInt aError,TEventSource aSource)+ −
/**+ −
* This function completes the client's request.+ −
*/+ −
{+ −
iIo->WriteAndTimerCancel(this);+ −
iIo->RemoveExpectStrings(this);+ −
iOKExpectString = NULL;+ −
iErrorExpectString = NULL;+ −
if (aSource==EWriteCompletion)+ −
iIo->Read();+ −
iState = EATNotInProgress;+ −
LOGTEXT2(_L8("MMTsy:CATNetworkInfo:\tCATNetworkInfo completed with error code : %d"), aError);+ −
//+ −
// BEWARE: The next command will be started from inside ReqCompleted or FlowControlResume+ −
// + −
//+ −
// This object is not always started thru the CATBase::ExecuteCommand+ −
// So we sometimes have to manually control the flow control of iEventSignalActive+ −
iPhoneGlobals->iEventSignalActive = EFalse;+ −
+ −
if (iReqHandle)+ −
{+ −
// Explicit call from a client+ −
if (aError==KErrNone)+ −
{+ −
GetCurrentNetworkInfo(&iNetworkInfo); + −
}+ −
iTelObject->ReqCompleted(iReqHandle, aError);+ −
}+ −
else+ −
{+ −
// CheckOperator() call from CATCommands::Complete+ −
iTelObject->FlowControlResume();+ −
}+ −
CATCommands::Complete(aError,aSource);+ −
}+ −
+ −
void CATNetworkInfo::CompleteWithIOError(TEventSource /*aSource*/,TInt aStatus)+ −
/**+ −
* This function handles I/O errors that may occur during any of the stages of the state machine.+ −
*/+ −
{+ −
if (iState!=EATNotInProgress)+ −
{+ −
iIo->WriteAndTimerCancel(this);+ −
if (iReqHandle)+ −
{+ −
iTelObject->ReqCompleted(iReqHandle, aStatus);+ −
}+ −
else+ −
{+ −
// CheckOperator() call from CATCommands::Complete+ −
iTelObject->FlowControlResume();+ −
}+ −
iState = EATNotInProgress;+ −
}+ −
}+ −
+ −
void CATNetworkInfo::StartGetOperator()+ −
/**+ −
* This function kicks off the state machine by transmitting the first command, "AT+COPS?" and+ −
* setting the state.+ −
*/+ −
{+ −
iPhoneGlobals->iPhoneStatus.iNetworkChanged=EFalse;+ −
InitializeNetworkInfo(); // Initialize the TNetworkInfo struct that will contain the mobile's responses+ −
iTxBuffer.Copy(KGetCurrentOperatorCommand);+ −
iIo->Write(this, iTxBuffer);+ −
iIo->SetTimeOut(this, 5000);+ −
iState=EATGetCurrentOperatorWriteComplete;+ −
}+ −
+ −
void CATNetworkInfo::InitializeNetworkInfo()+ −
/**+ −
* This function is used to initialize (to zero) the network information elements in the CPhoneGlobals+ −
* structure.+ −
*/+ −
{+ −
RMobilePhone::TMobilePhoneNetworkInfoV1& networkinfo = iPhoneGlobals->iPhoneStatus.iCurrentNetwork;+ −
+ −
networkinfo.iMode = RMobilePhone::ENetworkModeUnknown;+ −
networkinfo.iCountryCode.Zero(); // Unknown, MCC+ −
networkinfo.iNetworkId.Zero(); // MNC+ −
networkinfo.iCdmaSID.Zero(); // Unused CDMA field+ −
networkinfo.iAnalogSID.Zero(); // Unused CDMA field+ −
networkinfo.iShortName.Zero();+ −
networkinfo.iLongName.Zero();+ −
networkinfo.iStatus = RMobilePhone::ENetworkStatusUnknown; + −
networkinfo.iDisplayTag.Zero();+ −
}+ −
+ −
void CATNetworkInfo::ParseOperatorResponseL()+ −
/**+ −
* This function is used to parse the ME responses to commands to retrieve numeric, short name + −
* or long name network information. Possible responses are:+ −
* +COPS: mode, 0, "long format name"+ −
* +COPS: mode, 1, "short format name"+ −
* +COPS: mode, 2, "operator ID in hex"+ −
* +COPS: mode (no network information available)+ −
*+ −
* Relevant information is retrieved and written into the CPhoneGlobals class.+ −
*/+ −
{+ −
RMobilePhone::TMobilePhoneNetworkInfoV1& networkInfo = iPhoneGlobals->iPhoneStatus.iCurrentNetwork; + −
+ −
ParseBufferLC(); // Parse the buffer and create a linked list with the phone's response+ −
+ −
CATParamListEntry* entry;+ −
TDblQueIter<CATParamListEntry> iter(iRxResults);+ −
+ −
// The 1st item in the list should be the +COPS: response+ −
entry=iter++;+ −
if (entry && entry->iResultPtr.MatchF(KOperatorResponse)!=0)+ −
User::Leave(KErrGeneral);+ −
+ −
// The next item is the mode (this information is not used)+ −
entry=iter++;+ −
if (!entry)+ −
User::Leave(KErrGeneral); + −
+ −
// The next item should be the format. If there is no network information then this item+ −
// would be empty. The network status is consequently updated.+ −
entry=iter++;+ −
if (!entry) // Not connected, so the response is "+COPS: 0"+ −
networkInfo.iStatus=RMobilePhone::ENetworkStatusUnknown;+ −
else + −
{+ −
TInt format=CATParamListEntry::EntryValL(entry);+ −
+ −
// If the format is available, the network name is the next item in the list + −
entry=iter++;+ −
if (!entry)+ −
User::Leave(KErrGeneral);+ −
switch (format)+ −
{+ −
case 0:+ −
if((entry->iResultPtr).Length() > networkInfo.iLongName.MaxLength())+ −
networkInfo.iLongName.Copy((entry->iResultPtr).Mid(0,networkInfo.iLongName.MaxLength())); + −
else+ −
networkInfo.iLongName.Copy(entry->iResultPtr);+ −
break;+ −
case 1:+ −
if((entry->iResultPtr).Length() > networkInfo.iShortName.MaxLength())+ −
networkInfo.iShortName.Copy((entry->iResultPtr).Mid(0,networkInfo.iShortName.MaxLength())); + −
else + −
networkInfo.iShortName.Copy(entry->iResultPtr); + −
break;+ −
case 2:+ −
User::LeaveIfError(NetworkIdL(entry->iResultPtr,networkInfo.iCountryCode, networkInfo.iNetworkId));+ −
break;+ −
default:+ −
User::Leave(KErrGeneral);+ −
break;+ −
}+ −
+ −
// We've got an answer, so this must be the current network+ −
networkInfo.iStatus=RMobilePhone::ENetworkStatusCurrent;+ −
}+ −
CleanupStack::PopAndDestroy();+ −
}+ −
+ −
void CATNetworkInfo::GetCurrentNetworkInfo(CATNetworkInfo::TTsyNetworkInfo* aNetworkInfo)+ −
/**+ −
* This function checks to see if the network registration information in CPhoneGlobals is valid,+ −
* and, if it is, it copies the CPhoneGlobals network information into the waiting client request+ −
* buffer.+ −
*/+ −
{+ −
RMobilePhone::TMobilePhoneNetworkInfoV1& networkInfo = (*(aNetworkInfo->iNetworkInfoPckg))();+ −
RMobilePhone::TMobilePhoneLocationAreaV1& areaInfo = *(aNetworkInfo->iArea);+ −
RMobilePhone::TMobilePhoneRegistrationStatus status = iPhoneGlobals->iPhoneStatus.iRegistrationStatus;+ −
+ −
if (status == RMobilePhone::ERegisteredOnHomeNetwork+ −
|| status == RMobilePhone::ERegisteredRoaming+ −
|| status == RMobilePhone::ERegistrationUnknown) // AT+CREG? is not supported, but info obtained during initialization is still valid. NickyM+ −
{+ −
RMobilePhone::TMobilePhoneNetworkInfoV1& info = iPhoneGlobals->iPhoneStatus.iCurrentNetwork;+ −
RMobilePhone::TMobilePhoneLocationAreaV1& locationInfo = iPhoneGlobals->iPhoneStatus.iLocationArea;+ −
+ −
networkInfo.iStatus = info.iStatus;+ −
networkInfo.iCountryCode = info.iCountryCode; + −
networkInfo.iNetworkId = info.iNetworkId;+ −
networkInfo.iCdmaSID = info.iCdmaSID; // for CDMA+ −
networkInfo.iAnalogSID = info.iAnalogSID; // for CDMA+ −
networkInfo.iShortName = info.iShortName;+ −
networkInfo.iLongName = info.iLongName;+ −
networkInfo.iDisplayTag = info.iLongName; // This TSY handles the display tag as the same as longname+ −
networkInfo.iMode = iPhoneGlobals->iNetworkMode;+ −
areaInfo.iAreaKnown = locationInfo.iAreaKnown;+ −
areaInfo.iLocationAreaCode = locationInfo.iLocationAreaCode;+ −
areaInfo.iCellId = locationInfo.iCellId;+ −
}+ −
else+ −
{+ −
networkInfo.iStatus = RMobilePhone::ENetworkStatusUnknown;+ −
networkInfo.iShortName.Zero(); // Should this be .Zero() ?+ −
networkInfo.iLongName.Zero(); // Should this be .Zero() ?+ −
areaInfo.iAreaKnown = EFalse; + −
areaInfo.iLocationAreaCode = 0;+ −
areaInfo.iCellId = 0;+ −
+ −
}+ −
return;+ −
}+ −
+ −
+ −
// class CNotifyNetworkRegistrationStatusChange+ −
+ −
CNotifyNetworkRegistrationStatusChange* CNotifyNetworkRegistrationStatusChange::NewL(TTsyReqHandle aReqHandle,CTelObject* aTelObject, + −
RMobilePhone::TMobilePhoneRegistrationStatus* aRegStatus)+ −
{+ −
return new(ELeave) CNotifyNetworkRegistrationStatusChange(aReqHandle,aTelObject,aRegStatus);+ −
}+ −
+ −
CNotifyNetworkRegistrationStatusChange::CNotifyNetworkRegistrationStatusChange(TTsyReqHandle aReqHandle,CTelObject* aTelObject, + −
RMobilePhone::TMobilePhoneRegistrationStatus* aRegStatus)+ −
: CNotifyBase(aReqHandle,aTelObject)+ −
{+ −
iRegStatus = aRegStatus;+ −
}+ −
+ −
CNotifyNetworkRegistrationStatusChange::~CNotifyNetworkRegistrationStatusChange()+ −
{}+ −
+ −
TBool CNotifyNetworkRegistrationStatusChange::CheckAndCompleteNotification(CTelObject* aTelObject, TEvent aEvent, TEvent /*aLastEvent*/)+ −
/**+ −
* This function completes a Registration status Notification.+ −
*/+ −
{ + −
if (aEvent!=ERegistrationStatusChanged)+ −
return EFalse;+ −
+ −
LOGTEXT2(_L8("Event %d:\tRegistration Status Changed Notification completed"),aEvent);+ −
*iRegStatus = reinterpret_cast<CPhoneMobile*>(aTelObject)->RegistrationStatus();+ −
iTelObject->ReqCompleted(iReqHandle,KErrNone);+ −
return ETrue;+ −
}+ −
+ −
// class CCurrentNetworkChangedNotify+ −
+ −
CNotifyCurrentNetworkChange* CNotifyCurrentNetworkChange::NewL(TTsyReqHandle aReqHandle,CTelObject* aTelObject,TInt* aInfo)+ −
{ + −
return new(ELeave) CNotifyCurrentNetworkChange(aReqHandle,aTelObject,aInfo);+ −
}+ −
+ −
CNotifyCurrentNetworkChange::CNotifyCurrentNetworkChange(TTsyReqHandle aReqHandle,CTelObject* aTelObject,TInt* aInfo)+ −
: CNotifyBase(aReqHandle,aTelObject)+ −
{+ −
CATNetworkInfo::TTsyNetworkInfo* info = reinterpret_cast<CATNetworkInfo::TTsyNetworkInfo*>(aInfo);+ −
iNetworkInfo.iNetworkInfoPckg = info->iNetworkInfoPckg;+ −
iNetworkInfo.iArea = info->iArea;+ −
}+ −
+ −
CNotifyCurrentNetworkChange::~CNotifyCurrentNetworkChange()+ −
{}+ −
+ −
TBool CNotifyCurrentNetworkChange::CheckAndCompleteNotification(CTelObject* aTelObject,TEvent aEvent,TEvent /*aLastEvent*/)+ −
/**+ −
* This function completes a Current Network Change Notification.+ −
*/+ −
{ + −
if (aEvent!=ECurrentNetworkChanged)+ −
return EFalse; + −
+ −
LOGTEXT2(_L8("Event %d:\tCurrent Network Changed Notification completed"),aEvent);+ −
// REINTERPRET_CAST(CPhoneMobile*,aTelObject)->CurrentNetworkInfo(&iNetworkInfo);+ −
reinterpret_cast<CPhoneMobile*>(aTelObject)->CurrentNetworkInfo(&iNetworkInfo);+ −
iTelObject->ReqCompleted(iReqHandle,KErrNone);+ −
return ETrue;+ −
}+ −
+ −
// Class CATDetectNetwork+ −
//+ −
// Detect all available networks.+ −
+ −
CATDetectNetwork::CATDetectNetwork(CATIO* aIo, CTelObject* aTelObject, CATInit* aInit,CPhoneGlobals* aPhoneGlobals)+ −
: CATCommands(aIo,aTelObject,aInit,aPhoneGlobals)+ −
{}+ −
+ −
CATDetectNetwork* CATDetectNetwork::NewL(CATIO* aIo,CTelObject* aTelObject,CATInit* aInit,CPhoneGlobals* aPhoneGlobals)+ −
/**+ −
* Standard 2 phase constructor.+ −
*/+ −
{+ −
CATDetectNetwork* self = new(ELeave) CATDetectNetwork(aIo, aTelObject, aInit, aPhoneGlobals);+ −
CleanupStack::PushL(self);+ −
self->ConstructL();+ −
CleanupStack::Pop();+ −
return self;+ −
}+ −
+ −
CATDetectNetwork::~CATDetectNetwork()+ −
/**+ −
* Destructor.+ −
*/+ −
{+ −
iIo->RemoveExpectStrings(this);+ −
}+ −
+ −
void CATDetectNetwork::Start(TTsyReqHandle aTsyReqHandle,TAny* aParam)+ −
/**+ −
* This is the standard entry point for retrieving the detected Operator Information.+ −
*/+ −
{+ −
LOGTEXT(_L8("MMTsy:\tCATDetectNetwork:\tStarting Network detection"));+ −
if (aParam != NULL)+ −
{+ −
TTsyDetectedNetworks* info = static_cast<TTsyDetectedNetworks* >(aParam);+ −
iDetectedNetworks.iBufSize = info->iBufSize;+ −
iDetectedNetworks.iBufPtr = info->iBufPtr;+ −
}+ −
+ −
iReqHandle = aTsyReqHandle;+ −
+ −
WriteExpectingResults(KDetectNetworkCommand, 3);+ −
__ASSERT_ALWAYS(iIo->AddExpectString(this,KNotifyMeIfErrorString) != NULL,Panic(EGeneral));+ −
iState=EATDetectWaitForWriteComplete;+ −
}+ −
+ −
void CATDetectNetwork::EventSignal(TEventSource aSource)+ −
/**+ −
* This function contains the state machine for the command. The states flow consecutively and are+ −
* described below.+ −
* + −
* \par EATDetectWaitForWriteComplete+ −
* Wait for the "AT+COPS=?" write to complete+ −
*+ −
* \par EATDetectReadComplete+ −
* Reads the Modem's response to the AT+COPS=? command. If it gets an "ERROR" back it resets the + −
* timer and sets a new state (EATDetectExtendedReadComplete) and waits for another response.+ −
*+ −
* \par EATDetectExtendedReadComplete+ −
* Reads the phone's response to the AT+COPS=? command and parses the response. Completes the+ −
* request.+ −
*+ −
* \par EATWaitForStopState+ −
* This state is used when stopping the state machine to ensure that a pending modem response has been+ −
* retrieved before freeing up the Multimode TSY to send more commands. Prematurely stopping the state machine+ −
* is usually forced by a client cancel request.+ −
*/+ −
{+ −
if (aSource==ETimeOutCompletion)+ −
{+ −
if (iState!=EATDetectExtendedReadComplete)+ −
{+ −
LOGTEXT(_L8("MmTsy:\tCATDetectNetwork:\tTimeout Error during Network Detect read"));+ −
RemoveStdExpectStrings();+ −
Complete(KErrTimedOut,aSource);+ −
return;+ −
}+ −
else+ −
{+ −
// the phone really does not support +COPS=?, so report that error+ −
RemoveStdExpectStrings();+ −
Complete(KErrNotSupported,EReadCompletion);+ −
return;+ −
}+ −
}+ −
+ −
switch(iState)+ −
{+ −
case EATDetectWaitForWriteComplete:+ −
__ASSERT_ALWAYS(aSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected));+ −
{+ −
iIo->WriteAndTimerCancel(this);+ −
iIo->SetTimeOut(this,45 * KOneSecondPause); // Some phones take a long time to detect all the networks+ −
AddStdExpectStrings();+ −
iState=EATDetectReadComplete;+ −
}+ −
break;+ −
+ −
case EATDetectReadComplete:+ −
__ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));+ −
iIo->WriteAndTimerCancel(this);+ −
if (iIo->FoundChatString()==iErrorExpectString)+ −
{+ −
LOGTEXT(_L8("Modem returned ERROR - waiting for further response"));+ −
iIo->ClearCurrentLine();+ −
iIo->SetTimeOut(this,45 * KOneSecondPause);+ −
iState = EATDetectExtendedReadComplete;+ −
break;+ −
}+ −
// fall through ...+ −
+ −
case EATDetectExtendedReadComplete:+ −
__ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));+ −
iIo->WriteAndTimerCancel(this);+ −
{+ −
TInt ret(ValidateExpectString());+ −
RemoveStdExpectStrings();+ −
if (ret==KErrNone)+ −
TRAP(ret,ParseResponseL());+ −
Complete(ret,aSource); // The return value is set in the Complete methode+ −
}+ −
break;+ −
+ −
case EATWaitForStopState:+ −
__ASSERT_ALWAYS(aSource==EReadCompletion, Panic(EATCommand_IllegalCompletionReadExpected));+ −
{+ −
iIo->WriteAndTimerCancel(this);+ −
Complete(KErrCancel, aSource);+ −
}+ −
break;+ −
+ −
default:+ −
break;+ −
}//switch+ −
}//EventSignal+ −
+ −
void CATDetectNetwork::Stop(TTsyReqHandle aTsyReqHandle)+ −
/**+ −
* This function is used to prematurely stop the state machine. This would usually occur following a+ −
* client cancel request.+ −
*/+ −
{+ −
__ASSERT_ALWAYS(aTsyReqHandle == iReqHandle, Panic(EIllegalTsyReqHandle));+ −
LOGTEXT(_L8("MMTsy:\tCATDetectNetwork:\tCancel called."));+ −
switch(iState)+ −
{+ −
case EATNotInProgress:+ −
case EATDetectWaitForWriteComplete:+ −
{+ −
LOGTEXT2(_L8("Current state TSY is cancelling from %d"), iState);+ −
Complete(KErrCancel, EReadCompletion);+ −
}+ −
break;+ −
+ −
default:+ −
{+ −
LOGTEXT(_L8("MmTsy:\tCATDetectNetwork:\tStop, now waiting for expected modem response"));+ −
AddStdExpectStrings();+ −
iIo->SetTimeOut(this);+ −
iState = EATWaitForStopState;+ −
}+ −
break;+ −
}+ −
}+ −
+ −
+ −
void CATDetectNetwork::Complete(TInt aError,TEventSource aSource)+ −
/**+ −
* This function completes the client request.+ −
*/+ −
{+ −
iState = EATNotInProgress;+ −
iIo->WriteAndTimerCancel(this);+ −
iIo->RemoveExpectStrings(this);+ −
iOKExpectString = NULL;+ −
iErrorExpectString = NULL;+ −
CATCommands::Complete(aError,aSource);+ −
+ −
LOGTEXT2(_L8("MMTsy:CATDetectNetwork:\tCATDetectNetwork completed with error code : %d"), aError);+ −
if (aError==KErrCancel)+ −
{+ −
CPhoneMobile* phone = static_cast<CPhoneMobile*>(iTelObject);+ −
phone->CompleteDetectedNetworksCancel(iReqHandle);+ −
}+ −
else+ −
iTelObject->ReqCompleted(iReqHandle, aError);+ −
}+ −
+ −
void CATDetectNetwork::CompleteWithIOError(TEventSource /*aSource*/,TInt aStatus)+ −
/**+ −
* This function handles I/O errors that may occur during any of the stages of the state machine.+ −
*/+ −
{+ −
if (iState!=EATNotInProgress)+ −
{+ −
iIo->WriteAndTimerCancel(this);+ −
iState = EATNotInProgress;+ −
iTelObject->ReqCompleted(iReqHandle, aStatus);+ −
}+ −
}+ −
+ −
void CATDetectNetwork::ParseResponseL()+ −
/**+ −
* This function parses the phone's response to the Detect Networks command.+ −
*/+ −
{+ −
// should be+ −
//+ −
// +COPS: (status,"longname","shortname",code),... ,,(list),(list)+ −
//+ −
// but SH888 gives+ −
//+ −
// +COPS: (status,"longname","shortname",code)<cr><lf>+ −
// +COPS: ...+ −
//+ −
+ −
CMobilePhoneNetworkList* list=CMobilePhoneNetworkList::NewL();+ −
CleanupStack::PushL(list);+ −
+ −
ParseBufferLC();+ −
+ −
RMobilePhone::TMobilePhoneNetworkInfoV1 info; + −
// This TSY only supports GSM mode so we can hardcode this+ −
info.iMode=RMobilePhone::ENetworkModeGsm;+ −
TDblQueIter<CATParamListEntry> iter(iRxResults);+ −
CATParamListEntry* entry=iter++;+ −
if (entry)+ −
{+ −
if (entry->iResultPtr!=KOperatorResponse)+ −
User::Leave(KErrGeneral);+ −
//+ −
entry=iter++;+ −
if (!entry)+ −
User::Leave(KErrGeneral);+ −
for (;;)+ −
{+ −
info.iStatus = RMobilePhone::TMobilePhoneNetworkStatus(CATParamListEntry::EntryValL(entry));+ −
//+ −
entry=iter++;+ −
if (!entry)+ −
User::Leave(KErrGeneral);+ −
info.iLongName.Copy(entry->iResultPtr); + −
//+ −
entry=iter++;+ −
if (!entry)+ −
User::Leave(KErrGeneral);+ −
if((entry->iResultPtr).Length() > info.iShortName.MaxLength())+ −
info.iShortName.Copy((entry->iResultPtr).Mid(0,info.iShortName.MaxLength())); + −
else+ −
info.iShortName.Copy(entry->iResultPtr);+ −
//+ −
entry=iter++;+ −
if (!entry)+ −
User::Leave(KErrGeneral);+ −
User::LeaveIfError(NetworkIdL(entry->iResultPtr,info.iCountryCode, info.iNetworkId)); // MNC and MCC + −
+ −
list->AddEntryL(info); + −
+ −
entry=iter++;+ −
if (!entry)+ −
break;+ −
if (entry->iResultPtr.Length()==0)+ −
break;+ −
if (entry->iResultPtr!=KOperatorResponse)+ −
continue;+ −
entry=iter++;+ −
if (!entry)+ −
break;+ −
}+ −
}+ −
+ −
CleanupStack::PopAndDestroy(); // results+ −
+ −
*(iDetectedNetworks.iBufPtr) = list->StoreLC(); // Stream the list to optimice the size of it.+ −
*(iDetectedNetworks.iBufSize) = (*(iDetectedNetworks.iBufPtr))->Size(); // Store the size of the streamed list to be passed back to the client. + −
+ −
CleanupStack::Pop(); // pop the CBufBase allocated by StoreLC+ −
CleanupStack::PopAndDestroy(); // pop AND detroy the list.+ −
+ −
} // End of ParseResponseL() + −
+ −
+ −
+ −