kerneltest/e32test/pccd/t_medch.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:26:05 +0100
branchRCL_3
changeset 29 743008598095
parent 0 a41df078684a
child 43 c1f20ce4abcf
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// e32test\pccd\t_medch.cpp
// Continuously generate media changes followesd by a remount of the peripheral bus controller.
// 
//

#define __E32TEST_EXTENSION__
#include <e32test.h>
#include <e32svr.h>
#include <hal.h>
#include "d_medch.h"

//#define __SOAK_TEST__				// Define to run until a key is pressed (Automatic tests only)
//#define __MANUAL_TEST__			// Define to allow manual control of the door/media
//#define __DEVICE_HAS_NO_DOOR__	// Define for devices that have no door (Manual tests only)

#if defined(__MANUAL_TEST__) && defined(__WINS__)
#define __DEVICE_HAS_NO_DOOR__
#endif

#if !defined(__MANUAL_TEST__) && defined(__DEVICE_HAS_NO_DOOR__)
#undef __DEVICE_HAS_NO_DOOR__
#endif

#if defined(__MANUAL_TEST__) && defined(__SOAK_TEST__)
#undef __SOAK_TEST__
#endif

#ifndef __SOAK_TEST__
#ifdef __WINS__
const TInt KMaxTestTime	=  5000000;	// Run the test for 5 seconds on emulator
#else
const TInt KMaxTestTime	= 10000000;	// Run the test for 10 seconds on target
#endif
#endif

#define MMC_PDD_NAME _L("MEDMMC")

const TInt KPowerUpTimeOut = 5000000; // Give the card 5 seconds to power up

LOCAL_D	RTest test(_L("Media change test"));

LOCAL_D	TBusLocalDrive TheDrive;
LOCAL_D	RMedCh TheMediaChange;
LOCAL_D TRequestStatus TheMediaStatus;
LOCAL_D TBool TheChangedFlag;


LOCAL_C TBool SetupDrivesForPlatform(TInt& aDrive, TInt& aSocket)
/**
 * Finds a suitable drive for the media change test
 *
 * @param aDrive  The number of the local drive to test
 * @param aSocket The number of the socket to test
 * @return TBool ETrue if a suitable drive is found, EFalse otherwise.
 */
	{
	
	TDriveInfoV1Buf diBuf;
	UserHal::DriveInfo(diBuf);
	TDriveInfoV1 &di=diBuf();

	aDrive  = -1;
	aSocket = -1;
	
	for(aDrive=0; aDrive < di.iTotalSupportedDrives; aDrive++)
		{
		test.Printf(_L(" Drive %d - %S\r\n"), aDrive, &di.iDriveName[aDrive]);
		if(di.iDriveName[aDrive].MatchF(_L("MultiMediaCard0")) == KErrNone)
			break;
		}

	if(aDrive == di.iTotalSupportedDrives)
		{
		test.Printf(_L(" MMC Drive Not Found\r\n"));
		return EFalse;
		}
		
	
	for(aSocket=0; aSocket < di.iTotalSockets; aSocket++)
		{
		test.Printf(_L("Socket %d - %S\r\n"), aSocket, &di.iSocketName[aSocket]);
		if(di.iSocketName[aSocket].MatchF(_L("MultiMediaCard0")) == KErrNone)
			break;
		}

	if(aSocket == di.iTotalSockets)
		{
		test.Printf(_L(" MMC Socket Not Found\r\n"));
		return EFalse;
		}

	return ETrue;
	}

LOCAL_C void TestMediaAccess(TInt aExpectedError, TBool aExpectedChange)
/**
 * Tests that the drive is accessable (or not) by issuing a request 
 * to power up the media.  Also verifies that the attributes are correct.
 * 
 * @param aExpectedError The expected result of powering up the drive
 * @param aExpectedChange ETrue if the changed flag is expected to be set
 *
 * @return ETrue if successful, EFalse otherwise
 */
	{
	
	RTimer rto;
	TInt r = rto.CreateLocal();
	test(r == KErrNone);
	
	TRequestStatus rtoStat;
	rto.After(rtoStat, KPowerUpTimeOut);
	test(rtoStat == KRequestPending);
	
	if(aExpectedChange)
		{
		// TheChangedFlag is set when the door is opened if media was present.
		// The asynch notifier is signalled when media is removed OR inserted.
		User::WaitForRequest(TheMediaStatus, rtoStat);
		test(TheMediaStatus != KRequestPending);
		}

	// ...aChangedFlag's purpose is to notify us of media removal.
	test_Equal(aExpectedChange,TheChangedFlag);

	TheDrive.NotifyChange(&TheMediaStatus);
	TheChangedFlag = EFalse;

	// Attempt to power up the drive
	TLocalDriveCapsV2Buf info;
	do
		{
		r = TheDrive.Caps(info);
		}
	while(r != aExpectedError && rtoStat == KRequestPending);

	rto.Cancel();
	rto.Close();

	// ...was the error as expected?
	test(r == aExpectedError);

	// ...and are the caps still OK?
	if(r == KErrNone)
		test(info().iType == EMediaHardDisk);
	else if(r == KErrNotReady)
		test(info().iType == EMediaNotPresent);

	if(aExpectedChange == EFalse)
		test(TheMediaStatus == KRequestPending);
	}

LOCAL_C void NextTest(const TDesC& aTitle, TInt aCycles)
/**
 * Simply displays a string on the console and the current iteration.
 * 
 * @param aTitle  The text to be displayed
 * @param aCycles The current iteration
 */
	{
	test.Console()->SetPos(20, 25);
	test.Printf(_L("%S [%d cycles]"), &aTitle, aCycles);
#ifdef __MANUAL_TEST__
	test.Console()->SetPos(20, 27);
	test.Printf(_L("<press a key>"));
	test.Getch();
#endif
	}
		
GLDEF_C TInt E32Main()
/**
 * Test Entry Point for T_MEDCH.
 * 
 * This test uses the associated driver (D_MEDCH) to simulate media removal and 
 * door opening/closing.  The media is powered up in each state and verified that 
 * the correct error code and changed count is returned.
 */
    {
	TBuf<64> b;
	test.Title();

	/**
	 * Load the associated media driver (MEDMMC by default).  This is required to ensure 
	 * that the device can be powered up and the capabilities if the media accessed.
	 */
	test.Start(_L("Load Media Driver"));
	TInt r;
	r=User::LoadPhysicalDevice(MMC_PDD_NAME);
	if(r==KErrNotFound)
		{
		test.Printf(_L("Test not supported on this platform \n"));
		test.End();
		return(0);
		}
	test(r==KErrNone || r==KErrAlreadyExists);

	/**
	 * Connect to the required local drive.
	 * TheChangedFlag is used for detection of media removal.
	 */
	TInt drive;
	TInt socket;
	if(SetupDrivesForPlatform(drive, socket))
		{
		b.Format(_L("Connect to local drive %d"), drive);
		test.Next(b);
		TheDrive.Connect(drive, TheChangedFlag);
	
		/**
		 * Read the drive capabilities to ensure that this test may be run.
		 */
		test.Next(_L("Get drive capabilities"));
		TLocalDriveCapsV2Buf info;
		r = TheDrive.Caps(info);
		if(r == KErrNotReady || r == KErrNotSupported)
			{
			test.Next(_L("\r\nTest requires media to be present and the door closed - Disconnecting"));
			TheDrive.Disconnect();		
			test.End();
			return KErrNone;
			}	
		test(r == KErrNone);
	
		test(TheDrive.Caps(info) == KErrNone);
		test(info().iType == EMediaHardDisk);
	
		/**
		 * Load the media simulation test driver
		 */
		test.Next(_L("Load media change logical device"));
		r=User::LoadLogicalDevice(_L("D_MEDCH"));
		test(r == KErrNone || r == KErrAlreadyExists);
	
		test.Next(_L("Open device"));
		r=TheMediaChange.Open(socket, TheMediaChange.VersionRequired());
		if(r == KErrNotSupported)
			{
			test.Next(_L("\r\nTest not supported on this drive - Disconnecting"));
			r=User::FreeLogicalDevice(_L("MedCh"));
			test(r == KErrNone);
			TheDrive.Disconnect();
			test.End();
			return KErrNone;
			}	
		test(r == KErrNone);
	
		/**
		 * Verify that the system supports simulation of media change events
		 */
		test.Next(_L("Test support for media change simulation"));
		r = TheMediaChange.DoorNormal();
		test(r == KErrNone || r == KErrNotSupported);
	
		/**
		 * Now for the real testing...
		 */
		if(r == KErrNone)
			{
			/**
	    	 * Test0 - Simulate 2 consecutive door open interrupts
			 */
			test.Next(_L("Test that the pbus can handle 2 consecutive door open interrupts"));
			TheDrive.NotifyChange(&TheMediaStatus);
			r = TheMediaChange.DoubleDoorOpen();
			test(r == KErrNone || r == KErrNotSupported);
			TestMediaAccess(KErrNone, ETrue);
		

			TInt cycles=0;
#if defined(__SOAK_TEST__)
			TRequestStatus endStat;
			test.Console()->Read(endStat);
			while(endStat == KRequestPending)
#elif !defined(__MANUAL_TEST__)
			RTimer t;
			r=t.CreateLocal();
			test(r == KErrNone);
			TRequestStatus endStat;
			t.After(endStat, KMaxTestTime);
			test(endStat == KRequestPending);
			while(endStat == KRequestPending)
#endif
				{
				TheChangedFlag = EFalse;
	
				TheDrive.NotifyChange(&TheMediaStatus);
	
				/**
	    		 * Test1 - Simulate door open
				 *		 - Power up responds with KErrNotReady
				 */
				NextTest(_L("Open Door......"), cycles);
#ifndef __MANUAL_TEST__
				test(TheMediaChange.DoorOpen() == KErrNone);
#endif
				TestMediaAccess(KErrNotReady, ETrue);
				TheDrive.NotifyChange(&TheMediaStatus);
	
				/**
	    		 * Test2 - Simulate door closed (with media removed)
				 *		 - Power up responds with KErrNotReady
				 */
#ifndef __DEVICE_HAS_NO_DOOR__
	    		NextTest(_L("Remove Media..."), cycles);
#ifndef __MANUAL_TEST__
				test(TheMediaChange.DoorClose(EFalse) == KErrNone);		
#endif
				TestMediaAccess(KErrNotReady, EFalse);					
				/**
	    		 * Test3 - Simulate door open
				 *		 - Power up responds with KErrNotReady
				 */
				NextTest(_L("Open Door......"), cycles);
#ifndef __MANUAL_TEST__
				test(TheMediaChange.DoorOpen() == KErrNone);			
#endif
				TestMediaAccess(KErrNotReady, EFalse);				// Power up responds with KErrNotReady
#endif
				/**
	    		 * Test4 - Simulate door closed (with media present)
				 *		 - Power up responds with KErrNone
				 */
	    		NextTest(_L("Insert Media..."), cycles);
#ifndef __MANUAL_TEST__
				test(TheMediaChange.DoorClose(ETrue) == KErrNone);
#endif
				TestMediaAccess(KErrNone, ETrue);
				++cycles;
				}
	
			test.Console()->SetPos(0, 27);
#if !defined(__SOAK_TEST__) && !defined(__MANUAL_TEST__)
			t.Close();
#endif
			}
		else if(r == KErrNotSupported)
			{
			test.Printf(_L("Media change simulation not supported"));
			}
	
		/**
		 * Tidy up and exit
		 */
		test.Next(_L("\r\nClose device"));
		TheMediaChange.Close();
	
		test.Next(_L("Free device"));
		r=User::FreeLogicalDevice(_L("MedCh"));
		test(r == KErrNone);
	
		b.Format(_L("\r\nDisconnect from local drive %d "), drive);
		test.Next(b);
		TheDrive.Disconnect();
		}

	test.End();
	return(0);
	}