localconnectivityservice/modematplugin/src/atcopscmd.cpp
changeset 1 388a17646e40
child 5 11d83199e2d9
equal deleted inserted replaced
0:c3e98f10fcf4 1:388a17646e40
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Handles the commands "AT+COPS?", "AT+COPS=?" and "AT+COPS=..."
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <MmTsy_names.h>
       
    20 #include "atcopscmd.h"
       
    21 #include "cmdpluginobserver.h"
       
    22 #include "debug.h"
       
    23 
       
    24 _LIT8( KCOPSTestCmd, "AT+COPS=?");
       
    25 _LIT8( KCOPSReadCmd, "AT+COPS?");
       
    26 _LIT8( KCOPSSetCmd,  "AT+COPS=");
       
    27 
       
    28 _LIT8(KSupportedModesStr, ",(0,1,3,4)");
       
    29 _LIT8(KSupportedFormatsStr, ",(0,1,2)"); 
       
    30 
       
    31 // The parameters are in predefined indexes in an incoming AT command. 
       
    32 const TInt KModeParameterIndex     			= 0;  
       
    33 const TInt KFormatParameterIndex   			= 1;  
       
    34 const TInt KOperatorParameterIndex 			= 2;  
       
    35 const TInt KAccessTechnologyParameterIndex  = 3;  
       
    36 
       
    37 const TInt KMinimumParameterCountWhenModePresent       = 1;  
       
    38 const TInt KMinimumParameterCountWhenFormatPresent     = 2;  
       
    39 const TInt KMinimumParameterCountWhenOperatorPresent   = 3;  
       
    40 const TInt KMinimumParameterCountWhenAccTechPresent    = 4;  
       
    41 
       
    42 // These parameter lengths are derived from 3GPP TS 27.007 V8.4.1
       
    43 const TInt KShortOperatorNameFormatLength 			= 10; 
       
    44 const TInt KLongOperatorNameFormatLength 			= 20; 
       
    45 const TInt KNumericOperatorNameFormatLength 		= 5; 
       
    46 const TInt KMaxNetworkTestResponseAdditionalSize 	= 17; // The maximun length of parts of fixed length. 
       
    47 const TInt KMaxNetworkReadResponseAdditionalSize 	= 28 ; // The maximun length of parts fixed length.
       
    48 
       
    49 // ---------------------------------------------------------------------------
       
    50 // Two-phased constructor.
       
    51 // ---------------------------------------------------------------------------
       
    52 //
       
    53 CATCOPSCmd* CATCOPSCmd::NewL( MCmdPluginObserver* aCallback )
       
    54     {
       
    55     CATCOPSCmd* self = new (ELeave) CATCOPSCmd( aCallback );
       
    56     CleanupStack::PushL( self );
       
    57     self->ConstructL();
       
    58     CleanupStack::Pop( self );
       
    59     return self;
       
    60     }
       
    61 
       
    62 // ---------------------------------------------------------------------------
       
    63 // Destructor.
       
    64 // ---------------------------------------------------------------------------
       
    65 //
       
    66 CATCOPSCmd::~CATCOPSCmd()
       
    67     {
       
    68     iParamArray.ResetAndDestroy(); 
       
    69     iParamArray.Close(); 
       
    70     iPacketService.Close(); 
       
    71     iCustomApi.Close(); 
       
    72     iPhone.Close(); 
       
    73     iServer.Close();
       
    74     delete iDetectedNetworks;
       
    75     delete iRetrieveDetectedNetworks; 
       
    76     }
       
    77 
       
    78 // ---------------------------------------------------------------------------
       
    79 // CATCOPSCmd::CATCOPSCmd
       
    80 // ---------------------------------------------------------------------------
       
    81 //
       
    82 CATCOPSCmd::CATCOPSCmd( MCmdPluginObserver* aCallback ) :
       
    83     CActive(EPriorityStandard),
       
    84     iCallback( aCallback ), 
       
    85 	iFormat(RMmCustomAPI::EOperatorNameMccMnc), 
       
    86     iRegistrationMode(EModeAutomatic), 
       
    87     iAccTech(EAccTechNotSet), 
       
    88     iCurrentOperation(EIdle)
       
    89     {
       
    90     iCmdHandlerType = ECmdHandlerTypeUndefined;
       
    91     }
       
    92 
       
    93 // ---------------------------------------------------------------------------
       
    94 // CATCOPSCmd::ConstructL
       
    95 // ---------------------------------------------------------------------------
       
    96 //
       
    97 void CATCOPSCmd::ConstructL()
       
    98     {
       
    99     if ( !iCallback )
       
   100         {
       
   101         User::Leave( KErrGeneral );
       
   102         }
       
   103     CActiveScheduler::Add(this);
       
   104     LEAVE_IF_ERROR(iServer.Connect());
       
   105     LEAVE_IF_ERROR(iServer.LoadPhoneModule(KMmTsyModuleName));
       
   106     LEAVE_IF_ERROR(iPhone.Open(iServer, KMmTsyPhoneName));
       
   107     LEAVE_IF_ERROR(iCustomApi.Open(iPhone));
       
   108     LEAVE_IF_ERROR(iPacketService.Open(iPhone));
       
   109     iRetrieveDetectedNetworks = CRetrieveMobilePhoneDetectedNetworks::NewL(iPhone); 
       
   110     }
       
   111 
       
   112 // ---------------------------------------------------------------------------
       
   113 // Reports the support status of an AT command. This is a synchronous API.
       
   114 // ---------------------------------------------------------------------------
       
   115 //
       
   116 TBool CATCOPSCmd::IsCommandSupported( const TDesC8& aCmd )
       
   117     {
       
   118     TRACE_FUNC_ENTRY
       
   119     TInt retTemp = KErrNone;
       
   120 
       
   121 		// First test if "test" command, because the pattern is similar with the "set" command, 
       
   122 		// this is just one extra question mark longer than that. 
       
   123     retTemp = aCmd.Compare( KCOPSTestCmd );
       
   124     if ( retTemp == 0 )
       
   125         {
       
   126         iCmdHandlerType = ECmdHandlerTypeTest;
       
   127         TRACE_FUNC_EXIT
       
   128         return ETrue;
       
   129         }
       
   130 
       
   131     retTemp = aCmd.Compare( KCOPSReadCmd );
       
   132     if ( retTemp == 0 )
       
   133         {
       
   134         iCmdHandlerType = ECmdHandlerTypeRead;
       
   135         TRACE_FUNC_EXIT
       
   136         return ETrue;
       
   137         }
       
   138 
       
   139 	// Test if the beginning matches the test command pattern. We're skipping parameters 
       
   140 	// here on purpose, because "set" handler will create an error reply later if 
       
   141 	// parameters are not valid. 
       
   142     retTemp = aCmd.Left(KCOPSSetCmd().Length()).Compare(KCOPSSetCmd);
       
   143     if ( retTemp == 0 )
       
   144         {
       
   145         iCmdHandlerType = ECmdHandlerTypeSet;
       
   146         TRACE_FUNC_EXIT
       
   147         return ETrue;
       
   148         }
       
   149 
       
   150     iCmdHandlerType = ECmdHandlerTypeUndefined;
       
   151     TRACE_FUNC_EXIT
       
   152     return EFalse;
       
   153     }
       
   154 
       
   155 // ---------------------------------------------------------------------------
       
   156 // Handles an AT command. Cancelling of the pending request is done by
       
   157 // HandleCommandCancel(). The implementation in the extension plugin should
       
   158 // be asynchronous.
       
   159 // ---------------------------------------------------------------------------
       
   160 //
       
   161 void CATCOPSCmd::HandleCommand( const TDesC8& aCmd,
       
   162                                    RBuf8& aReply,
       
   163                                    TBool aReplyNeeded )
       
   164     {
       
   165     TRACE_FUNC_ENTRY
       
   166 
       
   167     if ( !aReplyNeeded )
       
   168         {
       
   169         TRACE_FUNC_EXIT
       
   170         return;
       
   171         }
       
   172 
       
   173     if(iCurrentOperation != EIdle)  
       
   174         {
       
   175         // only one call at time allowed. If another one is passed in, 
       
   176         // then cancel the previous and reply with an error.   
       
   177         HandleCommandCancel(); 
       
   178         CreateReply(EFalse); 
       
   179         }
       
   180     
       
   181     if ( iCmdHandlerType == ECmdHandlerTypeUndefined )
       
   182         {
       
   183 		CreateReply(EFalse); 
       
   184 		}
       
   185 
       
   186     if ( iCmdHandlerType == ECmdHandlerTypeTest )
       
   187         {
       
   188         // Collect network data and complete in RunL 
       
   189         iRetrieveDetectedNetworks->StartV2(iStatus); 
       
   190         iCurrentOperation = EListAvailableNetworkOperators; 
       
   191         SetActive(); 
       
   192         TRACE_FUNC_EXIT
       
   193         return;
       
   194         }
       
   195 
       
   196 /*
       
   197 Read command returns the current mode, the currently selected operator 
       
   198 and the current Access Technology. If no operator is selected, <format>, 
       
   199 <oper> and < AcT>  are omitted.
       
   200 */
       
   201     if ( iCmdHandlerType == ECmdHandlerTypeRead )
       
   202         {
       
   203         // Collect data in two steps. First read operator name. Continue in RunL() 
       
   204         RMobilePhone::TMobilePhoneNetworkSelectionV1 selection; 
       
   205         RMobilePhone::TMobilePhoneNetworkSelectionV1Pckg nwSelectionSetting(selection); 
       
   206         iPhone.GetNetworkSelectionSetting(nwSelectionSetting);
       
   207         switch(selection.iMethod)
       
   208             {
       
   209             case RMobilePhone::ENetworkSelectionAutomatic: 
       
   210                 iRegistrationMode = EModeAutomatic;
       
   211                 break; 
       
   212             case RMobilePhone::ENetworkSelectionManual: 
       
   213                 iRegistrationMode = EModeManual;
       
   214                 break; 
       
   215             default: 
       
   216                 // Cannot get a known selection mode! 
       
   217                 TRACE_INFO(_L("CATCOPSCmd::HandleCommand() -- Cannot get a known selection mode!"));
       
   218                 CreateReply(EFalse); 
       
   219                 TRACE_FUNC_EXIT
       
   220                 return; 
       
   221             }
       
   222         RMobilePhone::TMobilePhoneNetworkInfoV2Pckg nwInfo(iNetworkInfo); 
       
   223         iPhone.GetCurrentNetwork(iStatus, nwInfo); 
       
   224         iCurrentOperation = EGetNetworkInfoOperatorName; 
       
   225 		SetActive(); 
       
   226         TRACE_INFO((_L("CATCOPSCmd::HandleCommand() starting operation (%d)"), iCurrentOperation));
       
   227         TRACE_FUNC_EXIT
       
   228         return;
       
   229         }
       
   230 
       
   231     // Getting this far means ECmdHandlerTypeSet. There must be parameter(s), too.   
       
   232     TRAPD(err, ExtractParametersL(aCmd)); 
       
   233 
       
   234     // Check that we got some parameters, at least the "mode". If not, return an error: 
       
   235 	if(iParamArray.Count() < KMinimumParameterCountWhenModePresent) 
       
   236         {
       
   237         // Return error response, there were no parameters! 
       
   238         TRACE_INFO(_L("CATCOPSCmd::HandleCommand() -- no parameters!"));
       
   239         CreateReply(EFalse); 
       
   240         TRACE_FUNC_EXIT
       
   241         return; 
       
   242         }
       
   243 
       
   244 	// At least the mode parameter is present at this point. Inspect it and check other parameters. 
       
   245 	TNetworkRegistrationMode mode; 
       
   246 	err = GetModeAndCheckParameterCount(iParamArray[KModeParameterIndex]->Des(), mode); 
       
   247 	if(err != KErrNone) 
       
   248 		{
       
   249         // Return error response, invalid mode or other parameters! 
       
   250 		TRACE_INFO(_L("CATCOPSCmd::HandleCommand() -- invalid mode or other parameters!"));
       
   251         CreateReply(EFalse); 
       
   252 	    TRACE_FUNC_EXIT
       
   253         return; 
       
   254 		}
       
   255 
       
   256     // At this point the iRegistrationMode is stored and the parameters are valid. 
       
   257 	iRegistrationMode = mode; 
       
   258 	TRACE_INFO(( _L("CATCOPSCmd::HandleCommand() mode stored (%d)"), iRegistrationMode));
       
   259 		
       
   260 	if(iParamArray.Count() > 1) 
       
   261 		{
       
   262 		// If also format is present, extract it and store for later reference. 
       
   263         RMmCustomAPI::TOperatorNameType format;
       
   264         err = GetFormatFromParameter(iParamArray[KFormatParameterIndex]->Des(), format); 
       
   265 		if(err != KErrNone) 
       
   266 		    {
       
   267 		    // Return an error, invalid format. 
       
   268 			// Previously set format is still in use. 
       
   269 	 		TRACE_INFO(_L("CATCOPSCmd::HandleCommand() -- invalid format!"));
       
   270             CreateReply(EFalse); 
       
   271 	 		TRACE_FUNC_EXIT
       
   272 			return; 
       
   273 			}
       
   274 		// Format parameter is OK, keep it.
       
   275 		iFormat = format;  
       
   276 		TRACE_INFO(( _L("CATCOPSCmd::HandleCommand() format stored (%d)"), iFormat));
       
   277 		}
       
   278 
       
   279 	// We're done with the required parameters, it's time to start processing the command. 
       
   280 	// So do a self complete and continue in RunL(): 
       
   281 	iReply = &aReply;  // Store the reply for later reference in RunL. 
       
   282 	iCurrentOperation = EInspectModeAndProcessCommand; 
       
   283 	TRequestStatus *status = &iStatus;  
       
   284 	User::RequestComplete(status, KErrNone); 
       
   285 	SetActive(); 
       
   286 	TRACE_INFO((_L("CATCOPSCmd::HandleCommand() starting operation (%d)"), iCurrentOperation));
       
   287     TRACE_FUNC_EXIT
       
   288     }
       
   289 
       
   290 // ---------------------------------------------------------------------------
       
   291 // Parses the aCmd parameter and stores results in iParamArray.
       
   292 // ---------------------------------------------------------------------------
       
   293 //
       
   294 void CATCOPSCmd::ExtractParametersL(const TDesC8& aCmd) 
       
   295 	{
       
   296     TRACE_FUNC_ENTRY
       
   297 
       
   298     TRACE_INFO(( _L8("CATCOPSCmd::ExtractParameters() extracting (%S)"), &aCmd));
       
   299 
       
   300     TPtrC8 parameters = aCmd.Right(aCmd.Length() - KCOPSSetCmd().Length()); 
       
   301 
       
   302     iParamArray.ResetAndDestroy(); 
       
   303 
       
   304     // Parse the parameters into the parameter array: 
       
   305     TInt separatorPos;  
       
   306     while((separatorPos = parameters.Locate(',')) != KErrNotFound)
       
   307         {
       
   308         TRACE_INFO(( _L("CATCOPSCmd::ExtractParameters() separator position (%d)"), separatorPos));
       
   309         TPtrC8 param = parameters.Left(separatorPos);
       
   310         parameters.Set(parameters.Right(parameters.Length() - (separatorPos + 1))); // Remove the extracted part + separator 
       
   311         HBufC8 *heapParam = param.AllocL();    
       
   312         CleanupStack::PushL( heapParam );
       
   313         // Strip the quotation marks from the parameter: 
       
   314         TPtr8 ptr = heapParam->Des(); 
       
   315         RemoveQuotationMarks(ptr); 
       
   316         TRACE_INFO(( _L8("CATCOPSCmd::ExtractParameters() appending (%S)"), &ptr));
       
   317         iParamArray.Append(heapParam); 
       
   318         CleanupStack::Pop( heapParam );
       
   319         }
       
   320 
       
   321     // Finally append the last piece of parameters: 
       
   322     HBufC8 *param = parameters.AllocL(); 
       
   323     CleanupStack::PushL( param );
       
   324     TPtr8 ptr = param->Des(); 
       
   325     RemoveQuotationMarks(ptr); 
       
   326     TRACE_INFO(( _L8("CATCOPSCmd::ExtractParameters() appending (%S)"), &ptr));
       
   327     iParamArray.Append(param); 
       
   328     CleanupStack::Pop( param );
       
   329 
       
   330     TRACE_FUNC_EXIT
       
   331 	}
       
   332 
       
   333 // ---------------------------------------------------------------------------
       
   334 // Strips all quotation parms from the string passed in. 
       
   335 // ---------------------------------------------------------------------------
       
   336 //
       
   337 void CATCOPSCmd::RemoveQuotationMarks(TPtr8& aParameter) 
       
   338     {
       
   339     TRACE_FUNC_ENTRY
       
   340     // Strip the quotation marks from the parameter: 
       
   341     TInt quotePos;  
       
   342     while((quotePos = aParameter.Locate('"')) != KErrNotFound)
       
   343     {
       
   344         aParameter.Delete(quotePos,1); 
       
   345     }
       
   346     TRACE_FUNC_EXIT
       
   347     }
       
   348 
       
   349 
       
   350 // ---------------------------------------------------------------------------
       
   351 // Returns the selected mode in aMode and checks the parameter count. 
       
   352 // ---------------------------------------------------------------------------
       
   353 //
       
   354 TInt CATCOPSCmd::GetModeAndCheckParameterCount(const TDesC8& aParameter, TNetworkRegistrationMode &aMode) 
       
   355 	{
       
   356   TRACE_FUNC_ENTRY
       
   357 	TLex8 lex;
       
   358 	lex.Assign(aParameter);
       
   359 	TInt mode(0); 
       
   360 
       
   361 	TInt err = lex.Val(mode); 
       
   362 	TRACE_INFO(( _L("CATCOPSCmd::GetModeAndCheckParameterCount() mode (%d)"), mode));
       
   363 
       
   364 	if( err != KErrNone )
       
   365 		{
       
   366         TRACE_INFO(_L("CATCOPSCmd::GetModeAndCheckParameterCount() TLex error!)"));
       
   367         TRACE_FUNC_EXIT
       
   368         return KErrArgument; 
       
   369 		}			
       
   370 
       
   371   if(mode < EModeAutomatic || mode > EModeManualAutomatic || mode == EModeDeregister)
       
   372       {
       
   373       // Not a valid mode. 
       
   374       TRACE_FUNC_EXIT
       
   375       return KErrArgument; 
       
   376       }
       
   377 
       
   378   if( (mode == EModeManual || mode == EModeManualAutomatic)  &&  iParamArray.Count() < KMinimumParameterCountWhenOperatorPresent )
       
   379       {
       
   380       // Valid modes but not enough parameters. At least format and operator needed.  
       
   381       TRACE_INFO(( _L("CATCOPSCmd::GetModeAndCheckParameterCount() not enough parameters (%d)"), iParamArray.Count()));
       
   382       TRACE_FUNC_EXIT
       
   383       return KErrArgument; 
       
   384       }
       
   385   if( mode == EModeSetFormatParameter && iParamArray.Count() < KMinimumParameterCountWhenFormatPresent )
       
   386       {
       
   387       // Valid mode, but not enough parameters. Format is needed.  
       
   388       TRACE_INFO(_L("CATCOPSCmd::GetModeAndCheckParameterCount() no format parameter)"));
       
   389       TRACE_FUNC_EXIT
       
   390       return KErrArgument; 
       
   391       }
       
   392 
       
   393   // Valid mode and enough parameters. 
       
   394   aMode = static_cast<TNetworkRegistrationMode>(mode);
       
   395 
       
   396 	TRACE_FUNC_EXIT
       
   397 	return KErrNone; 
       
   398 	}
       
   399 
       
   400 // ---------------------------------------------------------------------------
       
   401 // Converts an AT command parameter to numeric format value and checks it is valid. 
       
   402 // ---------------------------------------------------------------------------
       
   403 //
       
   404 TInt CATCOPSCmd::GetFormatFromParameter(const TDesC8& aParameter, RMmCustomAPI::TOperatorNameType &aFormat) 
       
   405 	{
       
   406     TRACE_FUNC_ENTRY
       
   407     TLex8 lex;
       
   408     lex.Assign(aParameter);
       
   409     TInt format(0); 
       
   410     TInt err = lex.Val(format); 
       
   411 
       
   412     if(err != KErrNone)
       
   413         {
       
   414         TRACE_FUNC_EXIT
       
   415         return KErrArgument; 
       
   416         }
       
   417     switch(format)
       
   418         {
       
   419         case EFormatLong: // long by 3GPP TS 27.007 V8.4.1  
       
   420             TRACE_INFO(_L("Format is long by 3GPP TS 27.007 V8.4.1"));
       
   421             aFormat = RMmCustomAPI::EOperatorNameNitzFull; 
       
   422             break; 
       
   423         case EFormatShort: // short by 3GPP TS 27.007 V8.4.1 
       
   424             TRACE_INFO(_L("Format is short by 3GPP TS 27.007 V8.4.1"));
       
   425             aFormat = RMmCustomAPI::EOperatorNameNitzShort; 
       
   426             break; 
       
   427         case EFormatNumeric: // numeric by 3GPP TS 27.007 V8.4.1 
       
   428             TRACE_INFO(_L("Format is numeric by 3GPP TS 27.007 V8.4.1"));
       
   429             aFormat = RMmCustomAPI::EOperatorNameMccMnc; 
       
   430             // Operator is numeric, conver it into S60 style. 
       
   431             break; 
       
   432         default: 
       
   433             TRACE_FUNC_EXIT
       
   434             return KErrArgument;
       
   435         }
       
   436 
       
   437     TRACE_FUNC_EXIT
       
   438     return KErrNone; 
       
   439     }
       
   440 
       
   441 // ---------------------------------------------------------------------------
       
   442 // Converts an AT command parameter to numeric access technology value and checks it is valid. 
       
   443 // ---------------------------------------------------------------------------
       
   444 //
       
   445 TInt CATCOPSCmd::GetAccTechFromParameter(const TDesC8& aParameter, TAccessTechnology& aAccTech) 
       
   446     {
       
   447     TRACE_FUNC_ENTRY
       
   448     TLex8 lex;
       
   449     lex.Assign(aParameter);
       
   450     TInt accTech(0); 
       
   451     TInt err = lex.Val(accTech); 
       
   452 
       
   453     if(err != KErrNone)
       
   454         {
       
   455         TRACE_FUNC_EXIT
       
   456         return KErrArgument; 
       
   457         }
       
   458 
       
   459     if(accTech != EGSM && accTech != EUDMA) // The only allowed access technologies. 
       
   460         {
       
   461         TRACE_FUNC_EXIT
       
   462         return KErrArgument; 
       
   463         }
       
   464  
       
   465     aAccTech = static_cast<TAccessTechnology>(accTech);
       
   466 
       
   467     TRACE_FUNC_EXIT
       
   468     return KErrNone; 
       
   469     }
       
   470 
       
   471 // ---------------------------------------------------------------------------
       
   472 // Converts an AT command parameter to ETel compatible operator values 
       
   473 // ---------------------------------------------------------------------------
       
   474 //
       
   475 TInt CATCOPSCmd::ConvertOperatorToMccMnc(const CMobilePhoneNetworkListV2 *aDetectedNetworks, 
       
   476                                         const RMmCustomAPI::TOperatorNameType aFormat, 
       
   477                                         const TBuf<KMaxOperatorNameLength>& aOperatorParameter, 
       
   478                                         RMobilePhone::TMobilePhoneNetworkCountryCode& aMcc, 
       
   479                                         RMobilePhone::TMobilePhoneNetworkIdentity& aMnc) 
       
   480     {
       
   481     TRACE_FUNC_ENTRY
       
   482 
       
   483     if(aFormat == RMmCustomAPI::EOperatorNameMccMnc) 
       
   484         {
       
   485         // Check first that there are at least five characters passed in. 
       
   486        	TChar nextChar; 
       
   487         if(aOperatorParameter.Length() < 5)
       
   488         	{
       
   489 			return KErrArgument; 
       
   490         	}
       
   491         for(int i = 0; i < 5; ++i)
       
   492         	{
       
   493             nextChar = aOperatorParameter[i]; 
       
   494             if(!nextChar.IsDigit()) 
       
   495                 {
       
   496                 return KErrArgument; 
       
   497                 }
       
   498       		}
       
   499         // Operator is in three digit country code + two digit network code format.  
       
   500 	    // Must be converted to ETel style. The possible extra will be simply discarded. 
       
   501      	TRACE_INFO(_L("CATCOPSCmd::ConvertOperatorToMccMnc() operator is all digits, convert it into ETel data types."));
       
   502 	    aMcc.Copy(aOperatorParameter.Left(3)); 
       
   503 	    aMnc.Copy(aOperatorParameter.Right(2)); 
       
   504 	    }
       
   505     else  // The short or long text string formats. 
       
   506         {
       
   507         // Find the requested operator from the operator array.  
       
   508         // If array is empty, return an error. 
       
   509         if(!aDetectedNetworks)
       
   510             {
       
   511             TRACE_INFO(_L("CATCOPSCmd::ConvertOperatorToMccMnc() No detected networks!"));
       
   512             TRACE_FUNC_EXIT
       
   513             return KErrNotFound; 
       
   514             }
       
   515 
       
   516         RMobilePhone::TMobilePhoneNetworkInfoV2 nwInfo; 
       
   517         for(TInt i=0; i < iDetectedNetworks->Enumerate(); ++i)
       
   518             {
       
   519             TRAPD(err, nwInfo = iDetectedNetworks->GetEntryL(i))  
       
   520             if(err != KErrNone)
       
   521                 {
       
   522                 return KErrNotFound; 
       
   523                 }
       
   524 
       
   525             if(aFormat == RMmCustomAPI::EOperatorNameNitzShort)
       
   526                 {
       
   527                 TRACE_INFO(_L("CATCOPSCmd::ConvertOperatorToMccMnc() Operator is in short format, comparing."));
       
   528                 if(nwInfo.iShortName.Compare(aOperatorParameter) == 0)
       
   529                     {
       
   530                     TRACE_INFO(_L("Match found."));
       
   531                     aMcc = nwInfo.iCountryCode; 
       
   532                     aMnc = nwInfo.iNetworkId; 
       
   533                     TRACE_FUNC_EXIT
       
   534                     return KErrNone; 
       
   535                     } 
       
   536                 }
       
   537             else if(aFormat == RMmCustomAPI::EOperatorNameNitzFull)
       
   538                 {
       
   539                 TRACE_INFO(_L("CATCOPSCmd::ConvertOperatorToMccMnc() Operator is in long format, comparing."));
       
   540                 if(nwInfo.iLongName.Compare(aOperatorParameter) == 0)
       
   541                     {
       
   542                     TRACE_INFO(_L("Match found."));
       
   543                     aMcc = nwInfo.iCountryCode; 
       
   544                     aMnc = nwInfo.iNetworkId; 
       
   545                     TRACE_FUNC_EXIT
       
   546                     return KErrNone; 
       
   547                     } 
       
   548                 }
       
   549             else        
       
   550                 {
       
   551                 TRACE_INFO(_L("CATCOPSCmd::ConvertOperatorToMccMnc() Unknown operator format!"));
       
   552                 TRACE_FUNC_EXIT
       
   553                 return KErrArgument; 
       
   554                 }
       
   555             }
       
   556         TRACE_INFO(_L("CATCOPSCmd::ConvertOperatorToMccMnc() Operator was not found in list!"));
       
   557         TRACE_FUNC_EXIT
       
   558         return KErrNotFound; 
       
   559         }
       
   560 
       
   561     TRACE_FUNC_EXIT
       
   562     return KErrNone; 
       
   563     }
       
   564 
       
   565 
       
   566 // ---------------------------------------------------------------------------
       
   567 // Initiates an automatic network registration.  
       
   568 // ---------------------------------------------------------------------------
       
   569 //
       
   570 void CATCOPSCmd::AutomaticNetworkRegistration() 
       
   571     {
       
   572     TRACE_FUNC_ENTRY
       
   573     RMobilePhone::TMobilePhoneNetworkManualSelection nwInfo; 
       
   574 	iCurrentOperation = EAutomaticallyRegisterToNetwork; 
       
   575 	nwInfo.iCountry = KNullDesC;
       
   576 	nwInfo.iNetwork = KNullDesC;
       
   577 	iPhone.SelectNetwork(iStatus, EFalse, nwInfo); 
       
   578 	SetActive();  // Response will be sent in RunL 
       
   579 	TRACE_INFO((_L("CATCOPSCmd::HandleCommand() starting operation (%d)"), iCurrentOperation));
       
   580 	TRACE_FUNC_EXIT
       
   581 	}
       
   582 
       
   583 // ---------------------------------------------------------------------------
       
   584 // Initiates a manual network registration.  
       
   585 // ---------------------------------------------------------------------------
       
   586 //
       
   587 void CATCOPSCmd::ManualNetworkRegistration(const RMobilePhone::TMobilePhoneNetworkCountryCode& aMcc, 
       
   588                                            const RMobilePhone::TMobilePhoneNetworkIdentity& aMnc) 
       
   589     {
       
   590 	TRACE_FUNC_ENTRY
       
   591 	RMobilePhone::TMobilePhoneNetworkManualSelection nwInfo; 
       
   592 	iCurrentOperation = EManuallyRegisterToNetwork; 
       
   593 	nwInfo.iCountry.Append(aMcc);
       
   594 	nwInfo.iNetwork.Append(aMnc);
       
   595 	iPhone.SelectNetwork(iStatus, ETrue, nwInfo); 
       
   596 	SetActive(); 	// Response will be sent in RunL 
       
   597 	TRACE_INFO((_L("CATCOPSCmd::HandleCommand() starting operation (%d)"), iCurrentOperation));
       
   598 	TRACE_FUNC_EXIT
       
   599     }
       
   600 
       
   601 // ---------------------------------------------------------------------------
       
   602 // Initiates a manual network registration and access technology selection.  
       
   603 // ---------------------------------------------------------------------------
       
   604 //
       
   605 void CATCOPSCmd::ManualNetworkRegistration(const RMobilePhone::TMobilePhoneNetworkCountryCode& aMcc, 
       
   606                                            const RMobilePhone::TMobilePhoneNetworkIdentity& aMnc, 
       
   607                                            const TAccessTechnology aAccTech) 
       
   608     {
       
   609     TRACE_FUNC_ENTRY
       
   610 	// Store access technology for later reference: 
       
   611     iAccTech = aAccTech; 
       
   612 	// Call another overload to start the first phase of the operation: 
       
   613 	ManualNetworkRegistration(aMcc, aMnc); 
       
   614 	// Set the state again so the RunL knows to launch the next phase: 
       
   615 	iCurrentOperation = EManuallyRegisterToNetworkAndChooseAccTech; 
       
   616   	TRACE_INFO((_L("CATCOPSCmd::HandleCommand() starting operation (%d)"), iCurrentOperation));
       
   617 	TRACE_FUNC_EXIT
       
   618     }
       
   619 
       
   620 // ---------------------------------------------------------------------------
       
   621 // CATCOPSCmd::RunL 
       
   622 // ---------------------------------------------------------------------------
       
   623 //
       
   624 void CATCOPSCmd::RunL()
       
   625     {
       
   626     TRACE_FUNC_ENTRY
       
   627 	TInt err = KErrNone; 
       
   628 	if(iStatus != KErrNone)   
       
   629 	    {
       
   630         HandleError(); 
       
   631 	    }
       
   632     // Proceed to next step or return a response if all is done.
       
   633     switch(iCurrentOperation)
       
   634         {
       
   635         case EListAvailableNetworkOperators: 
       
   636             TRACE_INFO((_L("CATCOPSCmd::HandleCommand() completing operation (%d)"), iCurrentOperation));
       
   637             if(iDetectedNetworks)
       
   638                 {
       
   639                 delete iDetectedNetworks;
       
   640                 iDetectedNetworks = NULL; 
       
   641                 }
       
   642             iDetectedNetworks = iRetrieveDetectedNetworks->RetrieveListV2L(); 
       
   643             // Then create a response. 
       
   644             TRAP(err, ConstructNetworkListResponseL()); 
       
   645             if(err != KErrNone)
       
   646                 {
       
   647                 // An error here means that no response has been sent. Reply with an error. 
       
   648                 CreateReply(EFalse); 
       
   649                 }
       
   650             break; 
       
   651         
       
   652         case EInspectModeAndProcessCommand: 
       
   653             // Check the mode and act accordingly 
       
   654             TRACE_INFO((_L("CATCOPSCmd::HandleCommand() completing operation (%d)"), iCurrentOperation));
       
   655             err = InspectModeAndProcessCommand(); 
       
   656             if(err != KErrNone)
       
   657                 {
       
   658                 CreateReply(EFalse); 
       
   659                 }
       
   660             break; 
       
   661 
       
   662         case EGetNetworkInfoOperatorName: 
       
   663             if(ConstructNetworkInfoResponse() != KErrNone)
       
   664                 {
       
   665                 // An error means that no response has been sent. Reply with an error. 
       
   666                 CreateReply(EFalse); 
       
   667                 }
       
   668             break; 
       
   669 
       
   670         case EManuallyRegisterToNetworkAndChooseAccTech: 
       
   671             TRACE_INFO((_L("CATCOPSCmd::HandleCommand() completing operation (%d)"), iCurrentOperation));
       
   672             switch(iAccTech)
       
   673                 {
       
   674                 case EGSM: 
       
   675                     iCustomApi.SetSystemNetworkMode(iStatus, RMmCustomAPI::KCapsNetworkModeGsm);
       
   676                     iCurrentOperation = ESetSystemNetworkBand; 
       
   677                     SetActive(); 
       
   678                     break; 
       
   679                 case EUDMA: 
       
   680                     iCustomApi.SetSystemNetworkMode(iStatus, RMmCustomAPI::KCapsNetworkModeUmts);
       
   681                     iCurrentOperation = ESetSystemNetworkBand; 
       
   682                     SetActive(); 
       
   683                     break; 
       
   684                 default:
       
   685                     // No automatic registering requested, so send back an error response. 
       
   686                     TRACE_INFO( _L("CATCOPSCmd::RunL() incorrect acc.tech., reply an error."));
       
   687                     CreateReply(EFalse); 
       
   688                 }
       
   689             TRACE_INFO((_L("CATCOPSCmd::HandleCommand() starting operation (%d)"), iCurrentOperation));
       
   690             break; 
       
   691 
       
   692         case EManuallyRegisterToNetwork: 
       
   693         case EAutomaticallyRegisterToNetwork: 
       
   694         case ESetSystemNetworkBand: 
       
   695             TRACE_INFO((_L("CATCOPSCmd::HandleCommand() completing operation (%d)"), iCurrentOperation));
       
   696             // Last step completed successfully, so create OK response. 
       
   697             CreateReply(ETrue); 
       
   698             break; 
       
   699 
       
   700         default: 
       
   701             TRACE_INFO(( _L("CATCOPSCmd::RunL() default operation (%d)!"), iCurrentOperation));
       
   702             break; 
       
   703         }
       
   704     TRACE_FUNC_EXIT
       
   705     }
       
   706 
       
   707 // ---------------------------------------------------------------------------
       
   708 // Handles an error in async call. 
       
   709 // ---------------------------------------------------------------------------
       
   710 //
       
   711 void CATCOPSCmd::HandleError()
       
   712     {
       
   713     TRACE_FUNC_ENTRY
       
   714     TRACE_INFO(( _L("CATCOPSCmd::RunL() failure (%d) in operation (%d)!"), iStatus.Int(), iCurrentOperation));
       
   715 
       
   716     // In case of failure check the operation. In some cases failures are OK.
       
   717     switch(iCurrentOperation)
       
   718         {
       
   719         case EManuallyRegisterToNetwork: 
       
   720             if(iRegistrationMode == EModeManualAutomatic)
       
   721                 {
       
   722                 // Manual registration failed, try automatic next. 
       
   723                 TRACE_INFO( _L("CATCOPSCmd::RunL() registration mode manual automatic, try automatic."));
       
   724                 AutomaticNetworkRegistration(); 
       
   725                 }
       
   726             else 
       
   727                 {
       
   728                 // No automatic registering requested, so send back an error response. 
       
   729                 TRACE_INFO( _L("CATCOPSCmd::RunL() reply an error."));
       
   730                 CreateReply(EFalse); 
       
   731                 }
       
   732             break; 
       
   733         case ESetSystemNetworkBand: 
       
   734         case EManuallyRegisterToNetworkAndChooseAccTech: 
       
   735             // Cannot set the access technology, so set it back to EAccTechNotSet. 
       
   736             // This prevents replying to queries with outdated or incorrect acc tech information. 
       
   737             TRACE_INFO( _L("CATCOPSCmd::RunL() couldn't set system network band, so reset access tech."));
       
   738             iAccTech = EAccTechNotSet; 
       
   739             // Fall through to default, because these require an error response. 
       
   740 
       
   741         default: 
       
   742             // In all other cases send back an error response. 
       
   743             TRACE_INFO( _L("CATCOPSCmd::RunL() reply an error."));
       
   744             CreateReply(EFalse); 
       
   745             break; 
       
   746         }
       
   747     TRACE_FUNC_EXIT
       
   748     }
       
   749 
       
   750 
       
   751 // ---------------------------------------------------------------------------
       
   752 // Cancels a pending HandleCommand request.
       
   753 // ---------------------------------------------------------------------------
       
   754 //
       
   755 void CATCOPSCmd::HandleCommandCancel()
       
   756     {
       
   757     TRACE_FUNC_ENTRY
       
   758     Cancel(); 
       
   759     TRACE_FUNC_EXIT
       
   760     }
       
   761 
       
   762 // ---------------------------------------------------------------------------
       
   763 // CATCOPSCmd::DoCancel
       
   764 // ---------------------------------------------------------------------------
       
   765 //
       
   766 void CATCOPSCmd::DoCancel()
       
   767     {
       
   768     TRACE_FUNC_ENTRY
       
   769     switch(iCurrentOperation)
       
   770         {
       
   771         case EAutomaticallyRegisterToNetwork:
       
   772         case EManuallyRegisterToNetwork:
       
   773         case EManuallyRegisterToNetworkAndChooseAccTech:
       
   774             iPhone.CancelAsyncRequest(EMobilePhoneSelectNetworkCancel);  
       
   775             break; 
       
   776         case EGetNetworkInfoOperatorName:
       
   777             iPhone.CancelAsyncRequest(EMobilePhoneGetCurrentNetworkCancel);  
       
   778             break; 
       
   779         case ESetSystemNetworkBand:
       
   780             iCustomApi.CancelAsyncRequest(ECustomSetSystemNetworkModeIPC); 
       
   781             break; 
       
   782         case EListAvailableNetworkOperators:
       
   783             iRetrieveDetectedNetworks->Cancel();  
       
   784             break; 
       
   785         default: 
       
   786             break; 
       
   787         }
       
   788 
       
   789     iCurrentOperation = EIdle; 
       
   790 
       
   791     TRACE_FUNC_EXIT
       
   792     }
       
   793 
       
   794 // ---------------------------------------------------------------------------
       
   795 // Helper method for RunL() 
       
   796 // ---------------------------------------------------------------------------
       
   797 //
       
   798 TInt CATCOPSCmd::InspectModeAndProcessCommand()
       
   799     {
       
   800     TRACE_FUNC_ENTRY
       
   801     TBuf<KMaxOperatorNameLength> buf;
       
   802     TInt err; 
       
   803 
       
   804     switch (iRegistrationMode)
       
   805         {
       
   806         case EModeAutomatic: 
       
   807             AutomaticNetworkRegistration(); 
       
   808             break; 
       
   809         case EModeManual: 
       
   810         case EModeManualAutomatic: // see also RunL() 
       
   811             if(iParamArray.Count() < KMinimumParameterCountWhenOperatorPresent)
       
   812                 {
       
   813                 TRACE_FUNC_EXIT
       
   814                 return KErrArgument; 
       
   815                 }
       
   816             
       
   817             // At least the operator is present, so convert it into S60 format. 
       
   818             buf.Copy(iParamArray[KOperatorParameterIndex]->Des()); 
       
   819             err = ConvertOperatorToMccMnc(iDetectedNetworks, iFormat, buf, iMcc, iMnc); 
       
   820             if(err != KErrNone)
       
   821                 {
       
   822                 TRACE_INFO(_L("CATCOPSCmd::HandleCommand() -- operator conversion failed!"));
       
   823                 TRACE_FUNC_EXIT
       
   824                 return KErrArgument; 
       
   825                 }
       
   826 
       
   827             if (iParamArray.Count() >= KMinimumParameterCountWhenAccTechPresent) 
       
   828                 {
       
   829                 // Also access tech. is present. Convert it to ETel compatible value.  
       
   830                 TAccessTechnology accTech; 
       
   831                 TInt err = GetAccTechFromParameter(iParamArray[KAccessTechnologyParameterIndex]->Des(), accTech); 
       
   832                 if(err != KErrNone)
       
   833                     {
       
   834                     // Parameter problem, return an error. 
       
   835                     TRACE_FUNC_EXIT
       
   836                     return KErrArgument; 
       
   837                     }
       
   838                 // Register both operator and access technology manually.
       
   839                 ManualNetworkRegistration(iMcc, iMnc, accTech); 
       
   840                 }
       
   841             else 
       
   842                 {
       
   843                 // No access technology parameter, so register just the operator. 
       
   844                 ManualNetworkRegistration(iMcc, iMnc); 
       
   845                 }
       
   846             break; 
       
   847         case EModeDeregister: // Deregister from network 
       
   848             // Not supported, return an error. 
       
   849 			TRACE_FUNC_EXIT
       
   850             return KErrArgument; 
       
   851         case EModeSetFormatParameter: 
       
   852             // Storing format parameter was done already, so just reply OK. 
       
   853             CreateReply(ETrue); 
       
   854 			TRACE_FUNC_EXIT
       
   855             return KErrNone; 
       
   856         default: 
       
   857             return KErrArgument; 
       
   858         }
       
   859     TRACE_FUNC_EXIT
       
   860     return KErrNone; 
       
   861     }
       
   862 
       
   863 // ---------------------------------------------------------------------------
       
   864 // Converts the ETel access technology into 3GPP TS 27.007 V8.4.1 compatible format. 
       
   865 // ---------------------------------------------------------------------------
       
   866 //
       
   867 TInt CATCOPSCmd::SolveAccessTechnology(RMobilePhone::TMobilePhoneNetworkAccess &aAccessTech)
       
   868     {
       
   869     TRACE_FUNC_ENTRY
       
   870 
       
   871     TUint caps;
       
   872     if(iPacketService.GetStaticCaps(caps, RPacketContext::EPdpTypePPP) != KErrNone)
       
   873         {
       
   874         TRACE_FUNC_EXIT
       
   875         return KErrGeneral;     
       
   876         }
       
   877 
       
   878     TRACE_INFO(( _L8("CATCOPSCmd::SolveAccessTechnology() static caps gotten (%b)"), caps));
       
   879 
       
   880     switch(aAccessTech)
       
   881         {
       
   882         case RMobilePhone::ENetworkAccessGsm: 
       
   883             if(caps & RPacketService::KCapsEGPRSSupported)
       
   884                 {
       
   885                 iAccTech = EGSMwithEGPRS; 
       
   886                 }
       
   887             else 
       
   888                 {
       
   889                 iAccTech = EGSM; 
       
   890                 }
       
   891             break; 
       
   892         case RMobilePhone::ENetworkAccessGsmCompact: 
       
   893             iAccTech = EGSMCompact; 
       
   894             break; 
       
   895         case RMobilePhone::ENetworkAccessUtran: 
       
   896             if(caps & RPacketService::KCapsHSDPASupported) 
       
   897                 {
       
   898                 if(caps & RPacketService::KCapsHSUPASupported)
       
   899                     {
       
   900                     iAccTech = EUDMAwithHSDPAandHSUPA;  
       
   901                     }
       
   902                 else 
       
   903                     {
       
   904                     iAccTech = EHSDPA;  
       
   905                     }
       
   906                 }
       
   907             else if(caps & RPacketService::KCapsHSUPASupported) 
       
   908                 {
       
   909                 iAccTech = EHSUPA;  
       
   910                 }
       
   911             else 
       
   912                 {
       
   913                 iAccTech = EUDMA;  
       
   914                 }
       
   915             break;
       
   916         default: 
       
   917             TRACE_INFO( _L("CATCOPSCmd::SolveAccessTechnology() unknown access tech!"));
       
   918             iAccTech = EAccTechNotSet; 
       
   919             return KErrArgument; 
       
   920 		}
       
   921     TRACE_FUNC_EXIT
       
   922     return KErrNone;  
       
   923     }
       
   924 
       
   925 // ---------------------------------------------------------------------------
       
   926 // Contructs a response for the read command. 
       
   927 // ---------------------------------------------------------------------------
       
   928 //
       
   929 TInt CATCOPSCmd::ConstructNetworkInfoResponse()
       
   930     {
       
   931     TRACE_FUNC_ENTRY
       
   932     RBuf8 reply;
       
   933     TInt size(KMaxNetworkTestResponseAdditionalSize + KLongOperatorNameFormatLength);       
       
   934     TChar carriageReturn;
       
   935     TChar lineFeed;
       
   936     TInt err;
       
   937     err = reply.Create(size);
       
   938 	err |= iCallback->GetCharacterValue( ECharTypeCR, carriageReturn );
       
   939 	err |= iCallback->GetCharacterValue( ECharTypeLF, lineFeed );		
       
   940 	if(err != KErrNone) 
       
   941 		{
       
   942 		return err; 
       
   943 		}
       
   944 
       
   945 	// Some PC Software expects and extra CR+LF, hence those are added twice: 
       
   946 	reply.Append( carriageReturn ); 
       
   947 	reply.Append( lineFeed );
       
   948     reply.Append( carriageReturn );
       
   949     reply.Append( lineFeed );  
       
   950     reply.Append(_L("+COPS: "));  
       
   951     reply.AppendNum(iRegistrationMode);  
       
   952     reply.Append(_L(","));  
       
   953     switch(iFormat)
       
   954         {
       
   955         case RMmCustomAPI::EOperatorNameNitzFull:   
       
   956             reply.AppendNum(EFormatLong);  
       
   957             reply.Append(_L(",")); 
       
   958             reply.Append(_L("\""));   
       
   959             TRACE_INFO(( _L8("CATCOPSCmd::ConstructNetworkInfoResponse() appending (%S)"), 
       
   960                     &iNetworkInfo.iLongName));
       
   961             reply.Append(iNetworkInfo.iLongName);  
       
   962             break; 
       
   963         case RMmCustomAPI::EOperatorNameNitzShort:
       
   964             reply.AppendNum(EFormatShort); 
       
   965             reply.Append(_L(",")); 
       
   966             reply.Append(_L("\"")); 
       
   967             TRACE_INFO(( _L8("CATCOPSCmd::ConstructNetworkInfoResponse() appending (%S)"), 
       
   968                     &iNetworkInfo.iShortName));
       
   969             reply.Append(iNetworkInfo.iShortName); 
       
   970             break; 
       
   971         case RMmCustomAPI::EOperatorNameMccMnc: 
       
   972             reply.AppendNum(EFormatNumeric); 
       
   973             reply.Append(_L(",")); 
       
   974             reply.Append(_L("\"")); 
       
   975             TRACE_INFO(( _L8("CATCOPSCmd::ConstructNetworkInfoResponse() appending codes (%S) and (%S)"), 
       
   976                             &iNetworkInfo.iCountryCode, &iNetworkInfo.iNetworkId));
       
   977             reply.Append(iNetworkInfo.iCountryCode); 
       
   978             reply.Append(iNetworkInfo.iNetworkId); 
       
   979             break; 
       
   980         }
       
   981     reply.Append(_L("\"")); 
       
   982 
       
   983     if(SolveAccessTechnology(iNetworkInfo.iAccess) == KErrNone && iAccTech != EAccTechNotSet) 
       
   984         {
       
   985         TRACE_INFO((_L("CATCOPSCmd::ConstructNetworkInfoResponse() appending acc. tech. (%d)"), 
       
   986                             iAccTech));
       
   987         reply.Append(_L(",")); 
       
   988         reply.AppendNum(iAccTech); 
       
   989         }
       
   990 
       
   991     reply.Append( carriageReturn );
       
   992     reply.Append( lineFeed );
       
   993 
       
   994     CreateReply(ETrue, reply); 
       
   995 
       
   996     TRACE_FUNC_EXIT
       
   997     return KErrNone;  
       
   998     }
       
   999 
       
  1000 
       
  1001 // ---------------------------------------------------------------------------
       
  1002 // Contructs a response for the test command. 
       
  1003 // ---------------------------------------------------------------------------
       
  1004 //
       
  1005 void CATCOPSCmd::ConstructNetworkListResponseL()
       
  1006     {
       
  1007     TRACE_FUNC_ENTRY
       
  1008     RBuf8 reply;
       
  1009     TChar carriageReturn;
       
  1010     TChar lineFeed;
       
  1011 
       
  1012     TInt maxItemSize(KMaxNetworkReadResponseAdditionalSize  
       
  1013             + KShortOperatorNameFormatLength 
       
  1014             + KLongOperatorNameFormatLength 
       
  1015             + KNumericOperatorNameFormatLength
       
  1016             + KSupportedModesStr().Length()
       
  1017             + KSupportedFormatsStr().Length()); 
       
  1018 
       
  1019     CleanupClosePushL(reply); 
       
  1020 
       
  1021     User::LeaveIfNull(iDetectedNetworks); 
       
  1022     User::LeaveIfError(reply.Create( maxItemSize * iDetectedNetworks->Enumerate())); 
       
  1023     User::LeaveIfError(iCallback->GetCharacterValue( ECharTypeCR, carriageReturn ));
       
  1024     User::LeaveIfError(iCallback->GetCharacterValue( ECharTypeLF, lineFeed ));		
       
  1025 
       
  1026     // Some PC Software expects and extra CR+LF, hence those are added twice: 
       
  1027     reply.Append( carriageReturn );
       
  1028     reply.Append( lineFeed );
       
  1029     reply.Append( carriageReturn );
       
  1030     reply.Append( lineFeed );
       
  1031     reply.Append( _L("+COPS: ") ); 
       
  1032 
       
  1033     RMobilePhone::TMobilePhoneNetworkInfoV2 nwInfo; 
       
  1034     for(TInt i = 0; i < iDetectedNetworks->Enumerate(); ++i)
       
  1035         {
       
  1036 		if(i > 0) // Add CR+LF after the first cycle. 
       
  1037 			{
       
  1038             reply.Append( carriageReturn );
       
  1039             reply.Append( lineFeed );
       
  1040 			}
       
  1041         nwInfo = iDetectedNetworks->GetEntryL(i);  
       
  1042 
       
  1043         reply.Append(_L("(")); 
       
  1044         reply.AppendNum(nwInfo.iStatus); 
       
  1045         reply.Append(_L(",")); 
       
  1046 		reply.Append(_L("\"")); 
       
  1047         reply.Append(nwInfo.iLongName); 
       
  1048 		reply.Append(_L("\"")); 
       
  1049         reply.Append(_L(",")); 
       
  1050 		reply.Append(_L("\"")); 
       
  1051         reply.Append(nwInfo.iShortName); 
       
  1052 		reply.Append(_L("\"")); 
       
  1053         reply.Append(_L(",")); 
       
  1054 		reply.Append(_L("\"")); 
       
  1055         reply.Append(nwInfo.iCountryCode); 
       
  1056         reply.Append(nwInfo.iNetworkId); 
       
  1057 		reply.Append(_L("\"")); 
       
  1058         if(SolveAccessTechnology(nwInfo.iAccess) == KErrNone && iAccTech != EAccTechNotSet) 
       
  1059             {
       
  1060             TRACE_INFO((_L("CATCOPSCmd::ConstructNetworkListResponse() appending acc. tech. (%d)"), iAccTech));
       
  1061             reply.Append(_L(",")); 
       
  1062             reply.AppendNum(iAccTech); 
       
  1063             }
       
  1064         reply.Append(_L(")")); 
       
  1065         reply.Append(_L(",")); 
       
  1066 		TRACE_INFO( _L("CATCOPSCmd::ConstructNetworkListResponse() -- entry added to reply."));
       
  1067         }
       
  1068     reply.Append(KSupportedModesStr); // Supported modes as defined in 3GPP TS 27.007 V8.4.1
       
  1069     reply.Append(KSupportedFormatsStr);  // Supported formats as defined in 3GPP TS 27.007 V8.4.1
       
  1070 
       
  1071     reply.Append( carriageReturn );
       
  1072     reply.Append( lineFeed );
       
  1073 
       
  1074 		// Finally append the "OK". CreateOkOrErrorReply returns verbose or numeric version. 
       
  1075     RBuf8 okReply;
       
  1076     CleanupClosePushL(okReply); 
       
  1077     iCallback->CreateOkOrErrorReply( okReply, ETrue );
       
  1078     reply.Append( okReply);
       
  1079     CreateReply(ETrue, reply); 
       
  1080     CleanupStack::PopAndDestroy(&okReply);   
       
  1081     CleanupStack::PopAndDestroy(&reply);   
       
  1082     TRACE_FUNC_EXIT
       
  1083     }
       
  1084 
       
  1085 // ---------------------------------------------------------------------------
       
  1086 // Finalises the response and sends it. 
       
  1087 // ---------------------------------------------------------------------------
       
  1088 //
       
  1089 void CATCOPSCmd::CreateReply(TBool aIsOK, const TDesC8 &aReply) 
       
  1090     {
       
  1091     if(aIsOK == EFalse)
       
  1092         {
       
  1093         iCallback->CreateReplyAndComplete( EReplyTypeError);
       
  1094         }
       
  1095     else 
       
  1096         {
       
  1097         if(aReply.Length() > 0)
       
  1098             {
       
  1099             iCallback->CreateReplyAndComplete( EReplyTypeOther,
       
  1100                                            aReply );
       
  1101             }
       
  1102         else 
       
  1103             {
       
  1104             iCallback->CreateReplyAndComplete( EReplyTypeOk);
       
  1105             }
       
  1106         }
       
  1107     iCurrentOperation = EIdle; 
       
  1108     TRACE_FUNC_EXIT
       
  1109     }