networkprotocolmodules/suplprotocolmodule/SuplProtocol/src/suplnetworkinfohandler.cpp
changeset 0 9cfd9a3ee49c
equal deleted inserted replaced
-1:000000000000 0:9cfd9a3ee49c
       
     1 // Copyright (c) 2008-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 // Object to monitor the ETel networki information needed by SUPL
       
    15 // protocol module
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file
       
    21  @internalTechnology
       
    22  @deprecated
       
    23 */
       
    24 
       
    25 #include <e32debug.h>
       
    26 
       
    27 #include "suplnetworkinfohandler.h"
       
    28 #include <e32base.h>
       
    29 #include <e32property.h>
       
    30 #include <etelmm.h>
       
    31 #include <rsshared.h>
       
    32 #include "supldevloggermacros.h"
       
    33 
       
    34 using namespace CommsDat;
       
    35 
       
    36 const TUint KMaxCellIdOrLac = 65535;
       
    37 const TUint KMaxMccOrMnc = 999;
       
    38 
       
    39 
       
    40 /**
       
    41 */
       
    42 CSuplNetworkInfoHandler::CSuplNetworkInfoHandler(MSuplNetworkInfoObserver& aObserver) :
       
    43 	CActive(EPriorityStandard),
       
    44 	iObserver(aObserver),
       
    45 	iState(EStateNull),
       
    46 	iNetworkInfoPckg(iNetworkInfo),
       
    47 	iOnStoreInfoPckg(iOnStoreInfo),
       
    48 	iOnStoreEntryPckg(iOnStoreEntry)	
       
    49 	{
       
    50 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::CSuplNetworkInfoHandler() Begin\n");
       
    51 	CActiveScheduler::Add(this);
       
    52 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::CSuplNetworkInfoHandler() End\n");
       
    53 	}
       
    54 
       
    55 /**
       
    56 */	
       
    57 CSuplNetworkInfoHandler::~CSuplNetworkInfoHandler()
       
    58 	{
       
    59 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::~CSuplNetworkInfoHandler() Begin\n");
       
    60 	Cancel();
       
    61 	
       
    62 	if (iTimingAdvSupport)
       
    63 		{
       
    64 		delete iCellInfoHandler;
       
    65 		iCellPhone.Close();
       
    66 		}
       
    67 	
       
    68 	iOnStore.Close();
       
    69 	
       
    70 	iNetPhone.Close();
       
    71 	iTelServer.Close();
       
    72 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::~CSuplNetworkInfoHandler() End\n");
       
    73 	}
       
    74 
       
    75 /**
       
    76 */	
       
    77 CSuplNetworkInfoHandler* CSuplNetworkInfoHandler::NewL(MSuplNetworkInfoObserver& aObserver)
       
    78 	{
       
    79 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::NewL() Begin\n");
       
    80 	CSuplNetworkInfoHandler* self = new (ELeave) CSuplNetworkInfoHandler(aObserver);
       
    81 	CleanupStack::PushL(self);
       
    82 	self->ConstructL();
       
    83 	CleanupStack::Pop(self);
       
    84 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::NewL() End\n");
       
    85 	return self;
       
    86 	}
       
    87 
       
    88 /**
       
    89 */
       
    90 void CSuplNetworkInfoHandler::ConstructL()
       
    91 	{
       
    92 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::ConstructL() Begin\n");
       
    93 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::ConstructL() End\n");
       
    94 	}
       
    95 
       
    96 /**
       
    97 */
       
    98 void CSuplNetworkInfoHandler::StartGettingNetworkInfoL()
       
    99 {
       
   100 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::StartGettingNetworkInfo() Begin\n");
       
   101 
       
   102 	//Attempt to connect to the ETel Server.  This will start C32Start if
       
   103 	//it has not already been started by the startup routine.
       
   104 	User::LeaveIfError(iTelServer.Connect());
       
   105 		
       
   106 	// Check if the Comms Process RootServer has started
       
   107 	iConfigurationProperty.Attach(KUidSystemCategory, RootServer::KUidC32StartPropertyKey.iUid);
       
   108 	TInt propertyValue = RootServer::EInitialising;
       
   109 	TInt propertyResult = iConfigurationProperty.Get(propertyValue);
       
   110 		
       
   111 	if(propertyValue < RootServer::EConfigurationComplete)
       
   112 		{
       
   113 		iState = EStateInitializing;
       
   114 		iConfigurationProperty.Subscribe(iStatus);
       
   115 		SetActive();
       
   116 		}
       
   117 	else
       
   118 		{
       
   119 		// Attempt to get network information
       
   120 		GetNetworkInfoL();
       
   121 		}
       
   122 
       
   123 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::StartGettingNetworkInfo() End\n");
       
   124 }
       
   125 
       
   126 /** 
       
   127 */
       
   128 void CSuplNetworkInfoHandler::GetNetworkInfoL()
       
   129 	{
       
   130 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetNetworkInfoL() Begin\n");
       
   131 	InitialisePhonesL();
       
   132 	
       
   133 	// Connected to ETel successfully
       
   134 	if (iTimingAdvSupport)
       
   135 		{
       
   136 		// Instantiate the active object that monitors changes to 
       
   137 		// Timing Advance passing to it the initialized RMobilePhone
       
   138 		// and the observer interested in Timing Advance.
       
   139 		iCellInfoHandler = CSuplCellInfoHandler::NewL(iObserver,iCellPhone);
       
   140 		iCellInfoHandler->StartGettingCellInfo();
       
   141 		}
       
   142 
       
   143 	// Get the network info
       
   144 	iState = EStateGettingNetInfo;
       
   145 	iNetPhone.GetCurrentNetwork(iStatus, iNetworkInfoPckg, iLocArea);
       
   146 	SetActive();
       
   147 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetNetworkInfoL() End\n");
       
   148 	}
       
   149 
       
   150 /**
       
   151 */
       
   152 void CSuplNetworkInfoHandler::RunL()
       
   153 	{
       
   154 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::RunL() Begin\n");
       
   155 	User::LeaveIfError(iStatus.Int());
       
   156 	
       
   157 	switch (iState)
       
   158 		{
       
   159 		case EStateInitializing:
       
   160 			{
       
   161 			TInt propertyValue = RootServer::EInitialising; // set to safe state
       
   162 			TInt propertyResult = iConfigurationProperty.Get(propertyValue);
       
   163 			
       
   164 			if(propertyValue != RootServer::EConfigurationComplete)
       
   165 				{
       
   166 				iConfigurationProperty.Subscribe(iStatus);
       
   167 				SetActive();
       
   168 				}
       
   169 			else
       
   170 				{
       
   171 				iConfigurationProperty.Cancel();
       
   172 				GetNetworkInfoL();
       
   173 				}
       
   174 			break;
       
   175 			}
       
   176 
       
   177 		case EStateGettingNetInfo:
       
   178 			{
       
   179 			if(ValidateNetInfo())
       
   180 				{
       
   181 				iObserver.NetInfoResults(iNetworkInfo, iLocArea);
       
   182 				}
       
   183 			if(iHomeNetworkInfoSupport)
       
   184 				{
       
   185 				GetMccMnc();
       
   186 				}
       
   187 			else if(iMsisdnSupport)
       
   188 				{
       
   189 				GetMsisdnStoreInfo();
       
   190 				}
       
   191 			else
       
   192 				{
       
   193 				MonitorNetworkChange();
       
   194 				}
       
   195 			break;	
       
   196 			}
       
   197 		
       
   198 		case EStateGettingMccMnc:
       
   199 			{
       
   200 			if(iStatus==KErrNone && ValidateNetInfo())
       
   201 				{
       
   202 				//All checks are done in ValidateNetInfo
       
   203 				TUint mcc = 0;
       
   204 				TLex lex(iNetworkInfo.iCountryCode);
       
   205 				lex.Val(mcc);
       
   206 				TUint mnc = 0;
       
   207 				lex.Assign(iNetworkInfo.iNetworkId);
       
   208 				lex.Val(mnc);
       
   209 				iObserver.HomeMccMncResult(mcc, mnc);
       
   210 				}
       
   211 			if(iMsisdnSupport)
       
   212 				{
       
   213 				GetMsisdnStoreInfo();
       
   214 				}
       
   215 			else
       
   216 				{
       
   217 				MonitorNetworkChange();
       
   218 				}
       
   219 			break;
       
   220 			}
       
   221 			
       
   222 		case EStateGettingMsisdnStoreInfo:
       
   223 			{
       
   224 			if(iStatus==KErrNone && iOnStoreInfo.iUsedEntries>0 && 
       
   225 					(iOnStoreInfo.iCaps & RMobilePhoneStore::KCapsIndividualEntry))
       
   226 				{
       
   227 				//Currently we simply use the first record to get the MSISDN 
       
   228 				iOnStoreEntry.iIndex = 1;
       
   229 				GetMsisdnStoreEntry();
       
   230 				}
       
   231 			else
       
   232 				{
       
   233 				iMsisdnSupport = EFalse;
       
   234 				MonitorNetworkChange();
       
   235 				}
       
   236 			break;
       
   237 			}
       
   238 		
       
   239 		case EStateGettingMsisdnStoreEntry:
       
   240 			{
       
   241 			if(iStatus==KErrNone)
       
   242 				{
       
   243 				iObserver.MsisdnResult(iOnStoreEntry.iNumber.iTelNumber);
       
   244 				}
       
   245 			else
       
   246 				{
       
   247 				iMsisdnSupport = EFalse;
       
   248 				}
       
   249 			MonitorNetworkChange();	
       
   250 			break;
       
   251 			}
       
   252 			
       
   253 		case EStateNetInfoChangeMon:
       
   254 			{
       
   255 			if(ValidateNetInfo())
       
   256 				{
       
   257 				iObserver.NetInfoResults(iNetworkInfo, iLocArea);
       
   258 				}
       
   259 			MonitorNetworkChange(); // Keep monitoring
       
   260 			break;				
       
   261 			}
       
   262 		
       
   263 		default:
       
   264 			break;		
       
   265 		}
       
   266 	
       
   267 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::RunL() End\n");
       
   268 	}
       
   269 
       
   270 /**
       
   271 */	
       
   272 void CSuplNetworkInfoHandler::DoCancel()
       
   273 	{
       
   274 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::DoCancel() Begin\n");
       
   275 	//Check to see what stage we in are to find out what to cancel
       
   276 	switch (iState)
       
   277 		{
       
   278 		case EStateInitializing:
       
   279 			{
       
   280 			iConfigurationProperty.Cancel();
       
   281 			break;				
       
   282 			} 
       
   283 		case EStateGettingNetInfo:
       
   284 			{
       
   285 			iNetPhone.CancelAsyncRequest(EMobilePhoneGetCurrentNetwork);
       
   286 			break;
       
   287 			}
       
   288 		case EStateGettingMccMnc:
       
   289 			{
       
   290 			iNetPhone.CancelAsyncRequest(EMobilePhoneGetHomeNetwork);
       
   291 			break;
       
   292 			}
       
   293 		case EStateNetInfoChangeMon:
       
   294 			{
       
   295 			iNetPhone.CancelAsyncRequest(EMobilePhoneNotifyCurrentNetworkChange);
       
   296 			break;
       
   297 			}
       
   298 			
       
   299 		default:
       
   300 			break;
       
   301 		}
       
   302 	
       
   303 	if(iCellInfoHandler)
       
   304 		{
       
   305 		iCellInfoHandler->Cancel();
       
   306 		}
       
   307 	
       
   308 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::DoCancel() End\n");
       
   309 	}
       
   310 
       
   311 /**
       
   312 */	
       
   313 TInt CSuplNetworkInfoHandler::RunError(TInt /*aError*/)
       
   314 	{
       
   315 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::DoCancel() Begin\n");
       
   316 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::DoCancel() End\n");
       
   317 	return KErrNone;
       
   318 	}
       
   319 
       
   320 /** Asynchronous request to obtain MCC and MNC
       
   321 */
       
   322 void CSuplNetworkInfoHandler::GetMccMnc()
       
   323 	{
       
   324 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetMccMnc() Begin\n");
       
   325 	iState = EStateGettingMccMnc;
       
   326 	iNetPhone.GetHomeNetwork(iStatus, iNetworkInfoPckg);
       
   327 	SetActive();
       
   328 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetMccMnc() End\n");
       
   329 	}
       
   330 
       
   331 /** Asynchronous request to obtain Msisdn - getting store info.
       
   332 */
       
   333 void CSuplNetworkInfoHandler::GetMsisdnStoreInfo()
       
   334 	{
       
   335 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetMsisdnStoreInfo() Begin\n");
       
   336 	iState = EStateGettingMsisdnStoreInfo;
       
   337 	iOnStore.GetInfo(iStatus, iOnStoreInfoPckg);
       
   338 	SetActive();
       
   339 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetMsisdnStoreInfo() End\n");
       
   340 	}
       
   341 
       
   342 /** Asynchronous request to obtain Msisdn - getting store entry.
       
   343 */
       
   344 void CSuplNetworkInfoHandler::GetMsisdnStoreEntry()
       
   345 	{
       
   346 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetMsisdnStoreEntry() Begin\n");
       
   347 	iState = EStateGettingMsisdnStoreEntry;
       
   348 	//please note that the index is set in RunL for iOnStoreEntryPckg
       
   349 	iOnStore.Read(iStatus, iOnStoreEntryPckg);
       
   350 	SetActive();
       
   351 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetMsisdnStoreEntry() End\n");
       
   352 	}
       
   353 
       
   354 
       
   355 /** Asychronous request to obtain notifications
       
   356 of change in the current network data
       
   357 */
       
   358 void CSuplNetworkInfoHandler::MonitorNetworkChange()
       
   359 	{
       
   360 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::MonitorNetworkChange() Begin\n");
       
   361 	iState = EStateNetInfoChangeMon;
       
   362 	iNetPhone.NotifyCurrentNetworkChange(iStatus, iNetworkInfoPckg, iLocArea);
       
   363 	SetActive();
       
   364 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::MonitorNetworkChange() End\n");
       
   365 	}
       
   366 
       
   367 /** Retrieves the name of the .tsy to use from CommDB/CommsDat
       
   368 
       
   369 Hard-coded to use the .tsy file specified in the ModemBearerEntry
       
   370 which is specified (by index) by the KCDTIdModemPhoneServicesSMS
       
   371 setting in the global settings table.
       
   372 */
       
   373 void CSuplNetworkInfoHandler::GetCommDbTSYnameL(TDes& aTsyName)
       
   374 	{
       
   375 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetCommDbTSYnameL() Begin\n");
       
   376 	CMDBSession* db = CMDBSession::NewLC(KCDLatestVersion);
       
   377 
       
   378 	CMDBField<TUint32>* globalSettingField = new(ELeave) CMDBField<TUint32>(KCDTIdModemPhoneServicesSMS);
       
   379 	CleanupStack::PushL(globalSettingField);
       
   380 
       
   381 	globalSettingField->SetRecordId(1);
       
   382 	globalSettingField->LoadL(*db);
       
   383 	TUint32 modemId = *globalSettingField;
       
   384 
       
   385 	CMDBField<TDesC>* tsyField = new(ELeave) CMDBField<TDesC>(KCDTIdTsyName);
       
   386 	CleanupStack::PushL(tsyField);
       
   387 
       
   388 	tsyField->SetRecordId(modemId);
       
   389 	tsyField->LoadL(*db);
       
   390 
       
   391 	aTsyName = *tsyField;
       
   392 	CleanupStack::PopAndDestroy(3, db); // db, tsyField & globalSettingField
       
   393 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetCommDbTSYnameL() End\n");
       
   394 	}
       
   395 
       
   396 /** Finds and opens the phones to be used to monitor current network
       
   397 info and cell info (timing advance).
       
   398 
       
   399 This method also checks if the TSY can provide the different
       
   400 bits of information needed by SUPL from ETEL: current and home network
       
   401 information, cell ID information (for Timing Advance).
       
   402 	
       
   403 @leave	Leaves if underlying ETEL.DLL returns error,
       
   404 or if we can't find a suitable Phone or can't open it.
       
   405 */
       
   406 void CSuplNetworkInfoHandler::InitialisePhonesL()
       
   407 	{
       
   408 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::InitialisePhonesL() Begin\n");
       
   409 	TInt err(KErrNone);
       
   410 		
       
   411 	// Read the name of the .tsy to load from CommDB
       
   412 	TBuf<KCommsDbSvrMaxFieldLength> tsyName;
       
   413 	GetCommDbTSYnameL(tsyName);
       
   414 
       
   415 	// Load .tsy into ETel
       
   416 	User::LeaveIfError(iTelServer.LoadPhoneModule(tsyName));
       
   417 
       
   418 	// Find available phones; check that the one we requested 
       
   419 	// to be loaded is there.
       
   420 	TInt phoneIndex(0);
       
   421 	User::LeaveIfError(iTelServer.EnumeratePhones(phoneIndex));
       
   422 	while(phoneIndex-->0)
       
   423 		{
       
   424 		TName searchTsyName;
       
   425 		// Check whether this phone belongs to loaded TSY
       
   426 		if ((iTelServer.GetTsyName(phoneIndex, searchTsyName) == KErrNone) 
       
   427 			&& (searchTsyName.CompareF(tsyName) == KErrNone)) 
       
   428 			break;
       
   429 		}
       
   430 		
       
   431 	// Open a phone to be used for monitoring the network.
       
   432 	RTelServer::TPhoneInfo phoneInfo;
       
   433 	User::LeaveIfError(iTelServer.GetPhoneInfo(phoneIndex, phoneInfo));	
       
   434 	User::LeaveIfError(iNetPhone.Open(iTelServer, phoneInfo.iName));
       
   435 	
       
   436 	// Check that the phone is ready to be used.	
       
   437 	RPhone::TStatus status;
       
   438 	User::LeaveIfError(iNetPhone.GetStatus(status));
       
   439 	if(status.iModemDetected != RPhone::EDetectedPresent)
       
   440 		{		
       
   441 		err = iNetPhone.Initialise();
       
   442 		if(err != KErrNone)
       
   443 			{
       
   444 			iNetPhone.Close();
       
   445 			User::Leave(err);
       
   446 			}
       
   447 		}	
       
   448 
       
   449 	// Check that network info can be accessed
       
   450 	TUint32 networkCaps;
       
   451 	User::LeaveIfError(iNetPhone.GetNetworkCaps(networkCaps));
       
   452 	if (!(networkCaps & RMobilePhone::KCapsGetCurrentNetwork
       
   453 		  && networkCaps & RMobilePhone::KCapsNotifyCurrentNetwork))
       
   454 		{
       
   455 		// No point in continuing
       
   456 		err = KErrNotSupported;
       
   457 		}
       
   458 	else
       
   459 		{
       
   460 		if(networkCaps & RMobilePhone::KCapsGetHomeNetwork)
       
   461 			{
       
   462 			iHomeNetworkInfoSupport = ETrue;
       
   463 			}
       
   464 		
       
   465 		// Network info can be accessed.
       
   466 
       
   467 		// Check if Timing Advance is supported by the TSY
       
   468 		// (If it isn't, that is NOT a critical error, so donnot
       
   469 		// change the returned error code)
       
   470 		iTimingAdvSupport = EFalse;
       
   471 		iTelServer.IsSupportedByModule(tsyName, KEtelFuncCellInfo, iTimingAdvSupport);
       
   472 		if (iTimingAdvSupport)
       
   473 			{
       
   474 			// Open a new phone for Get/NotifyCellInfo() requests			
       
   475 			if (KErrNone ==	iCellPhone.Open(iTelServer, phoneInfo.iName))
       
   476 				{
       
   477 				// Check that iCellPhone is ready to be used	
       
   478 				if(KErrNone == iCellPhone.GetStatus(status))
       
   479 					{
       
   480 					if(status.iModemDetected != RPhone::EDetectedPresent)
       
   481 						{
       
   482 						if(KErrNone != iCellPhone.Initialise())
       
   483 							{
       
   484 							// Unable to initialise phone
       
   485 							iCellPhone.Close();
       
   486 							iTimingAdvSupport = EFalse;
       
   487 							}
       
   488 						}
       
   489 					}
       
   490 				else
       
   491 					{
       
   492 					// Unable to get phone status
       
   493 					iCellPhone.Close();
       
   494 					iTimingAdvSupport = EFalse;					
       
   495 					}
       
   496 				}
       
   497 			else
       
   498 				{
       
   499 				// Unable to open phone
       
   500 				iTimingAdvSupport = EFalse;	
       
   501 				}
       
   502 			}
       
   503 		}
       
   504 	User::LeaveIfError(err);
       
   505 	
       
   506 	iMsisdnSupport = EFalse;
       
   507 	if(iTelServer.IsSupportedByModule(tsyName, KETelFuncMobileOwnNumberStore, iMsisdnSupport)==KErrNone && 
       
   508 			iMsisdnSupport)
       
   509 		{
       
   510 		if(iOnStore.Open(iNetPhone)!=KErrNone)
       
   511 			{
       
   512 			iMsisdnSupport=EFalse;
       
   513 			}
       
   514 		}
       
   515 	
       
   516 	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::InitialisePhonesL() End\n");
       
   517 	}
       
   518 
       
   519 /**
       
   520 Checks and fixes if necessary the network info
       
   521 */
       
   522 TBool CSuplNetworkInfoHandler::ValidateNetInfo()
       
   523 	{
       
   524 	TUint val = 0;
       
   525 	TLex lex(iNetworkInfo.iCountryCode);
       
   526 	TInt err = lex.Val(val);
       
   527 	if(err!=KErrNone || val > KMaxMccOrMnc)
       
   528 		{
       
   529 		return EFalse;
       
   530 		}
       
   531 	lex.Assign(iNetworkInfo.iNetworkId);
       
   532 	err=lex.Val(val);
       
   533 	if(err!=KErrNone || val > KMaxMccOrMnc)
       
   534 		{
       
   535 		return EFalse;
       
   536 		}
       
   537 			
       
   538 	if(iLocArea.iAreaKnown && (iLocArea.iLocationAreaCode > KMaxCellIdOrLac || 
       
   539 			iLocArea.iCellId > KMaxCellIdOrLac))
       
   540 		{
       
   541 		return EFalse;
       
   542 		}
       
   543 	return ETrue;
       
   544 	}