// 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);
}