sl@0: // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32test\pccd\t_medch.cpp sl@0: // Continuously generate media changes followesd by a remount of the peripheral bus controller. sl@0: // sl@0: // sl@0: sl@0: #define __E32TEST_EXTENSION__ sl@0: #include sl@0: #include sl@0: #include sl@0: #include "d_medch.h" sl@0: sl@0: //#define __SOAK_TEST__ // Define to run until a key is pressed (Automatic tests only) sl@0: //#define __MANUAL_TEST__ // Define to allow manual control of the door/media sl@0: //#define __DEVICE_HAS_NO_DOOR__ // Define for devices that have no door (Manual tests only) sl@0: sl@0: #if defined(__MANUAL_TEST__) && defined(__WINS__) sl@0: #define __DEVICE_HAS_NO_DOOR__ sl@0: #endif sl@0: sl@0: #if !defined(__MANUAL_TEST__) && defined(__DEVICE_HAS_NO_DOOR__) sl@0: #undef __DEVICE_HAS_NO_DOOR__ sl@0: #endif sl@0: sl@0: #if defined(__MANUAL_TEST__) && defined(__SOAK_TEST__) sl@0: #undef __SOAK_TEST__ sl@0: #endif sl@0: sl@0: #ifndef __SOAK_TEST__ sl@0: #ifdef __WINS__ sl@0: const TInt KMaxTestTime = 5000000; // Run the test for 5 seconds on emulator sl@0: #else sl@0: const TInt KMaxTestTime = 10000000; // Run the test for 10 seconds on target sl@0: #endif sl@0: #endif sl@0: sl@0: #define MMC_PDD_NAME _L("MEDMMC") sl@0: sl@0: const TInt KPowerUpTimeOut = 5000000; // Give the card 5 seconds to power up sl@0: sl@0: LOCAL_D RTest test(_L("Media change test")); sl@0: sl@0: LOCAL_D TBusLocalDrive TheDrive; sl@0: LOCAL_D RMedCh TheMediaChange; sl@0: LOCAL_D TRequestStatus TheMediaStatus; sl@0: LOCAL_D TBool TheChangedFlag; sl@0: sl@0: sl@0: LOCAL_C TBool SetupDrivesForPlatform(TInt& aDrive, TInt& aSocket) sl@0: /** sl@0: * Finds a suitable drive for the media change test sl@0: * sl@0: * @param aDrive The number of the local drive to test sl@0: * @param aSocket The number of the socket to test sl@0: * @return TBool ETrue if a suitable drive is found, EFalse otherwise. sl@0: */ sl@0: { sl@0: sl@0: TDriveInfoV1Buf diBuf; sl@0: UserHal::DriveInfo(diBuf); sl@0: TDriveInfoV1 &di=diBuf(); sl@0: sl@0: aDrive = -1; sl@0: aSocket = -1; sl@0: sl@0: for(aDrive=0; aDrive < di.iTotalSupportedDrives; aDrive++) sl@0: { sl@0: test.Printf(_L(" Drive %d - %S\r\n"), aDrive, &di.iDriveName[aDrive]); sl@0: if(di.iDriveName[aDrive].MatchF(_L("MultiMediaCard0")) == KErrNone) sl@0: break; sl@0: } sl@0: sl@0: if(aDrive == di.iTotalSupportedDrives) sl@0: { sl@0: test.Printf(_L(" MMC Drive Not Found\r\n")); sl@0: return EFalse; sl@0: } sl@0: sl@0: sl@0: for(aSocket=0; aSocket < di.iTotalSockets; aSocket++) sl@0: { sl@0: test.Printf(_L("Socket %d - %S\r\n"), aSocket, &di.iSocketName[aSocket]); sl@0: if(di.iSocketName[aSocket].MatchF(_L("MultiMediaCard0")) == KErrNone) sl@0: break; sl@0: } sl@0: sl@0: if(aSocket == di.iTotalSockets) sl@0: { sl@0: test.Printf(_L(" MMC Socket Not Found\r\n")); sl@0: return EFalse; sl@0: } sl@0: sl@0: return ETrue; sl@0: } sl@0: sl@0: LOCAL_C void TestMediaAccess(TInt aExpectedError, TBool aExpectedChange) sl@0: /** sl@0: * Tests that the drive is accessable (or not) by issuing a request sl@0: * to power up the media. Also verifies that the attributes are correct. sl@0: * sl@0: * @param aExpectedError The expected result of powering up the drive sl@0: * @param aExpectedChange ETrue if the changed flag is expected to be set sl@0: * sl@0: * @return ETrue if successful, EFalse otherwise sl@0: */ sl@0: { sl@0: sl@0: RTimer rto; sl@0: TInt r = rto.CreateLocal(); sl@0: test(r == KErrNone); sl@0: sl@0: TRequestStatus rtoStat; sl@0: rto.After(rtoStat, KPowerUpTimeOut); sl@0: test(rtoStat == KRequestPending); sl@0: sl@0: if(aExpectedChange) sl@0: { sl@0: // TheChangedFlag is set when the door is opened if media was present. sl@0: // The asynch notifier is signalled when media is removed OR inserted. sl@0: User::WaitForRequest(TheMediaStatus, rtoStat); sl@0: test(TheMediaStatus != KRequestPending); sl@0: } sl@0: sl@0: // ...aChangedFlag's purpose is to notify us of media removal. sl@0: test_Equal(aExpectedChange,TheChangedFlag); sl@0: sl@0: TheDrive.NotifyChange(&TheMediaStatus); sl@0: TheChangedFlag = EFalse; sl@0: sl@0: // Attempt to power up the drive sl@0: TLocalDriveCapsV2Buf info; sl@0: do sl@0: { sl@0: r = TheDrive.Caps(info); sl@0: } sl@0: while(r != aExpectedError && rtoStat == KRequestPending); sl@0: sl@0: rto.Cancel(); sl@0: rto.Close(); sl@0: sl@0: // ...was the error as expected? sl@0: test(r == aExpectedError); sl@0: sl@0: // ...and are the caps still OK? sl@0: if(r == KErrNone) sl@0: test(info().iType == EMediaHardDisk); sl@0: else if(r == KErrNotReady) sl@0: test(info().iType == EMediaNotPresent); sl@0: sl@0: if(aExpectedChange == EFalse) sl@0: test(TheMediaStatus == KRequestPending); sl@0: } sl@0: sl@0: LOCAL_C void NextTest(const TDesC& aTitle, TInt aCycles) sl@0: /** sl@0: * Simply displays a string on the console and the current iteration. sl@0: * sl@0: * @param aTitle The text to be displayed sl@0: * @param aCycles The current iteration sl@0: */ sl@0: { sl@0: test.Console()->SetPos(20, 25); sl@0: test.Printf(_L("%S [%d cycles]"), &aTitle, aCycles); sl@0: #ifdef __MANUAL_TEST__ sl@0: test.Console()->SetPos(20, 27); sl@0: test.Printf(_L("")); sl@0: test.Getch(); sl@0: #endif sl@0: } sl@0: sl@0: GLDEF_C TInt E32Main() sl@0: /** sl@0: * Test Entry Point for T_MEDCH. sl@0: * sl@0: * This test uses the associated driver (D_MEDCH) to simulate media removal and sl@0: * door opening/closing. The media is powered up in each state and verified that sl@0: * the correct error code and changed count is returned. sl@0: */ sl@0: { sl@0: TBuf<64> b; sl@0: test.Title(); sl@0: sl@0: /** sl@0: * Load the associated media driver (MEDMMC by default). This is required to ensure sl@0: * that the device can be powered up and the capabilities if the media accessed. sl@0: */ sl@0: test.Start(_L("Load Media Driver")); sl@0: TInt r; sl@0: r=User::LoadPhysicalDevice(MMC_PDD_NAME); sl@0: if(r==KErrNotFound) sl@0: { sl@0: test.Printf(_L("Test not supported on this platform \n")); sl@0: test.End(); sl@0: return(0); sl@0: } sl@0: test(r==KErrNone || r==KErrAlreadyExists); sl@0: sl@0: /** sl@0: * Connect to the required local drive. sl@0: * TheChangedFlag is used for detection of media removal. sl@0: */ sl@0: TInt drive; sl@0: TInt socket; sl@0: if(SetupDrivesForPlatform(drive, socket)) sl@0: { sl@0: b.Format(_L("Connect to local drive %d"), drive); sl@0: test.Next(b); sl@0: TheDrive.Connect(drive, TheChangedFlag); sl@0: sl@0: /** sl@0: * Read the drive capabilities to ensure that this test may be run. sl@0: */ sl@0: test.Next(_L("Get drive capabilities")); sl@0: TLocalDriveCapsV2Buf info; sl@0: r = TheDrive.Caps(info); sl@0: if(r == KErrNotReady || r == KErrNotSupported) sl@0: { sl@0: test.Next(_L("\r\nTest requires media to be present and the door closed - Disconnecting")); sl@0: TheDrive.Disconnect(); sl@0: test.End(); sl@0: return KErrNone; sl@0: } sl@0: test(r == KErrNone); sl@0: sl@0: test(TheDrive.Caps(info) == KErrNone); sl@0: test(info().iType == EMediaHardDisk); sl@0: sl@0: /** sl@0: * Load the media simulation test driver sl@0: */ sl@0: test.Next(_L("Load media change logical device")); sl@0: r=User::LoadLogicalDevice(_L("D_MEDCH")); sl@0: test(r == KErrNone || r == KErrAlreadyExists); sl@0: sl@0: test.Next(_L("Open device")); sl@0: r=TheMediaChange.Open(socket, TheMediaChange.VersionRequired()); sl@0: if(r == KErrNotSupported) sl@0: { sl@0: test.Next(_L("\r\nTest not supported on this drive - Disconnecting")); sl@0: r=User::FreeLogicalDevice(_L("MedCh")); sl@0: test(r == KErrNone); sl@0: TheDrive.Disconnect(); sl@0: test.End(); sl@0: return KErrNone; sl@0: } sl@0: test(r == KErrNone); sl@0: sl@0: /** sl@0: * Verify that the system supports simulation of media change events sl@0: */ sl@0: test.Next(_L("Test support for media change simulation")); sl@0: r = TheMediaChange.DoorNormal(); sl@0: test(r == KErrNone || r == KErrNotSupported); sl@0: sl@0: /** sl@0: * Now for the real testing... sl@0: */ sl@0: if(r == KErrNone) sl@0: { sl@0: /** sl@0: * Test0 - Simulate 2 consecutive door open interrupts sl@0: */ sl@0: test.Next(_L("Test that the pbus can handle 2 consecutive door open interrupts")); sl@0: TheDrive.NotifyChange(&TheMediaStatus); sl@0: r = TheMediaChange.DoubleDoorOpen(); sl@0: test(r == KErrNone || r == KErrNotSupported); sl@0: TestMediaAccess(KErrNone, ETrue); sl@0: sl@0: sl@0: TInt cycles=0; sl@0: #if defined(__SOAK_TEST__) sl@0: TRequestStatus endStat; sl@0: test.Console()->Read(endStat); sl@0: while(endStat == KRequestPending) sl@0: #elif !defined(__MANUAL_TEST__) sl@0: RTimer t; sl@0: r=t.CreateLocal(); sl@0: test(r == KErrNone); sl@0: TRequestStatus endStat; sl@0: t.After(endStat, KMaxTestTime); sl@0: test(endStat == KRequestPending); sl@0: while(endStat == KRequestPending) sl@0: #endif sl@0: { sl@0: TheChangedFlag = EFalse; sl@0: sl@0: TheDrive.NotifyChange(&TheMediaStatus); sl@0: sl@0: /** sl@0: * Test1 - Simulate door open sl@0: * - Power up responds with KErrNotReady sl@0: */ sl@0: NextTest(_L("Open Door......"), cycles); sl@0: #ifndef __MANUAL_TEST__ sl@0: test(TheMediaChange.DoorOpen() == KErrNone); sl@0: #endif sl@0: TestMediaAccess(KErrNotReady, ETrue); sl@0: TheDrive.NotifyChange(&TheMediaStatus); sl@0: sl@0: /** sl@0: * Test2 - Simulate door closed (with media removed) sl@0: * - Power up responds with KErrNotReady sl@0: */ sl@0: #ifndef __DEVICE_HAS_NO_DOOR__ sl@0: NextTest(_L("Remove Media..."), cycles); sl@0: #ifndef __MANUAL_TEST__ sl@0: test(TheMediaChange.DoorClose(EFalse) == KErrNone); sl@0: #endif sl@0: TestMediaAccess(KErrNotReady, EFalse); sl@0: /** sl@0: * Test3 - Simulate door open sl@0: * - Power up responds with KErrNotReady sl@0: */ sl@0: NextTest(_L("Open Door......"), cycles); sl@0: #ifndef __MANUAL_TEST__ sl@0: test(TheMediaChange.DoorOpen() == KErrNone); sl@0: #endif sl@0: TestMediaAccess(KErrNotReady, EFalse); // Power up responds with KErrNotReady sl@0: #endif sl@0: /** sl@0: * Test4 - Simulate door closed (with media present) sl@0: * - Power up responds with KErrNone sl@0: */ sl@0: NextTest(_L("Insert Media..."), cycles); sl@0: #ifndef __MANUAL_TEST__ sl@0: test(TheMediaChange.DoorClose(ETrue) == KErrNone); sl@0: #endif sl@0: TestMediaAccess(KErrNone, ETrue); sl@0: ++cycles; sl@0: } sl@0: sl@0: test.Console()->SetPos(0, 27); sl@0: #if !defined(__SOAK_TEST__) && !defined(__MANUAL_TEST__) sl@0: t.Close(); sl@0: #endif sl@0: } sl@0: else if(r == KErrNotSupported) sl@0: { sl@0: test.Printf(_L("Media change simulation not supported")); sl@0: } sl@0: sl@0: /** sl@0: * Tidy up and exit sl@0: */ sl@0: test.Next(_L("\r\nClose device")); sl@0: TheMediaChange.Close(); sl@0: sl@0: test.Next(_L("Free device")); sl@0: r=User::FreeLogicalDevice(_L("MedCh")); sl@0: test(r == KErrNone); sl@0: sl@0: b.Format(_L("\r\nDisconnect from local drive %d "), drive); sl@0: test.Next(b); sl@0: TheDrive.Disconnect(); sl@0: } sl@0: sl@0: test.End(); sl@0: return(0); sl@0: } sl@0: