usbmgmt/usbmgrtest/t_charging_emu/src/tbatterycharging.cpp
changeset 0 c9bc50fca66e
child 15 f92a4f87e424
equal deleted inserted replaced
-1:000000000000 0:c9bc50fca66e
       
     1 /*
       
     2 * Copyright (c) 2007-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:
       
    15 *
       
    16 */
       
    17 
       
    18 #include "tbatterycharging.h"
       
    19 #include "musbdevicenotify.h"
       
    20 
       
    21 #include <e32svr.h>
       
    22 #include <e32base.h>
       
    23 #include <e32std.h>
       
    24 #include <usbman.rsg>
       
    25 #include <f32file.h>
       
    26 #include <barsc.h>
       
    27 #include <barsread.h>
       
    28 #include <bautils.h>
       
    29 #include "UsbUtils.h"
       
    30 
       
    31 
       
    32 #include"tbatterychargingdefinitions.h"
       
    33 
       
    34 
       
    35 LOCAL_C void ConsoleMainL();
       
    36 
       
    37 GLDEF_C TInt E32Main()
       
    38 	{
       
    39 	__UHEAP_MARK;
       
    40 	CTrapCleanup* cleanup=CTrapCleanup::New(); // get clean-up stack
       
    41 	
       
    42 	TRAPD(error, ConsoleMainL() );
       
    43 	
       
    44 	__ASSERT_ALWAYS(!error,User::Panic(_L("UsbChargingTest"), error));
       
    45 	delete cleanup; // destroy clean-up stack
       
    46 	__UHEAP_MARKEND;
       
    47 	return KErrNone;
       
    48 	}
       
    49 
       
    50 void ConsoleMainL()
       
    51 	{
       
    52     CActiveScheduler* myScheduler = new(ELeave) CActiveScheduler;
       
    53     CleanupStack::PushL(myScheduler);
       
    54     CActiveScheduler::Install(myScheduler);	
       
    55     
       
    56 	CDummyUsbDevice* device = CDummyUsbDevice::NewL();
       
    57 	CleanupStack::PushL(device);
       
    58 	device->DoTestsL();
       
    59 	CActiveScheduler::Start();
       
    60 
       
    61 	CleanupStack::PopAndDestroy(2, myScheduler);
       
    62 	}
       
    63 
       
    64 CDummyUsbDevice* CDummyUsbDevice::NewL()
       
    65 /**
       
    66  * Constructs a CDummyUsbDevice object.
       
    67  *
       
    68  * @return	A new CDummyUsbDevice object
       
    69  */
       
    70 	{
       
    71 	CDummyUsbDevice* r = new (ELeave) CDummyUsbDevice();
       
    72 	CleanupStack::PushL(r);
       
    73 	r->ConstructL();
       
    74 	CleanupStack::Pop();
       
    75 	return r;
       
    76 	}
       
    77 
       
    78 CDummyUsbDevice::~CDummyUsbDevice()
       
    79 /**
       
    80  * Destructor.
       
    81  */
       
    82 	{
       
    83 	// Cancel any outstanding asynchronous operation.
       
    84 	Cancel();
       
    85 	iTimer.Close();
       
    86 	//delete iRepository;
       
    87 	iExtensionPlugins.ResetAndDestroy();
       
    88 
       
    89 	if(iEcom)
       
    90 		iEcom->Close();
       
    91 	REComSession::FinalClose();
       
    92 
       
    93 	// Free any memory allocated to the list of observers. Note that
       
    94 	// we don't want to call ResetAndDestroy, because we don't own
       
    95 	// the observers themselves.
       
    96 	iObservers.Reset();
       
    97 	delete iText;
       
    98 	iTest.Close();
       
    99 	
       
   100 	iProperty.Close();
       
   101 	iPropertyWriteToRepositoryAck.Close();
       
   102 	iPropertyReadChargingCurrentAck.Close();
       
   103 
       
   104 	}
       
   105 
       
   106 CDummyUsbDevice::CDummyUsbDevice()
       
   107 	: CActive(EPriorityStandard), iTest(_L("Usb Charging Plugin Test")), iPtr(0,200), iLine(0,200)
       
   108 /**
       
   109  * Constructor.
       
   110  */
       
   111 	{
       
   112 	CActiveScheduler::Add(this);
       
   113 	}
       
   114 
       
   115 void CDummyUsbDevice::ConstructL()
       
   116 /**
       
   117  * Performs 2nd phase construction of the USB device.
       
   118  */
       
   119 	{
       
   120 	iEcom = &(REComSession::OpenL());
       
   121 
       
   122 	InstantiateExtensionPluginsL();
       
   123 
       
   124 	if (iExtensionPlugins.Count() != 1)
       
   125 		{
       
   126 		User::Panic(KUsbChargingTestPanic, EUsbChargingTestPanicIncorrectPlugin);
       
   127 		}
       
   128 
       
   129 	iPlugin = iExtensionPlugins[0];
       
   130 
       
   131 	iDummyLdd.Initialise();
       
   132 	//iRepository = CRepository::NewL(KUsbBatteryChargingCentralRepositoryUid);
       
   133 	User::LeaveIfError(iTimer.CreateLocal());
       
   134 	
       
   135 	DefinePropertyL(KBattChargWriteRepositoryUid, KBattChargWriteRepositoryKey,RProperty::EInt);
       
   136 	DefinePropertyL(KBattChargReadPropertyCurrentUid,KBattChargReadCurrentChargingKey,RProperty::EInt);
       
   137 	
       
   138 	User::LeaveIfError(iPropertyWriteToRepositoryAck.Attach(TUid::Uid(KBattChargWriteRepositoryUid), KBattChargWriteRepositoryAckKey));
       
   139 	User::LeaveIfError(iPropertyReadChargingCurrentAck.Attach(TUid::Uid(KBattChargReadPropertyCurrentUid), KBattChargReadCurrentChargingAckKey));
       
   140 	
       
   141 	User::LeaveIfError(StartPropertyBatteryCharging());
       
   142 
       
   143 	}
       
   144 	
       
   145 void CDummyUsbDevice::DefinePropertyL(const TInt32 aCategory, TUint aKey,RProperty::TType eType)
       
   146 	{
       
   147 	
       
   148 	_LIT_SECURITY_POLICY_PASS(KAlwaysPass);
       
   149 
       
   150 	TInt err = iProperty.Define(TUid::Uid(aCategory),
       
   151 									aKey,
       
   152 									eType,
       
   153 									KAlwaysPass,
       
   154 									KAlwaysPass
       
   155 									);
       
   156 	if ( err != KErrAlreadyExists )
       
   157 		{
       
   158 		User::LeaveIfError(err);
       
   159 		}
       
   160 	}
       
   161 
       
   162 
       
   163 	
       
   164 void CDummyUsbDevice::InstantiateExtensionPluginsL()
       
   165 	{
       
   166 	const TUid KUidExtensionPluginInterface = TUid::Uid(KUsbmanExtensionPluginInterfaceUid);
       
   167 	RImplInfoPtrArray implementations;
       
   168 	const TEComResolverParams noResolverParams;
       
   169 	REComSession::ListImplementationsL(KUidExtensionPluginInterface, noResolverParams, KRomOnlyResolverUid, implementations);
       
   170 	CleanupResetAndDestroyPushL(implementations);
       
   171 
       
   172 	for (TInt i=0; i<implementations.Count(); i++)
       
   173 		{
       
   174 		const TUid KTestPluginUid = {0x1020DEA8};
       
   175 		if (implementations[i]->ImplementationUid() == KTestPluginUid)
       
   176 			{
       
   177 			CUsbmanExtensionPlugin* plugin = CUsbmanExtensionPlugin::NewL(implementations[i]->ImplementationUid(), *this);
       
   178 			CleanupStack::PushL(plugin);
       
   179 			// there will most likely be two plugins - the standard one, and the test one (which
       
   180 			// is an extension of the standard one, to include the interface 
       
   181 			// MUsbBatteryChargingTestPluginInterface2. So check, and only keep the test one:
       
   182 			MUsbBatteryChargingTestPluginInterface2* pluginIf
       
   183 				= reinterpret_cast<MUsbBatteryChargingTestPluginInterface2*>(
       
   184 					plugin->GetInterface(KUidUsbBatteryChargingTestPluginInterface2));
       
   185 			
       
   186 			if (pluginIf)
       
   187 				{
       
   188 				iExtensionPlugins.AppendL(plugin); // transfer ownership to iExtensionPlugins
       
   189 				CleanupStack::Pop(plugin);
       
   190 				}
       
   191 			else
       
   192 				{ // destroy it - it's the standard plugin.
       
   193 				CleanupStack::PopAndDestroy(plugin);
       
   194 				iObservers.Remove(iObservers.Count() - 1);
       
   195 				}
       
   196 			}
       
   197 		}
       
   198 	CleanupStack::PopAndDestroy(&implementations);
       
   199 	}
       
   200 
       
   201 void CDummyUsbDevice::RegisterObserverL(MUsbDeviceNotify& aObserver)
       
   202 /**
       
   203  * Register an observer of the device.
       
   204  * Presently, the device supports watching state.
       
   205  *
       
   206  * @param	aObserver	New Observer of the device
       
   207  */
       
   208 	{
       
   209 	User::LeaveIfError(iObservers.Append(&aObserver));
       
   210 	}
       
   211 
       
   212 
       
   213 void CDummyUsbDevice::DeRegisterObserver(MUsbDeviceNotify& aObserver)
       
   214 /**
       
   215  * De-registers an existing device observer.
       
   216  *
       
   217  * @param	aObserver	The existing device observer to be de-registered
       
   218  */
       
   219 	{
       
   220 	TInt index = iObservers.Find(&aObserver);
       
   221 
       
   222 	if (index >= 0)
       
   223 		iObservers.Remove(index);
       
   224 	}
       
   225 
       
   226 void CDummyUsbDevice::RunL()
       
   227 	{
       
   228 	DoCheck();
       
   229 	if (GetNextLine() < 0)
       
   230 		{
       
   231 		iTest.End();
       
   232 		iTest.Getch();
       
   233 		CActiveScheduler::Stop();
       
   234 		}
       
   235 	else
       
   236 		{
       
   237 		iLineNumber++;
       
   238 		iTest.Next(_L(""));
       
   239 		InterpretLine();
       
   240 		DoCommand();
       
   241 		DoAsyncOp();	
       
   242 		}
       
   243 	}
       
   244 
       
   245 void CDummyUsbDevice::DoCancel()
       
   246 	{
       
   247 	iTimer.Cancel();
       
   248 	}
       
   249 
       
   250 TInt CDummyUsbDevice::RunError(TInt /*aError*/)
       
   251 	{
       
   252 
       
   253 	return KErrNone;
       
   254 	}
       
   255 
       
   256 RDevUsbcClient& CDummyUsbDevice::MuepoDoDevUsbcClient()
       
   257 /**
       
   258  * Inherited from MUsbmanExtensionPluginObserver - Function used by plugins to
       
   259  * retrieve our handle to the LDD
       
   260  *
       
   261  * @return The LDD handle
       
   262  */
       
   263 	{
       
   264 	return iDummyLdd;
       
   265 	}
       
   266 
       
   267 void CDummyUsbDevice::MuepoDoRegisterStateObserverL(MUsbDeviceNotify& aObserver)
       
   268 /**
       
   269  * Inherited from MUsbmanExtensionPluginObserver - Function used by plugins to
       
   270  * register themselves for notifications of device/service state changes.
       
   271  *
       
   272  * @param aObserver New Observer of the device
       
   273  */
       
   274 	{
       
   275 	RegisterObserverL(aObserver);
       
   276 	}
       
   277 
       
   278 void CDummyUsbDevice::UpdatePluginInfo()
       
   279 	{
       
   280 	// we can assume our plugin does support this interface....
       
   281 	reinterpret_cast<MUsbBatteryChargingTestPluginInterface2*>(iPlugin->GetInterface(KUidUsbBatteryChargingTestPluginInterface2))->GetPluginInfo(iInfo);
       
   282 	}
       
   283 
       
   284 void CDummyUsbDevice::DoTestsL()
       
   285 	{
       
   286 	iTest.SetLogged(ETrue);
       
   287 	iTest.Title();
       
   288 	OpenFileL();
       
   289 	TInt length = GetNextLine();
       
   290 	if (length <= 0)
       
   291 		{
       
   292 		User::Panic(KUsbChargingTestPanic, EUsbChargingTestPanicBadInputData);
       
   293 		}
       
   294 	iLineNumber = 1;
       
   295 	iTest.Start(_L("test"));
       
   296 	InterpretLine();
       
   297 	DoCommand();
       
   298 	DoAsyncOp();
       
   299 	}
       
   300 
       
   301 void CDummyUsbDevice::InterpretLine()
       
   302 	{
       
   303 	TLex8 lex(iLine);
       
   304 	lex.SkipCharacters();
       
   305 	iCommand = GetCommand(iLine.Left(lex.Offset()));
       
   306 	lex.SkipSpace();
       
   307 	lex.Val(iCommandValue);
       
   308 	lex.SkipSpace();
       
   309 	TInt pos = lex.Offset();
       
   310 	lex.SkipCharacters();
       
   311 	iAsyncOp = GetAsyncOp(iLine.Mid(pos,lex.Offset()-pos));
       
   312 	lex.SkipSpace();
       
   313 	lex.Val(iAsyncOpValue);
       
   314 	lex.SkipSpace();
       
   315 	pos = lex.Offset();
       
   316 	lex.SkipCharacters();
       
   317 	iCheck = GetCheck(iLine.Mid(pos,lex.Offset()-pos));
       
   318 	lex.SkipSpace();
       
   319 	lex.Val(iCheckValue);
       
   320 	}
       
   321 
       
   322 void CDummyUsbDevice::OpenFileL()
       
   323 	{
       
   324 	RFs fs;
       
   325 	User::LeaveIfError(fs.Connect());
       
   326 	CleanupClosePushL(fs);
       
   327 
       
   328 	TFindFile ff(fs);
       
   329 	User::LeaveIfError(ff.FindByDir(_L("\\system\\data\\t_charging.txt"),KNullDesC));
       
   330 	
       
   331 	RFile file;
       
   332 	TInt size;
       
   333 	User::LeaveIfError(file.Open(fs,ff.File(),EFileStreamText|EFileRead|EFileShareReadersOnly));
       
   334 	CleanupClosePushL(file);
       
   335 	
       
   336 	User::LeaveIfError(file.Size(size));
       
   337 
       
   338 	iText = REINTERPRET_CAST(TText8*, User::AllocL(size));
       
   339 	iPtr.Set(iText, size/sizeof(TText8), size/sizeof(TText8));
       
   340 	TPtr8 dest(REINTERPRET_CAST(TUint8*,iText), 0, size);
       
   341 	User::LeaveIfError(file.Read(dest)); 
       
   342 
       
   343 	CleanupStack::PopAndDestroy(); // file
       
   344 	CleanupStack::PopAndDestroy(); // fs
       
   345 	}
       
   346 
       
   347 TInt CDummyUsbDevice::GetNextLine()
       
   348 	{
       
   349 	TInt newLineOffset = (iPtr.Mid(iFileOffset)).Locate(13);//Find(_L("\r\n"));
       
   350 	if (newLineOffset < 0)
       
   351 		{
       
   352 		return newLineOffset;
       
   353 		}
       
   354 	if (newLineOffset == 0)
       
   355 		{
       
   356 		iFileOffset += 2;
       
   357 		return GetNextLine();
       
   358 		}
       
   359 	iLine.Set(iPtr.MidTPtr(iFileOffset, newLineOffset));
       
   360 	iFileOffset += (newLineOffset + 2);
       
   361 	if (iLine.Find(_L8("//")) == 0) // i.e. line begins with "//"
       
   362 		{
       
   363 		return GetNextLine();
       
   364 		}
       
   365 	if (iLine.Find(_L8("**")) == 0) // line begins with **, so display it
       
   366 		{
       
   367 		TBuf<100> buf; // max length 100 for test messages
       
   368 		buf.Copy(iLine);
       
   369 		iTest.Printf(_L("\n%S\n\n"),&buf);
       
   370 		return GetNextLine();
       
   371 		};
       
   372 	return newLineOffset;
       
   373 	}
       
   374 
       
   375 TInt CDummyUsbDevice::GetCommand(const TDesC8& aDes)
       
   376 	{
       
   377 	if (aDes.MatchF(_L8("none")) != KErrNotFound)
       
   378 		return EUsbChargingTestCommandNone;
       
   379 	if (aDes.MatchF(_L8("devicestate")) != KErrNotFound)
       
   380 		return EUsbChargingTestCommandDeviceState;
       
   381 	if (aDes.MatchF(_L8("usersetting")) != KErrNotFound)
       
   382 		return EUsbChargingTestCommandUserSetting;
       
   383 	User::Panic(KUsbChargingTestPanic, EUsbChargingTestPanicBadInputData);
       
   384 	return -1;
       
   385 	}
       
   386 
       
   387 TInt CDummyUsbDevice::GetAsyncOp(const TDesC8& aDes)
       
   388 	{
       
   389 	if (aDes.MatchF(_L8("none")) != KErrNotFound)
       
   390 		return EUsbChargingTestAsyncOpNone;
       
   391 	if (aDes.MatchF(_L8("delay")) != KErrNotFound)
       
   392 		return EUsbChargingTestAsyncOpDelay;
       
   393 	User::Panic(KUsbChargingTestPanic, EUsbChargingTestPanicBadInputData);
       
   394 	return -1;
       
   395 	}
       
   396 
       
   397 TInt CDummyUsbDevice::GetCheck(const TDesC8& aDes)
       
   398 	{
       
   399 	if (aDes.MatchF(_L8("none")) != KErrNotFound)
       
   400 		return EUsbChargingTestCheckNone;
       
   401 	if (aDes.MatchF(_L8("pluginstate")) != KErrNotFound)
       
   402 		return EUsbChargingTestCheckPluginState;
       
   403 	if (aDes.MatchF(_L8("milliamps")) != KErrNotFound)
       
   404 		return EUsbChargingTestCheckMilliAmps;
       
   405 	if (aDes.MatchF(_L8("charging")) != KErrNotFound)
       
   406 		return EUsbChargingTestCheckCharging;
       
   407 	User::Panic(KUsbChargingTestPanic, EUsbChargingTestPanicBadInputData);
       
   408 	return -1;
       
   409 	}
       
   410 
       
   411 void CDummyUsbDevice::DoCommand()
       
   412 	{
       
   413 	switch (iCommand)
       
   414 		{
       
   415 		case EUsbChargingTestCommandNone:
       
   416 			{
       
   417 			// do nothing	
       
   418 			}
       
   419 			break;
       
   420 		case EUsbChargingTestCommandDeviceState:
       
   421 			{
       
   422 			iObservers[0]->UsbDeviceStateChange(KErrNone, iDeviceState, TUsbDeviceState(iCommandValue));
       
   423 			iDeviceState = TUsbDeviceState(iCommandValue);
       
   424 			}
       
   425 			break;
       
   426 		case EUsbChargingTestCommandUserSetting:
       
   427 			{
       
   428 			TInt err = WriteToRepositoryProperty(iCommandValue);
       
   429 			
       
   430 			//TInt err = iRepository->Set(KUsbBatteryChargingKeyEnabledUserSetting, iCommandValue);
       
   431 			iTest(err == KErrNone);
       
   432 			}
       
   433 			break;
       
   434 		default:
       
   435 			User::Panic(KUsbChargingTestPanic, EUsbChargingTestPanicBadCommand);
       
   436 		}
       
   437 	}
       
   438 
       
   439 void CDummyUsbDevice::DoAsyncOp()
       
   440 	{
       
   441 	switch (iAsyncOp)
       
   442 		{
       
   443 		case EUsbChargingTestAsyncOpNone:
       
   444 			{
       
   445 			SetActive();
       
   446 			TRequestStatus* status = &iStatus;
       
   447 			User::RequestComplete(status, KErrNone);
       
   448 			}
       
   449 			break;
       
   450 		case EUsbChargingTestAsyncOpDelay:
       
   451 			{
       
   452 			iTimer.After(iStatus, TTimeIntervalMicroSeconds32(iAsyncOpValue));
       
   453 			SetActive();
       
   454 			}
       
   455 			break;
       
   456 		default:
       
   457 			User::Panic(KUsbChargingTestPanic, EUsbChargingTestPanicBadAsyncOp);
       
   458 		}
       
   459 	}
       
   460 
       
   461 void CDummyUsbDevice::DoCheck()
       
   462 	{
       
   463 	UpdatePluginInfo();
       
   464 	switch (iCheck)
       
   465 		{
       
   466 		case EUsbChargingTestCheckNone:
       
   467 			{
       
   468 			// do nothing
       
   469 			}
       
   470 			break;
       
   471 		case EUsbChargingTestCheckPluginState:
       
   472 			{
       
   473 			iTest(iInfo.iPluginState == iCheckValue);
       
   474 			}
       
   475 			break;
       
   476 		case EUsbChargingTestCheckMilliAmps:
       
   477 			{
       
   478 			iTest(iInfo.iRequestedCurrentValue == iCheckValue);
       
   479 			}
       
   480 			break;
       
   481 		case EUsbChargingTestCheckCharging:
       
   482 			{
       
   483 			TInt current;			
       
   484 			TInt err = GetChargingCurrentFromProperty(current);
       
   485 			
       
   486 			//TInt err = RProperty::Get(KPropertyUidUsbBatteryChargingCategory,
       
   487 			//	KPropertyUidUsbBatteryChargingChargingCurrent, current);
       
   488 			iTest(err == KErrNone);
       
   489 			iTest(current == iCheckValue);
       
   490 			}
       
   491 			break;
       
   492 		default:
       
   493 			User::Panic(KUsbChargingTestPanic, EUsbChargingTestPanicBadCheck);
       
   494 		}
       
   495 	}
       
   496 	
       
   497 TInt CDummyUsbDevice::GetChargingCurrentFromProperty(TInt &aCurrent)
       
   498 	{
       
   499 	
       
   500 	TRequestStatus stat;
       
   501 	iPropertyReadChargingCurrentAck.Subscribe(stat);
       
   502 	
       
   503 	TInt err = iProperty.Set(TUid::Uid(KBattChargReadPropertyCurrentUid),
       
   504 								KBattChargReadCurrentChargingKey,
       
   505 								1);
       
   506 	ASSERT(!err);	
       
   507 	User::WaitForRequest(stat);
       
   508 	
       
   509 	TBufC8<50> value;
       
   510 	TPtr8 myPtr(value.Des());
       
   511 	TInt error = iPropertyReadChargingCurrentAck.Get(myPtr);
       
   512 	ASSERT(!error);
       
   513 	
       
   514 	TDataFromPropBattChargToTBatteryCharging received;
       
   515 	TPckg<TDataFromPropBattChargToTBatteryCharging>tmp(received);
       
   516 	tmp.Copy(value);
       
   517 	aCurrent = received.iCurrent;
       
   518 	return received.iError;
       
   519 	
       
   520 	}
       
   521 
       
   522 TInt CDummyUsbDevice::WriteToRepositoryProperty(TInt iCommandValue)
       
   523 	{
       
   524 	TRequestStatus stat;
       
   525 	iPropertyWriteToRepositoryAck.Subscribe(stat);
       
   526 		
       
   527 	TInt err = iProperty.Set(TUid::Uid(KBattChargWriteRepositoryUid),
       
   528 									KBattChargWriteRepositoryKey,
       
   529 									iCommandValue);
       
   530 	ASSERT(!err);	
       
   531 	User::WaitForRequest(stat);
       
   532 	TInt value;
       
   533 	err = iPropertyWriteToRepositoryAck.Get(value);
       
   534 	ASSERT(!err);
       
   535 	return value;
       
   536 	}
       
   537 	
       
   538 TInt CDummyUsbDevice::StartPropertyBatteryCharging()
       
   539 	{
       
   540 	const TUidType serverUid(KNullUid, KNullUid, KBatteryChargingTUid);
       
   541 	RProcess server;
       
   542 	TInt err = server.Create(KBattChargingImg, KNullDesC, serverUid);
       
   543 	if ( err != KErrNone )
       
   544 		{
       
   545 		return err;
       
   546 		}
       
   547 	TRequestStatus stat;
       
   548 	server.Rendezvous(stat);
       
   549 	
       
   550 	if ( stat != KRequestPending )
       
   551 		{		
       
   552 		server.Kill(0); 	// abort startup
       
   553 		}
       
   554 	else
       
   555 		{		
       
   556 		server.Resume();	// logon OK - start the server
       
   557 		}
       
   558 	
       
   559 	User::WaitForRequest(stat); 	// wait for start or death
       
   560 	
       
   561 	// we can't use the 'exit reason' if the server panicked as this
       
   562 	// is the panic 'reason' and may be '0' which cannot be distinguished
       
   563 	// from KErrNone
       
   564 	
       
   565 	err = (server.ExitType() == EExitPanic) ? KErrServerTerminated : stat.Int();
       
   566 	
       
   567 	server.Close();	
       
   568 	
       
   569 	return err;
       
   570 	
       
   571 	}
       
   572 	
       
   573