telephonyserverplugins/multimodetsy/Multimode/mnetwork.cpp
changeset 0 3553901f7fa8
child 24 6638e7f4bd8f
equal deleted inserted replaced
-1:000000000000 0:3553901f7fa8
       
     1 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // \file mnetwork.cpp
       
    15 // Basic GSM Network and Operator information Implementation file.
       
    16 // This file contains the implementation of the CATNetworkInfo, CATDetectNetwork,
       
    17 // CNotifyNetworkRegistrationStatusChange and CCurrentNetworkChangedNotify classes.
       
    18 // Find the current Network Operator in Numeric, Long and Short formats.
       
    19 // NB - Some phones do not fully support all the formats, if any. The commands are 
       
    20 // sent in sequence starting with the query command (AT+COPS?). All the phones currently
       
    21 // supported implement this command. Valid responses are set in the TMobilePhoneLocationAreaV1
       
    22 // and the TMobilePhoneNetworkInfoV1 structures and the Network's status is set to Current.
       
    23 // 
       
    24 //
       
    25 
       
    26 #include <et_phone.h>
       
    27 #include "mnetwork.h"
       
    28 #include "mSLOGGER.H"
       
    29 #include "ATIO.H"
       
    30 #include "Matstd.h"
       
    31 #include "mPHONE.H"
       
    32 
       
    33 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.
       
    34 
       
    35 _LIT8(KSetAndReadOperatorCommandNumeric, "AT+COPS=3,2;+COPS?\r");
       
    36 _LIT8(KSetAndReadOperatorCommandShort, "AT+COPS=3,1;+COPS?\r");
       
    37 _LIT8(KSetAndReadOperatorCommandLong, "AT+COPS=3,0;+COPS?\r");
       
    38 
       
    39 _LIT8(KGetCurrentOperatorCommand, "AT+COPS?\r");
       
    40 _LIT8(KOperatorResponse,"+COPS:");
       
    41 
       
    42 _LIT8(KDetectNetworkCommand,"AT+COPS=?");
       
    43 
       
    44 
       
    45 static TInt NetworkIdL(const TDesC8& aCode,
       
    46 					   RMobilePhone::TMobilePhoneNetworkCountryCode& aCountryCode, 
       
    47 					   RMobilePhone::TMobilePhoneNetworkIdentity& aNetworkIdentity)
       
    48 	{
       
    49 /**
       
    50  * Utility function to translate the 5 digit ASCII network identification returned by the ME
       
    51  * into Mobile Country Code (aCountryCode) and a Mobile Network Code (aNetworkIdentity) strings.
       
    52  * Tbe format returned by the ME is XXXYY, where XXX represents the Mobile Country Code and YY
       
    53  * represents the Mobile Network Code.
       
    54  */
       
    55 	if (aCode.Length()!=5)
       
    56 		{
       
    57 		return KErrGeneral;
       
    58 		}
       
    59 	
       
    60 	aCountryCode.SetLength(3);
       
    61 	aCountryCode[0] = aCode[0];
       
    62 	aCountryCode[1] = aCode[1];
       
    63 	aCountryCode[2] = aCode[2];
       
    64 
       
    65 	aNetworkIdentity.SetLength(2);
       
    66 	aNetworkIdentity[0] = aCode[3];
       
    67 	aNetworkIdentity[1] = aCode[4];
       
    68 	return KErrNone;
       
    69 	}
       
    70 
       
    71 
       
    72 CATNetworkInfo* CATNetworkInfo::NewL(CATIO* aIo,CTelObject* aTelObject,CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
       
    73 /**
       
    74  * Standard two-phase constructor.
       
    75  */
       
    76 	{
       
    77 	CATNetworkInfo* netInfo = new(ELeave) CATNetworkInfo(aIo, aTelObject, aInit, aPhoneGlobals);
       
    78 	CleanupStack::PushL(netInfo);
       
    79 	netInfo->ConstructL();
       
    80 	CleanupStack::Pop();
       
    81 	return netInfo;
       
    82 	}
       
    83 
       
    84 CATNetworkInfo::CATNetworkInfo(CATIO* aIo, CTelObject* aTelObject, CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
       
    85 	: CATCommands(aIo,aTelObject,aInit,aPhoneGlobals)
       
    86 	,iPhoneGlobals(aPhoneGlobals)
       
    87 	{}
       
    88 
       
    89 CATNetworkInfo::~CATNetworkInfo()
       
    90 /**
       
    91  * Standard Destructor.
       
    92  * Note the NULLing of the iATNetworkInfo pointer.  This should prevent any unwanted calling
       
    93  * of this function from the "end of command" sequence after the class' destruction.
       
    94  */
       
    95 	{
       
    96 	iIo->RemoveExpectStrings(this);
       
    97 	iPhoneGlobals->iATNetworkInfo=NULL;
       
    98 	}
       
    99 
       
   100 void CATNetworkInfo::Start(TTsyReqHandle aTsyReqHandle,TAny* aParam)
       
   101 /**
       
   102  * This is the standard entry point for retrieving the Network Information.
       
   103  */
       
   104 	{
       
   105 	LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tStarting Operator Info."));
       
   106 	iReqHandle = aTsyReqHandle;
       
   107 	if (aParam!=NULL)
       
   108 		{
       
   109 		TTsyNetworkInfo* info = static_cast<TTsyNetworkInfo*>(aParam);
       
   110 		iNetworkInfo.iNetworkInfoPckg = info->iNetworkInfoPckg;
       
   111 		iNetworkInfo.iArea = info->iArea;
       
   112 		}
       
   113 
       
   114 	//
       
   115 	// This object is not always started thru the CATBase::ExecuteCommand
       
   116 	// So we sometimes have to manually control the flow control of iEventSignalActive
       
   117 	iPhoneGlobals->iEventSignalActive = ETrue;
       
   118 	iCancelled=EFalse;
       
   119 
       
   120 	if (iReqHandle==0)
       
   121 		iTelObject->FlowControlSuspend();
       
   122 	StartGetOperator();
       
   123 	}
       
   124 
       
   125 void CATNetworkInfo::CheckOperator()
       
   126 /**
       
   127  * This function is called whenever an EventSignal Completes.  It is a second entry point for the command.
       
   128  * It checks CPhoneGlobals iPhoneStatus.iNetworkChanged and calls this function if it detects that the
       
   129  * networking information has changed and therefore the CPhoneGlobals data may be out of date and needs
       
   130  * to be refreshed.
       
   131  */
       
   132 	{
       
   133 	Start(0,0);
       
   134 	}
       
   135 
       
   136 
       
   137 void CATNetworkInfo::EventSignal(TEventSource aSource)
       
   138 /**
       
   139  * This function contains the state machine for the command.  The states flow consecutively and are
       
   140  * described below.
       
   141  * 
       
   142  * \par EATGetCurrentOperatorWriteComplete
       
   143  * Wait for the "AT+COPS?" write to complete
       
   144  *
       
   145  * \par EATGetCurrentOperatorReadComplete
       
   146  * Parse the "AT+COPS?" response.  If it gets an "ERROR" back it assume that no COPS commands are
       
   147  * supported, so complete the request with an error.  If it is supported, parse the result and proceed
       
   148  * to retrieve the numeric network code with "AT+COPS=3,2;+COPS?"
       
   149  *
       
   150  * \par EATNumericOperatorWaitForWriteComplete
       
   151  * Wait for the "AT+COPS=3,2;+COPS?" to complete
       
   152  *
       
   153  * \par EATSetNumericOperatorReadComplete
       
   154  * Parse the numeric network code if available.  Proceed to retrieve the short network code with
       
   155  * "AT+COPS=3,1;+COPS?".
       
   156  *
       
   157  * \par EATShortOperatorWaitForWriteComplete
       
   158  * Wait for the "AT+COPS=3,1;+COPS?" write to complete.
       
   159  *
       
   160  * \par EATSetShortOperatorReadComplete
       
   161  * Parse the short network name if available.  Proceed to retrieve the long network name with
       
   162  * "AT+COPS=3,0;+COPS?".
       
   163  *
       
   164  * \par EATLongOperatorWaitForWriteComplete
       
   165  * Wait for the "AT+COPS=3,0;+COPS?" write to complete.
       
   166  *
       
   167  * \par EATSetLongOperatorReadComplete
       
   168  * Parse the long network name if available.  Proceed to complete the request. 
       
   169  * Check for outstanding current network operator notifications at this point. 
       
   170  *
       
   171  * \par EATWaitForStopState
       
   172  * This state is used when stopping the state machine to ensure that a pending modem response has been
       
   173  * retrieved before freeing up the Multimode TSY to send more commands.  Prematurely stopping the state machine
       
   174  * is usually forced by a client cancel request.
       
   175  *
       
   176  * \par EATWaitForSettlingTimeout
       
   177  * This state is used to provide a pause at the end of the network information queries. The Nokia 8210
       
   178  * has been shown to require this, if it is not to arbitrarily error the next command.
       
   179  */
       
   180 	{
       
   181 	if ((aSource==ETimeOutCompletion)&&(iState!=EATWaitForSettlingTimeout))
       
   182 		{
       
   183 		LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tTimeout Error during Operator read"));
       
   184 		RemoveStdExpectStrings();
       
   185 		Complete(KErrTimedOut,aSource);
       
   186 		return;
       
   187 		}
       
   188 
       
   189 	switch(iState)
       
   190 		{
       
   191 		case EATGetCurrentOperatorWriteComplete:
       
   192 			__ASSERT_ALWAYS(aSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected));
       
   193 			{
       
   194 			iIo->WriteAndTimerCancel(this);
       
   195 			StandardWriteCompletionHandler(aSource, 5);
       
   196 			iState=EATGetCurrentOperatorReadComplete;
       
   197 			}
       
   198 			break;
       
   199 
       
   200 		case EATGetCurrentOperatorReadComplete:
       
   201 			__ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));
       
   202 			{
       
   203 			iIo->WriteAndTimerCancel(this);
       
   204 			TInt ret(ValidateExpectString());
       
   205 			RemoveStdExpectStrings();
       
   206 			if (ret != KErrNone)
       
   207 				{
       
   208 				LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\t+COPS? not supported"));
       
   209 				LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tSet Operator Command not supported")); // An assumption
       
   210 				Complete(ret, aSource);	// No point in sending the Set Command.
       
   211 				}
       
   212 			else if (iCancelled)
       
   213 				{
       
   214 				Complete(KErrCancel, aSource);	// Cancel state machine in safe place
       
   215 				}
       
   216 			else
       
   217 				{
       
   218 				LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\t+COPS? supported"));
       
   219 				TRAPD(ret,ParseOperatorResponseL());
       
   220 				if (ret != KErrNone)
       
   221 					{
       
   222 					LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tError parsing +COPS?"));
       
   223 					}								
       
   224 				iTxBuffer.Copy(KSetAndReadOperatorCommandNumeric); // AT+COPS=3,2;+COPS?
       
   225 				iIo->Write(this, iTxBuffer);
       
   226 				iIo->SetTimeOut(this, 5000);
       
   227 				iState=EATNumericOperatorWaitForWriteComplete;
       
   228 				}
       
   229 			}
       
   230 			break;		
       
   231 
       
   232 		case EATNumericOperatorWaitForWriteComplete:
       
   233 			__ASSERT_ALWAYS(aSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected));
       
   234 			{
       
   235 			iIo->WriteAndTimerCancel(this);
       
   236 			StandardWriteCompletionHandler(aSource, 5);
       
   237 			iState=EATSetNumericOperatorReadComplete;
       
   238 			}
       
   239 			break;
       
   240 
       
   241 		case EATSetNumericOperatorReadComplete:
       
   242 			__ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));
       
   243 			{
       
   244 			iIo->WriteAndTimerCancel(this);
       
   245 			TInt ret(ValidateExpectString());
       
   246 			RemoveStdExpectStrings();
       
   247 			if (iCancelled)
       
   248 				{
       
   249 				Complete(KErrCancel, aSource);	// Cancel state machine in safe place
       
   250 				return;
       
   251 				}
       
   252 			else if (ret != KErrNone) 
       
   253 				{
       
   254 				LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tAT+COPS=3,2 not supported"));				
       
   255 				}				
       
   256 			else	// Set Operator Command was successful, Read the Current Operator
       
   257 				{
       
   258 				LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\t	AT+COPS=3,2 supported"));
       
   259 				TRAPD(ret,ParseOperatorResponseL());
       
   260 				if (ret != KErrNone)
       
   261 					{
       
   262 					LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tError parsing +COPS=3,2"));
       
   263 					}					
       
   264 				}
       
   265 			iTxBuffer.Copy(KSetAndReadOperatorCommandShort); // AT+COPS=3,1;+COPS?
       
   266 			iIo->Write(this, iTxBuffer);
       
   267 			iIo->SetTimeOut(this, 5000);
       
   268 			iState=EATShortOperatorWaitForWriteComplete; 
       
   269 			}
       
   270 			break;
       
   271 
       
   272 		case EATShortOperatorWaitForWriteComplete:
       
   273 			__ASSERT_ALWAYS(aSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected));
       
   274 			{
       
   275 			iIo->WriteAndTimerCancel(this);
       
   276 			StandardWriteCompletionHandler(aSource, 5);
       
   277 			iState=EATSetShortOperatorReadComplete;
       
   278 			}
       
   279 			break;
       
   280 
       
   281 		case EATSetShortOperatorReadComplete:
       
   282 			__ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));
       
   283 				{
       
   284 				iIo->WriteAndTimerCancel(this);
       
   285 				TInt ret(ValidateExpectString());
       
   286 				RemoveStdExpectStrings();
       
   287 				if (iCancelled)
       
   288 					{
       
   289 					Complete(KErrCancel, aSource);	// Cancel state machine in safe place
       
   290 					return;
       
   291 					}
       
   292 				else if (ret != KErrNone)
       
   293 					{
       
   294 					LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tAT+COPS=3,1 not supported"));					
       
   295 					}
       
   296 				else// Set Operator Command was successful, Read the Current Operator
       
   297 					{	
       
   298 					LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\t	AT+COPS=3,1 supported"));
       
   299 					TRAPD(ret,ParseOperatorResponseL());
       
   300 					if (ret != KErrNone)
       
   301 						{
       
   302 						LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tError parsing +COPS=3,1"));
       
   303 						}						
       
   304 					}
       
   305 				iTxBuffer.Copy(KSetAndReadOperatorCommandLong); // AT+COPS=3,0;+COPS?
       
   306 				iIo->Write(this, iTxBuffer);
       
   307 				iIo->SetTimeOut(this, 5000);
       
   308 				iState=EATLongOperatorWaitForWriteComplete; 
       
   309 				}
       
   310 			break;
       
   311 
       
   312 		case EATLongOperatorWaitForWriteComplete:
       
   313 			__ASSERT_ALWAYS(aSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected));
       
   314 			{
       
   315 			iIo->WriteAndTimerCancel(this);
       
   316 			StandardWriteCompletionHandler(aSource, 5);
       
   317 			iState=EATSetLongOperatorReadComplete;
       
   318 			}
       
   319 			break;
       
   320 
       
   321 		case EATSetLongOperatorReadComplete:
       
   322 			__ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));
       
   323 			{
       
   324 			iIo->WriteAndTimerCancel(this);
       
   325 			TInt ret(ValidateExpectString());
       
   326 			RemoveStdExpectStrings();
       
   327 			if (ret != KErrNone)
       
   328 				{
       
   329 				LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\t+COPS=3,0 not supported"));
       
   330 				}
       
   331 			else	// Set Operator cmd was successful, Read the Current Operator
       
   332 				{
       
   333 				LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tAT+COPS=3,0 supported"));
       
   334 				TRAPD(ret,ParseOperatorResponseL());
       
   335 				if (ret != KErrNone)
       
   336 					{
       
   337 					LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tError parsing +COPS=3,0"));
       
   338 					}						
       
   339 				}
       
   340 
       
   341 			// Check outstanding current network operator notifications
       
   342 			iPhoneGlobals->iNotificationStore->CheckNotification(iTelObject,ECurrentNetworkChanged);
       
   343 
       
   344 			iIo->SetTimeOut(this, KSettlingPause*1000);
       
   345 			iState=EATWaitForSettlingTimeout;
       
   346 			}
       
   347 			break;
       
   348 
       
   349 		case EATWaitForSettlingTimeout:
       
   350 			__ASSERT_ALWAYS((aSource==ETimeOutCompletion),Panic(EATCommand_IllegalCompletionWriteExpected));
       
   351 			Complete(KErrNone,aSource);
       
   352 			break;
       
   353 	
       
   354 		case EATWaitForStopState:
       
   355 			__ASSERT_ALWAYS(aSource==EReadCompletion, Panic(EATCommand_IllegalCompletionReadExpected));
       
   356 			{
       
   357 			iIo->WriteAndTimerCancel(this);
       
   358 			Complete(KErrCancel, aSource);
       
   359 			}
       
   360 			break;
       
   361 
       
   362 		default:
       
   363 			break;
       
   364 		}//switch
       
   365 	}//EventSignal
       
   366 
       
   367 void CATNetworkInfo::Stop(TTsyReqHandle aTsyReqHandle)
       
   368 /**
       
   369  * This function is used to prematurely stop the state machine.  This would usually occur following a
       
   370  * client cancel request.
       
   371  */
       
   372 {
       
   373 	__ASSERT_ALWAYS(aTsyReqHandle == iReqHandle, Panic(EIllegalTsyReqHandle));
       
   374 	LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tCancel called."));
       
   375 	iCancelled=ETrue;
       
   376 }
       
   377 
       
   378 
       
   379 void CATNetworkInfo::Complete(TInt aError,TEventSource aSource)
       
   380 /**
       
   381  * This function completes the client's request.
       
   382  */
       
   383 	{
       
   384 	iIo->WriteAndTimerCancel(this);
       
   385 	iIo->RemoveExpectStrings(this);
       
   386 	iOKExpectString = NULL;
       
   387 	iErrorExpectString = NULL;
       
   388 	if (aSource==EWriteCompletion)
       
   389 		iIo->Read();
       
   390 	iState = EATNotInProgress;
       
   391 	LOGTEXT2(_L8("MMTsy:CATNetworkInfo:\tCATNetworkInfo completed with error code : %d"), aError);
       
   392 	//
       
   393 	// BEWARE: The next command will be started from inside ReqCompleted or FlowControlResume
       
   394 	// 
       
   395 	//
       
   396 	// This object is not always started thru the CATBase::ExecuteCommand
       
   397 	// So we sometimes have to manually control the flow control of iEventSignalActive
       
   398 	iPhoneGlobals->iEventSignalActive = EFalse;
       
   399 
       
   400 	if (iReqHandle)
       
   401 		{
       
   402 		// Explicit call from a client
       
   403 		if (aError==KErrNone)
       
   404 			{
       
   405 			GetCurrentNetworkInfo(&iNetworkInfo); 
       
   406 			}
       
   407 		iTelObject->ReqCompleted(iReqHandle, aError);
       
   408 		}
       
   409 	else
       
   410 		{
       
   411 		// CheckOperator() call from CATCommands::Complete
       
   412 		iTelObject->FlowControlResume();
       
   413 		}
       
   414 	CATCommands::Complete(aError,aSource);
       
   415 	}
       
   416 
       
   417 void CATNetworkInfo::CompleteWithIOError(TEventSource /*aSource*/,TInt aStatus)
       
   418 /**
       
   419  * This function handles I/O errors that may occur during any of the stages of the state machine.
       
   420  */
       
   421 	{
       
   422 	if (iState!=EATNotInProgress)
       
   423 		{
       
   424 		iIo->WriteAndTimerCancel(this);
       
   425 		if (iReqHandle)
       
   426 			{
       
   427 			iTelObject->ReqCompleted(iReqHandle, aStatus);
       
   428 			}
       
   429 		else
       
   430 			{
       
   431 			// CheckOperator() call from CATCommands::Complete
       
   432 			iTelObject->FlowControlResume();
       
   433 			}
       
   434 		iState = EATNotInProgress;
       
   435 		}
       
   436 	}
       
   437 
       
   438 void CATNetworkInfo::StartGetOperator()
       
   439 /**
       
   440  * This function kicks off the state machine by transmitting the first command, "AT+COPS?" and
       
   441  * setting the state.
       
   442  */
       
   443 	{
       
   444 	iPhoneGlobals->iPhoneStatus.iNetworkChanged=EFalse;
       
   445 	InitializeNetworkInfo();		// Initialize the TNetworkInfo struct that will contain the mobile's responses
       
   446 	iTxBuffer.Copy(KGetCurrentOperatorCommand);
       
   447 	iIo->Write(this, iTxBuffer);
       
   448 	iIo->SetTimeOut(this, 5000);
       
   449 	iState=EATGetCurrentOperatorWriteComplete;
       
   450 	}
       
   451 
       
   452 void CATNetworkInfo::InitializeNetworkInfo()
       
   453 /**
       
   454  * This function is used to initialize (to zero) the network information elements in the CPhoneGlobals
       
   455  * structure.
       
   456  */
       
   457 	{
       
   458 	RMobilePhone::TMobilePhoneNetworkInfoV1& networkinfo = iPhoneGlobals->iPhoneStatus.iCurrentNetwork;
       
   459 
       
   460 	networkinfo.iMode = RMobilePhone::ENetworkModeUnknown;
       
   461 	networkinfo.iCountryCode.Zero();		// Unknown, MCC
       
   462 	networkinfo.iNetworkId.Zero();			// MNC
       
   463 	networkinfo.iCdmaSID.Zero();			// Unused CDMA field
       
   464 	networkinfo.iAnalogSID.Zero();			// Unused CDMA field
       
   465 	networkinfo.iShortName.Zero();
       
   466 	networkinfo.iLongName.Zero();
       
   467 	networkinfo.iStatus = RMobilePhone::ENetworkStatusUnknown; 
       
   468 	networkinfo.iDisplayTag.Zero();
       
   469 	}
       
   470 
       
   471 void CATNetworkInfo::ParseOperatorResponseL()
       
   472 /**
       
   473  * This function is used to parse the ME responses to commands to retrieve numeric, short name 
       
   474  * or long name network information.  Possible responses are:
       
   475  * +COPS: mode, 0, "long format name"
       
   476  * +COPS: mode, 1, "short format name"
       
   477  * +COPS: mode, 2, "operator ID in hex"
       
   478  * +COPS: mode  (no network information available)
       
   479  *
       
   480  * Relevant information is retrieved and written into the CPhoneGlobals class.
       
   481  */
       
   482 	{
       
   483 	RMobilePhone::TMobilePhoneNetworkInfoV1& networkInfo = iPhoneGlobals->iPhoneStatus.iCurrentNetwork; 
       
   484 
       
   485 	ParseBufferLC();	// Parse the buffer and create a linked list with the phone's response
       
   486 
       
   487 	CATParamListEntry* entry;
       
   488 	TDblQueIter<CATParamListEntry> iter(iRxResults);
       
   489 
       
   490 	// The 1st item in the list should be the +COPS: response
       
   491 	entry=iter++;
       
   492 	if (entry && entry->iResultPtr.MatchF(KOperatorResponse)!=0)
       
   493 		User::Leave(KErrGeneral);
       
   494 
       
   495 	// The next item is the mode (this information is not used)
       
   496 	entry=iter++;
       
   497 	if (!entry)
       
   498 		User::Leave(KErrGeneral);  
       
   499 	
       
   500 	// The next item should be the format. If there is no network information then this item
       
   501 	// would be empty. The network status is consequently updated.
       
   502 	entry=iter++;
       
   503 	if (!entry)  // Not connected, so the response is "+COPS: 0"
       
   504 		networkInfo.iStatus=RMobilePhone::ENetworkStatusUnknown;
       
   505 	else	
       
   506 		{
       
   507 		TInt format=CATParamListEntry::EntryValL(entry);
       
   508 		
       
   509 		// If the format is available, the network name is the next item in the list 
       
   510 		entry=iter++;
       
   511 		if (!entry)
       
   512 			User::Leave(KErrGeneral);
       
   513 		switch (format)
       
   514 			{
       
   515 		case 0:
       
   516 			if((entry->iResultPtr).Length() > networkInfo.iLongName.MaxLength())
       
   517 				networkInfo.iLongName.Copy((entry->iResultPtr).Mid(0,networkInfo.iLongName.MaxLength()));			
       
   518 			else
       
   519 				networkInfo.iLongName.Copy(entry->iResultPtr);
       
   520 			break;
       
   521 		case 1:
       
   522 			if((entry->iResultPtr).Length() > networkInfo.iShortName.MaxLength())
       
   523 				networkInfo.iShortName.Copy((entry->iResultPtr).Mid(0,networkInfo.iShortName.MaxLength()));			
       
   524 			else 
       
   525 				networkInfo.iShortName.Copy(entry->iResultPtr);	
       
   526 			break;
       
   527 		case 2:
       
   528 			User::LeaveIfError(NetworkIdL(entry->iResultPtr,networkInfo.iCountryCode, networkInfo.iNetworkId));
       
   529 			break;
       
   530 		default:
       
   531 			User::Leave(KErrGeneral);
       
   532 			break;
       
   533 			}
       
   534 
       
   535 		// We've got an answer, so this must be the current network
       
   536 		networkInfo.iStatus=RMobilePhone::ENetworkStatusCurrent;
       
   537 		}
       
   538 	CleanupStack::PopAndDestroy();
       
   539 	}
       
   540 
       
   541 void CATNetworkInfo::GetCurrentNetworkInfo(CATNetworkInfo::TTsyNetworkInfo* aNetworkInfo)
       
   542 /**
       
   543  * This function checks to see if the network registration information in CPhoneGlobals is valid,
       
   544  * and, if it is, it copies the CPhoneGlobals network information into the waiting client request
       
   545  * buffer.
       
   546  */
       
   547 	{
       
   548 	RMobilePhone::TMobilePhoneNetworkInfoV1& networkInfo = (*(aNetworkInfo->iNetworkInfoPckg))();
       
   549 	RMobilePhone::TMobilePhoneLocationAreaV1& areaInfo = *(aNetworkInfo->iArea);
       
   550 	RMobilePhone::TMobilePhoneRegistrationStatus status = iPhoneGlobals->iPhoneStatus.iRegistrationStatus;
       
   551 
       
   552 	if (status == RMobilePhone::ERegisteredOnHomeNetwork
       
   553 		|| status == RMobilePhone::ERegisteredRoaming
       
   554 		|| status == RMobilePhone::ERegistrationUnknown) // AT+CREG? is not supported, but info obtained during initialization is still valid. NickyM
       
   555 		{
       
   556 		RMobilePhone::TMobilePhoneNetworkInfoV1& info = iPhoneGlobals->iPhoneStatus.iCurrentNetwork;
       
   557 		RMobilePhone::TMobilePhoneLocationAreaV1& locationInfo = iPhoneGlobals->iPhoneStatus.iLocationArea;
       
   558 
       
   559 		networkInfo.iStatus			= info.iStatus;
       
   560 		networkInfo.iCountryCode	= info.iCountryCode;	
       
   561 		networkInfo.iNetworkId		= info.iNetworkId;
       
   562 		networkInfo.iCdmaSID		= info.iCdmaSID;   // for CDMA
       
   563 		networkInfo.iAnalogSID		= info.iAnalogSID; // for CDMA
       
   564 		networkInfo.iShortName		= info.iShortName;
       
   565 		networkInfo.iLongName		= info.iLongName;
       
   566 		networkInfo.iDisplayTag		= info.iLongName;		// This TSY handles the display tag as the same as longname
       
   567 		networkInfo.iMode			= iPhoneGlobals->iNetworkMode;
       
   568 		areaInfo.iAreaKnown			= locationInfo.iAreaKnown;
       
   569 		areaInfo.iLocationAreaCode	= locationInfo.iLocationAreaCode;
       
   570 		areaInfo.iCellId			= locationInfo.iCellId;
       
   571 		}
       
   572 	else
       
   573 		{
       
   574 		networkInfo.iStatus			= RMobilePhone::ENetworkStatusUnknown;
       
   575 		networkInfo.iShortName.Zero();			// Should this be .Zero() ?
       
   576 		networkInfo.iLongName.Zero();			// Should this be .Zero() ?
       
   577 		areaInfo.iAreaKnown			= EFalse;	
       
   578 		areaInfo.iLocationAreaCode	= 0;
       
   579 		areaInfo.iCellId			= 0;
       
   580 
       
   581 		}
       
   582 	return;
       
   583 	}
       
   584 
       
   585 
       
   586 // class CNotifyNetworkRegistrationStatusChange
       
   587 
       
   588 CNotifyNetworkRegistrationStatusChange* CNotifyNetworkRegistrationStatusChange::NewL(TTsyReqHandle aReqHandle,CTelObject* aTelObject, 
       
   589 																					 RMobilePhone::TMobilePhoneRegistrationStatus* aRegStatus)
       
   590 	{
       
   591 	return new(ELeave) CNotifyNetworkRegistrationStatusChange(aReqHandle,aTelObject,aRegStatus);
       
   592 	}
       
   593 
       
   594 CNotifyNetworkRegistrationStatusChange::CNotifyNetworkRegistrationStatusChange(TTsyReqHandle aReqHandle,CTelObject* aTelObject, 
       
   595 																			   RMobilePhone::TMobilePhoneRegistrationStatus* aRegStatus)
       
   596 	: CNotifyBase(aReqHandle,aTelObject)
       
   597 	{
       
   598 	iRegStatus = aRegStatus;
       
   599 	}
       
   600 
       
   601 CNotifyNetworkRegistrationStatusChange::~CNotifyNetworkRegistrationStatusChange()
       
   602 	{}
       
   603 
       
   604 TBool CNotifyNetworkRegistrationStatusChange::CheckAndCompleteNotification(CTelObject* aTelObject, TEvent aEvent, TEvent /*aLastEvent*/)
       
   605 /**
       
   606  * This function completes a Registration status Notification.
       
   607  */
       
   608 	{	
       
   609 	if (aEvent!=ERegistrationStatusChanged)
       
   610 		return EFalse;
       
   611 
       
   612 	LOGTEXT2(_L8("Event %d:\tRegistration Status Changed Notification completed"),aEvent);
       
   613 	*iRegStatus = reinterpret_cast<CPhoneMobile*>(aTelObject)->RegistrationStatus();
       
   614 	iTelObject->ReqCompleted(iReqHandle,KErrNone);
       
   615 	return ETrue;
       
   616 	}
       
   617 
       
   618 // class CCurrentNetworkChangedNotify
       
   619 
       
   620 CNotifyCurrentNetworkChange* CNotifyCurrentNetworkChange::NewL(TTsyReqHandle aReqHandle,CTelObject* aTelObject,TInt* aInfo)
       
   621 	{	
       
   622 	return new(ELeave) CNotifyCurrentNetworkChange(aReqHandle,aTelObject,aInfo);
       
   623 	}
       
   624 
       
   625 CNotifyCurrentNetworkChange::CNotifyCurrentNetworkChange(TTsyReqHandle aReqHandle,CTelObject* aTelObject,TInt* aInfo)
       
   626 	: CNotifyBase(aReqHandle,aTelObject)
       
   627 	{
       
   628 	CATNetworkInfo::TTsyNetworkInfo* info = reinterpret_cast<CATNetworkInfo::TTsyNetworkInfo*>(aInfo);
       
   629 	iNetworkInfo.iNetworkInfoPckg = info->iNetworkInfoPckg;
       
   630 	iNetworkInfo.iArea = info->iArea;
       
   631 	}
       
   632 
       
   633 CNotifyCurrentNetworkChange::~CNotifyCurrentNetworkChange()
       
   634 	{}
       
   635 
       
   636 TBool CNotifyCurrentNetworkChange::CheckAndCompleteNotification(CTelObject* aTelObject,TEvent aEvent,TEvent /*aLastEvent*/)
       
   637 /**
       
   638  * This function completes a Current Network Change Notification.
       
   639  */
       
   640 	{	
       
   641 	if (aEvent!=ECurrentNetworkChanged)
       
   642 		return EFalse; 
       
   643 
       
   644 	LOGTEXT2(_L8("Event %d:\tCurrent Network Changed Notification completed"),aEvent);
       
   645 //	REINTERPRET_CAST(CPhoneMobile*,aTelObject)->CurrentNetworkInfo(&iNetworkInfo);
       
   646 	reinterpret_cast<CPhoneMobile*>(aTelObject)->CurrentNetworkInfo(&iNetworkInfo);
       
   647 	iTelObject->ReqCompleted(iReqHandle,KErrNone);
       
   648 	return ETrue;
       
   649 	}
       
   650 
       
   651 // Class CATDetectNetwork
       
   652 //
       
   653 // Detect all available networks.
       
   654 
       
   655 CATDetectNetwork::CATDetectNetwork(CATIO* aIo, CTelObject* aTelObject, CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
       
   656 	: CATCommands(aIo,aTelObject,aInit,aPhoneGlobals)
       
   657 	{}
       
   658 
       
   659 CATDetectNetwork* CATDetectNetwork::NewL(CATIO* aIo,CTelObject* aTelObject,CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
       
   660 /**
       
   661  * Standard 2 phase constructor.
       
   662  */
       
   663 	{
       
   664 	CATDetectNetwork* self = new(ELeave) CATDetectNetwork(aIo, aTelObject, aInit, aPhoneGlobals);
       
   665 	CleanupStack::PushL(self);
       
   666 	self->ConstructL();
       
   667 	CleanupStack::Pop();
       
   668 	return self;
       
   669 	}
       
   670 
       
   671 CATDetectNetwork::~CATDetectNetwork()
       
   672 /**
       
   673  * Destructor.
       
   674  */
       
   675 	{
       
   676 	iIo->RemoveExpectStrings(this);
       
   677 	}
       
   678 
       
   679 void CATDetectNetwork::Start(TTsyReqHandle aTsyReqHandle,TAny* aParam)
       
   680 /**
       
   681  * This is the standard entry point for retrieving the detected Operator Information.
       
   682  */
       
   683 	{
       
   684 	LOGTEXT(_L8("MMTsy:\tCATDetectNetwork:\tStarting Network detection"));
       
   685 	if (aParam != NULL)
       
   686 		{
       
   687 		TTsyDetectedNetworks*  info = static_cast<TTsyDetectedNetworks* >(aParam);
       
   688 		iDetectedNetworks.iBufSize = info->iBufSize;
       
   689 		iDetectedNetworks.iBufPtr = info->iBufPtr;
       
   690 		}
       
   691 
       
   692 	iReqHandle = aTsyReqHandle;
       
   693 
       
   694 	WriteExpectingResults(KDetectNetworkCommand, 3);
       
   695 	__ASSERT_ALWAYS(iIo->AddExpectString(this,KNotifyMeIfErrorString) != NULL,Panic(EGeneral));
       
   696 	iState=EATDetectWaitForWriteComplete;
       
   697 	}
       
   698 
       
   699 void CATDetectNetwork::EventSignal(TEventSource aSource)
       
   700 /**
       
   701  * This function contains the state machine for the command.  The states flow consecutively and are
       
   702  * described below.
       
   703  * 
       
   704  * \par EATDetectWaitForWriteComplete
       
   705  * Wait for the "AT+COPS=?" write to complete
       
   706  *
       
   707  * \par EATDetectReadComplete
       
   708  * Reads the Modem's response to the AT+COPS=? command.  If it gets an "ERROR" back it resets the 
       
   709  * timer and sets a new state (EATDetectExtendedReadComplete) and waits for another response.
       
   710  *
       
   711  * \par EATDetectExtendedReadComplete
       
   712  * Reads the phone's response to the AT+COPS=? command and parses the response. Completes the
       
   713  * request.
       
   714  *
       
   715  * \par EATWaitForStopState
       
   716  * This state is used when stopping the state machine to ensure that a pending modem response has been
       
   717  * retrieved before freeing up the Multimode TSY to send more commands.  Prematurely stopping the state machine
       
   718  * is usually forced by a client cancel request.
       
   719  */
       
   720 	{
       
   721 	if (aSource==ETimeOutCompletion)
       
   722 		{
       
   723 		if (iState!=EATDetectExtendedReadComplete)
       
   724 			{
       
   725 			LOGTEXT(_L8("MmTsy:\tCATDetectNetwork:\tTimeout Error during Network Detect read"));
       
   726 			RemoveStdExpectStrings();
       
   727 			Complete(KErrTimedOut,aSource);
       
   728 			return;
       
   729 			}
       
   730 		else
       
   731 			{
       
   732 			// the phone really does not support +COPS=?, so report that error
       
   733 			RemoveStdExpectStrings();
       
   734 			Complete(KErrNotSupported,EReadCompletion);
       
   735 			return;
       
   736 			}
       
   737 		}
       
   738 
       
   739 	switch(iState)
       
   740 		{
       
   741 	case EATDetectWaitForWriteComplete:
       
   742 		__ASSERT_ALWAYS(aSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected));
       
   743 		{
       
   744 		iIo->WriteAndTimerCancel(this);
       
   745 		iIo->SetTimeOut(this,45 * KOneSecondPause); // Some phones take a long time to detect all the networks
       
   746 		AddStdExpectStrings();
       
   747 		iState=EATDetectReadComplete;
       
   748 		}
       
   749 		break;
       
   750 
       
   751 	case EATDetectReadComplete:
       
   752 		__ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));
       
   753 		iIo->WriteAndTimerCancel(this);
       
   754 		if (iIo->FoundChatString()==iErrorExpectString)
       
   755 			{
       
   756 			LOGTEXT(_L8("Modem returned ERROR - waiting for further response"));
       
   757 			iIo->ClearCurrentLine();
       
   758 			iIo->SetTimeOut(this,45 * KOneSecondPause);
       
   759 			iState = EATDetectExtendedReadComplete;
       
   760 			break;
       
   761 			}
       
   762 		// fall through ...
       
   763 
       
   764 	case EATDetectExtendedReadComplete:
       
   765 		__ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));
       
   766 		iIo->WriteAndTimerCancel(this);
       
   767 		{
       
   768 		TInt ret(ValidateExpectString());
       
   769 		RemoveStdExpectStrings();
       
   770 		if (ret==KErrNone)
       
   771 			TRAP(ret,ParseResponseL());
       
   772 		Complete(ret,aSource); // The return value is set in the Complete methode
       
   773 		}
       
   774 		break;
       
   775 
       
   776 	case EATWaitForStopState:
       
   777 		__ASSERT_ALWAYS(aSource==EReadCompletion, Panic(EATCommand_IllegalCompletionReadExpected));
       
   778 		{
       
   779 		iIo->WriteAndTimerCancel(this);
       
   780 		Complete(KErrCancel, aSource);
       
   781 		}
       
   782 		break;
       
   783 
       
   784 	default:
       
   785 		break;
       
   786 		}//switch
       
   787 	}//EventSignal
       
   788 
       
   789 void CATDetectNetwork::Stop(TTsyReqHandle aTsyReqHandle)
       
   790 /**
       
   791  * This function is used to prematurely stop the state machine.  This would usually occur following a
       
   792  * client cancel request.
       
   793  */
       
   794 	{
       
   795 	__ASSERT_ALWAYS(aTsyReqHandle == iReqHandle, Panic(EIllegalTsyReqHandle));
       
   796 	LOGTEXT(_L8("MMTsy:\tCATDetectNetwork:\tCancel called."));
       
   797 	switch(iState)
       
   798 		{
       
   799 		case EATNotInProgress:
       
   800 		case EATDetectWaitForWriteComplete:
       
   801 			{
       
   802 			LOGTEXT2(_L8("Current state TSY is cancelling from %d"), iState);
       
   803 			Complete(KErrCancel, EReadCompletion);
       
   804 			}
       
   805 			break;
       
   806 
       
   807 		default:
       
   808 			{
       
   809 			LOGTEXT(_L8("MmTsy:\tCATDetectNetwork:\tStop, now waiting for expected modem response"));
       
   810 			AddStdExpectStrings();
       
   811 			iIo->SetTimeOut(this);
       
   812 			iState = EATWaitForStopState;
       
   813 			}
       
   814 			break;
       
   815 		}
       
   816 	}
       
   817 
       
   818 
       
   819 void CATDetectNetwork::Complete(TInt aError,TEventSource aSource)
       
   820 /**
       
   821  * This function completes the client request.
       
   822  */
       
   823 	{
       
   824 	iState = EATNotInProgress;
       
   825 	iIo->WriteAndTimerCancel(this);
       
   826 	iIo->RemoveExpectStrings(this);
       
   827 	iOKExpectString = NULL;
       
   828 	iErrorExpectString = NULL;
       
   829 	CATCommands::Complete(aError,aSource);
       
   830 
       
   831 	LOGTEXT2(_L8("MMTsy:CATDetectNetwork:\tCATDetectNetwork completed with error code : %d"), aError);
       
   832 	if (aError==KErrCancel)
       
   833 		{
       
   834 		CPhoneMobile* phone = static_cast<CPhoneMobile*>(iTelObject);
       
   835 		phone->CompleteDetectedNetworksCancel(iReqHandle);
       
   836 		}
       
   837 	else
       
   838 		iTelObject->ReqCompleted(iReqHandle, aError);
       
   839 	}
       
   840 
       
   841 void CATDetectNetwork::CompleteWithIOError(TEventSource /*aSource*/,TInt aStatus)
       
   842 /**
       
   843  * This function handles I/O errors that may occur during any of the stages of the state machine.
       
   844  */
       
   845 	{
       
   846 	if (iState!=EATNotInProgress)
       
   847 		{
       
   848 		iIo->WriteAndTimerCancel(this);
       
   849 		iState = EATNotInProgress;
       
   850 		iTelObject->ReqCompleted(iReqHandle, aStatus);
       
   851 		}
       
   852 	}
       
   853 
       
   854 void CATDetectNetwork::ParseResponseL()
       
   855 /**
       
   856  * This function parses the phone's response to the Detect Networks command.
       
   857  */
       
   858 	{
       
   859 	// should be
       
   860 	//
       
   861 	// +COPS: (status,"longname","shortname",code),... ,,(list),(list)
       
   862 	//
       
   863 	// but SH888 gives
       
   864 	//
       
   865 	// +COPS: (status,"longname","shortname",code)<cr><lf>
       
   866 	// +COPS: ...
       
   867 	//
       
   868 
       
   869 	CMobilePhoneNetworkList* list=CMobilePhoneNetworkList::NewL();
       
   870 	CleanupStack::PushL(list);
       
   871 
       
   872 	ParseBufferLC();
       
   873 
       
   874 	RMobilePhone::TMobilePhoneNetworkInfoV1 info;	
       
   875 	// This TSY only supports GSM mode so we can hardcode this
       
   876 	info.iMode=RMobilePhone::ENetworkModeGsm;
       
   877 	TDblQueIter<CATParamListEntry> iter(iRxResults);
       
   878 	CATParamListEntry* entry=iter++;
       
   879 	if (entry)
       
   880 		{
       
   881 		if (entry->iResultPtr!=KOperatorResponse)
       
   882 			User::Leave(KErrGeneral);
       
   883 		//
       
   884 		entry=iter++;
       
   885 		if (!entry)
       
   886 			User::Leave(KErrGeneral);
       
   887 		for (;;)
       
   888 			{
       
   889 			info.iStatus = RMobilePhone::TMobilePhoneNetworkStatus(CATParamListEntry::EntryValL(entry));
       
   890 			//
       
   891 			entry=iter++;
       
   892 			if (!entry)
       
   893 				User::Leave(KErrGeneral);
       
   894 			info.iLongName.Copy(entry->iResultPtr);		
       
   895 			//
       
   896 			entry=iter++;
       
   897 			if (!entry)
       
   898 				User::Leave(KErrGeneral);
       
   899 			if((entry->iResultPtr).Length() > info.iShortName.MaxLength())
       
   900 				info.iShortName.Copy((entry->iResultPtr).Mid(0,info.iShortName.MaxLength()));			
       
   901 			else
       
   902 				info.iShortName.Copy(entry->iResultPtr);
       
   903 			//
       
   904 			entry=iter++;
       
   905 			if (!entry)
       
   906 				User::Leave(KErrGeneral);
       
   907 			User::LeaveIfError(NetworkIdL(entry->iResultPtr,info.iCountryCode, info.iNetworkId));  // MNC and MCC	
       
   908 			
       
   909 			list->AddEntryL(info); 
       
   910 		
       
   911 			entry=iter++;
       
   912 			if (!entry)
       
   913 				break;
       
   914 			if (entry->iResultPtr.Length()==0)
       
   915 				break;
       
   916 			if (entry->iResultPtr!=KOperatorResponse)
       
   917 				continue;
       
   918 			entry=iter++;
       
   919 			if (!entry)
       
   920 				break;
       
   921 			}
       
   922 		}
       
   923 
       
   924 	CleanupStack::PopAndDestroy();			// results
       
   925 
       
   926 	*(iDetectedNetworks.iBufPtr) = list->StoreLC();	 // Stream the list to optimice the size of it.
       
   927 	*(iDetectedNetworks.iBufSize) = (*(iDetectedNetworks.iBufPtr))->Size(); // Store the size of the streamed list to be passed back to the client.   
       
   928 
       
   929 	CleanupStack::Pop();					// pop the CBufBase allocated by StoreLC
       
   930 	CleanupStack::PopAndDestroy();			// pop AND detroy the list.
       
   931 
       
   932 	} // End of ParseResponseL()  
       
   933 
       
   934 
       
   935