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_pccd3.cpp
sl@0: // 
sl@0: //
sl@0: 
sl@0: #include <e32test.h>
sl@0: #include <e32svr.h>
sl@0: #include <e32hal.h>
sl@0: #include <e32uid.h>
sl@0: #include <d_pccdif.h>
sl@0: #include <hal.h>
sl@0: #define TEST_NOTIFIER
sl@0: 
sl@0: LOCAL_D RTest test(_L("T_PCCD3"));
sl@0: LOCAL_D TBool SimpleCDScheme;
sl@0: LOCAL_D TInt TotalSockets;
sl@0: LOCAL_D RPcCardCntrlIf PccdDrv[KMaxPBusSockets];
sl@0: 
sl@0: const TSocket KSocket=0;
sl@0: const TInt KFunc=0;
sl@0: 
sl@0: 
sl@0: #ifdef TEST_NOTIFIER
sl@0: LOCAL_C void theMediaChangeNotifierTests()
sl@0: //
sl@0: // Test UserSvr::MediaChangeNotify() and UserSvr::ForceRemountMedia().
sl@0: //
sl@0: 	{
sl@0: 
sl@0: 	test.Next(_L("The media change notifier(s)"));
sl@0: 
sl@0: 	// Test requesting on a non-removable device
sl@0: 	TRequestStatus rs[KMaxPBusSockets];
sl@0: 	test(UserSvr::MediaChangeNotify(EFixedMedia0,&rs[0])==KErrNotSupported);
sl@0: 
sl@0: #ifndef _DEBUG
sl@0: 	test(UserSvr::MediaChangeNotify(ERemovableMedia0,&rs[0])==KErrInUse);
sl@0: #else
sl@0: 	test.Printf( _L("<<<THIS WILL BREAK F32 MEDIA CHANGE NOTIFICATION>>>\r\n"));
sl@0: 	TInt socket;
sl@0: 	TMediaDevice md;
sl@0: 	for (socket=0;socket<TotalSockets;socket++)
sl@0: 		{
sl@0: 		// Register the notifier on all sockets here - out of the main loop to 
sl@0: 		// test operation with multiple outstanding requests on different sockets
sl@0: 		md=(TMediaDevice)(ERemovableMedia0+socket);
sl@0: 		test(UserSvr::MediaChangeNotify(md,&rs[socket])==KErrNone);
sl@0: 		}
sl@0: 
sl@0: 	for (socket=0;socket<TotalSockets;socket++)
sl@0: 		{
sl@0: 		md=(TMediaDevice)(ERemovableMedia0+socket);
sl@0: 		// Perform the entire test twice
sl@0: 		for (TInt cycleCount=1;cycleCount<=2;cycleCount++)
sl@0: 			{
sl@0: 			if (cycleCount>1)
sl@0: 				{
sl@0: 				// Second time around we need to make a request 
sl@0: 				test(UserSvr::MediaChangeNotify(md,&rs[socket])==KErrNone);
sl@0: 				}
sl@0: 			UserSvr::ForceRemountMedia(md); 	// Generate media change	
sl@0: 			User::WaitForRequest(rs[socket]);			// From door open
sl@0: 			test(rs[socket].Int()==KErrNone);
sl@0: 			test.Printf( _L("Media change notify on Socket %d\r\n"),socket);
sl@0: 			if (!SimpleCDScheme)
sl@0: 				{
sl@0: 				// For CD scheme, the open/close occur too close together to
sl@0: 				// detect separately
sl@0: 				test(UserSvr::MediaChangeNotify(md,&rs[socket])==KErrNone);
sl@0: 				User::WaitForRequest(rs[socket]);		// From door close again
sl@0: 				test(rs[socket].Int()==KErrNone);
sl@0: 				test.Printf( _L("Media change notify on Socket %d\r\n"),socket);
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	// Test requesting on an invalid socket for this platform
sl@0: 	if (TotalSockets<KMaxPBusSockets)
sl@0: 		test(UserSvr::MediaChangeNotify((TMediaDevice)(ERemovableMedia0+TotalSockets),&rs[0])==KErrGeneral);
sl@0: 	#endif
sl@0: 	}
sl@0: 
sl@0: #else
sl@0: LOCAL_C void theMediaChangeNotifierTests()
sl@0: //
sl@0: // Test UserSvr::MediaChangeNotify() and UserSvr::ForceRemountMedia().
sl@0: //
sl@0: 	{
sl@0: 
sl@0: 	test.Next(_L("The media change notifier(s)"));
sl@0: 
sl@0: 	// Test requesting on a non-removable device
sl@0: 	TRequestStatus rs;
sl@0: 	test(UserSvr::MediaChangeNotify(EFixedMedia0,&rs)==KErrNotSupported);
sl@0: 
sl@0: #ifndef _DEBUG
sl@0: 	test(UserSvr::MediaChangeNotify(ERemovableMedia0,&rs)==KErrInUse);
sl@0: #else
sl@0: 	test.Printf( _L("<<<MEDIA CHANGE NOTIFICATION TESTS DISABLED>>>\r\n"),i);
sl@0: #endif
sl@0: 	}
sl@0: #endif
sl@0: 
sl@0: LOCAL_C void thePccdControllerMediaChangeEventTests()
sl@0: //
sl@0: // Test registering on media change events
sl@0: //
sl@0: 	{
sl@0: 
sl@0: 	test.Next(_L("PC Card Controller - Media change notification"));
sl@0: 	if (SimpleCDScheme)
sl@0: 		{
sl@0: 		TRequestStatus rs[KMaxPBusSockets];
sl@0: 		TInt i;
sl@0: 		for (i=0;i<TotalSockets;i++)
sl@0: 			test(PccdDrv[i].RegisterEvent(EPcCardEvMediaChange,&rs[i])==KErrNone);
sl@0: 
sl@0: 		for (i=0;i<TotalSockets;i++)
sl@0: 			{
sl@0: 			test.Printf( _L("<<<Insert the card in socket %d >>>\r\n"),i);
sl@0: 			User::WaitForRequest(rs[i]);
sl@0: 			test(rs[i].Int()==KErrNone);
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	else
sl@0: 		{
sl@0: 		TRequestStatus rs;
sl@0: 		test(PccdDrv[0].RegisterEvent(EPcCardEvMediaChange,&rs)==KErrNone);
sl@0: 
sl@0: #if defined (__WINS__)
sl@0: 		test.Printf( _L("<<<Hit F5>>>\r\n"));
sl@0: #else
sl@0: 		test.Printf( _L("<<<Open and close CF card door>>>\r\n"));
sl@0: 		test.Printf( _L("<<<Machine will turn off as soon as door is opened>>>\r\n"));
sl@0: #endif
sl@0: 		User::WaitForRequest(rs);
sl@0: 		test(rs.Int()==KErrNone);
sl@0: #if defined (__WINS__)
sl@0: 		// Delay power off until after F5 key up event. Key up doesn't occur when in standby.
sl@0: 		// Without this the power-on test fails because the simulated door state is stuck open.
sl@0: 		User::After(500000);
sl@0: #endif
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: LOCAL_C void thePccdControllerPowerEventTests()
sl@0: //
sl@0: // Test registering on power events
sl@0: //
sl@0: 	{
sl@0: 
sl@0: 	test.Next(_L("PC Card Controller - Power-off notification."));
sl@0: 	RTimer timer;
sl@0: 	TRequestStatus prs, trs;
sl@0: 	test(timer.CreateLocal()==KErrNone);
sl@0: 	test(PccdDrv[0].RegisterEvent(EPcCardEvPwrDown,&prs)==KErrNone);
sl@0: 	TTime tim;
sl@0: 	tim.HomeTime();
sl@0: 	tim+=TTimeIntervalSeconds(8);
sl@0: 	timer.At(trs,tim);
sl@0: 	UserHal::SwitchOff();
sl@0: 	User::WaitForRequest(prs);
sl@0: 	test(prs.Int()==KErrNone);
sl@0: 	User::WaitForRequest(trs);
sl@0: 	test(trs.Int()==KErrNone);
sl@0: 
sl@0: 	test.Next(_L("PC Card Controller - Power-on notification."));
sl@0: 	test(PccdDrv[0].RegisterEvent(EPcCardEvPwrUp,&prs)==KErrNone);
sl@0: 	tim.HomeTime();
sl@0: 	tim+=TTimeIntervalSeconds(8);
sl@0: 	timer.At(trs,tim);
sl@0: 	UserHal::SwitchOff();
sl@0: 	User::WaitForRequest(prs);
sl@0: 	test(prs.Int()==KErrNone);
sl@0: 	User::WaitForRequest(trs);
sl@0: 	test(trs.Int()==KErrNone);
sl@0: 	}
sl@0: 
sl@0: LOCAL_C void thePccdControllerStatusChangeEventTests()
sl@0: //
sl@0: // Test registering on status change events
sl@0: //
sl@0: 	{
sl@0: 
sl@0: 	TRequestStatus rs;
sl@0: 	if (!SimpleCDScheme)
sl@0: 		{
sl@0: 		// We're going to ask tester to remove CF card in order to generate a card status change 
sl@0: 		// notification. However, on P2s this involves opening the CF card door first. Because of
sl@0: 		// the media notifier (F32), opening door gives us a spurious RegisterEvent() notification.
sl@0: 		test.Printf( _L("<<<Open (don't close) media door>>>\r\n"));
sl@0: 		test(PccdDrv[0].RegisterEvent(EPcCardEvMediaChange,&rs)==KErrNone);
sl@0: 		User::WaitForRequest(rs);
sl@0: 		test(rs.Int()==KErrNone); 
sl@0: 		}
sl@0: 
sl@0: 	TInt i;
sl@0: 	for (i=(TotalSockets-1);i>=0;i--)
sl@0: 		{
sl@0: 		test.Next(_L("Card status change notification - card removal"));
sl@0: 		test(PccdDrv[i].RegisterEvent(EPcCardEvIndChange,&rs)==KErrNone);
sl@0: 		test.Printf( _L("<<<Remove the card from socket %d>>>\r\n"),i);
sl@0: 		User::WaitForRequest(rs);
sl@0: 		test(rs.Int()==KErrNone);
sl@0: 
sl@0: 		test.Next(_L("Card status change notification - card insertion"));
sl@0: 		User::After(200000);	// 0.2s
sl@0: 		TInt j=(i>0)?(i-1):i;
sl@0: 		test(PccdDrv[j].RegisterEvent(EPcCardEvIndChange,&rs)==KErrNone);
sl@0: 		test.Printf( _L("<<<Insert the card back into socket %d>>>\r\n"),j);
sl@0: 		User::WaitForRequest(rs);
sl@0: 		test(rs.Int()==KErrNone);
sl@0: 		}
sl@0: 
sl@0: 	if (!SimpleCDScheme)
sl@0: 		{
sl@0: 		test.Printf( _L("<<<Close) CF card door>>>\r\n"));
sl@0: 		test(PccdDrv[0].RegisterEvent(EPcCardEvPwrUp,&rs)==KErrNone);
sl@0: 		User::WaitForRequest(rs);
sl@0: 		test(rs.Int()==KErrNone); 
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: LOCAL_C void thePccdControllerCardReadyEventTests()
sl@0: //
sl@0: // Test registering on ready events (tests 1 socket only!!!!).
sl@0: //
sl@0: 	{
sl@0: 
sl@0: 	test.Next(_L("Card ready notification"));
sl@0: 	TRequestStatus rs;
sl@0: 	TInt r;
sl@0: 	r=PccdDrv[0].RegisterEvent(EPcCardEvRdyChange,&rs);
sl@0: 	if (r==KErrNotSupported)
sl@0: 		{
sl@0: 		test.Printf( _L("<<<Not supported on this platform>>>\r\n"));
sl@0: 		return;
sl@0: 		}
sl@0: 	test(r==KErrNone);
sl@0: 
sl@0: 	TPcCardStatus s;
sl@0: 	TSocketSignals ind;
sl@0: 	test(PccdDrv[0].SocketInfo(s,ind)==KErrNone);
sl@0: 	test(s==EPcCardNotReady);
sl@0: 	test(ind.iCardDetected);
sl@0: 	
sl@0: 	TRequestStatus prs;
sl@0: 	PccdDrv[0].PwrUp(&prs);
sl@0: 	User::WaitForRequest(rs);
sl@0: 	test(rs.Int()==KErrNone);
sl@0: 	User::WaitForRequest(prs);
sl@0: 	test(rs.Int()==KErrNone);
sl@0: 	}
sl@0: 
sl@0: GLDEF_C TInt E32Main()
sl@0: 	{
sl@0: 
sl@0: 	TInt r;
sl@0: #if defined (__WINS__)
sl@0: 	// Connect to all the local drives first as will be the case in ARM
sl@0: 	TBusLocalDrive Drive[KMaxLocalDrives];
sl@0: 	TBool ChangedFlag[KMaxLocalDrives];
sl@0: 	TInt j;
sl@0: 	for (j=0;j<KMaxLocalDrives;j++)
sl@0: 		Drive[j].Connect(j,ChangedFlag[j]);
sl@0: #endif
sl@0: 
sl@0: 	test.Title();
sl@0: //
sl@0: 	test.Start(_L("Read machine info."));
sl@0: 	// Find out what sort of media change architecture we have. How many sockets
sl@0: 	// there are and whether we have a full blown media door scheme or just a system 
sl@0: 	// using the PC Card CD signals. The later information we can't read from the
sl@0: 	// machine info, the test program just has to be updated with the machine name of 
sl@0: 	// any machine which employs the CD scheme.
sl@0: 	SimpleCDScheme=EFalse;
sl@0: 	TInt muid=0;
sl@0: 	r=HAL::Get(HAL::EMachineUid, muid);
sl@0: 	test(r==KErrNone);
sl@0: 	if (muid==HAL::EMachineUid_Brutus)
sl@0: 		SimpleCDScheme=ETrue;
sl@0: 	TDriveInfoV1Buf dinfo;
sl@0: 	UserHal::DriveInfo(dinfo);
sl@0: 	TotalSockets=dinfo().iTotalSockets;
sl@0: 
sl@0: 	if (SimpleCDScheme)
sl@0: 		test.Printf( _L("<<<Remove all PC/CF cards - hit a key>>>\r\n"));
sl@0: 	else
sl@0: 		{
sl@0: 		if (TotalSockets>0)
sl@0: 			test.Printf( _L("<<<Insert the card in socket %d - hit a key>>>\r\n"),(TotalSockets-1));
sl@0: 		}
sl@0: 	test.Getch();
sl@0: 
sl@0: 	test.Next(_L("Load/open logical devices"));
sl@0: 	r=User::LoadLogicalDevice(_L("D_PCCDIF"));
sl@0: 	test(r==KErrNone||r==KErrAlreadyExists);
sl@0: 	TInt i;
sl@0: 	for (i=0;i<TotalSockets;i++)
sl@0: 		{
sl@0: 		r=PccdDrv[i].Open(i,PccdDrv[i].VersionRequired());
sl@0: 		test(r==KErrNone);
sl@0: 		}
sl@0: 
sl@0: 	// Test UserSvr::MediaChangeNotify() and UserSvr::ForceRemountMedia().
sl@0: 	theMediaChangeNotifierTests();
sl@0: 
sl@0: 	// Test registering on PC Card Controller events
sl@0: 	thePccdControllerMediaChangeEventTests();
sl@0: 	thePccdControllerPowerEventTests();
sl@0: #if defined(__EPOC32__)
sl@0: 	thePccdControllerStatusChangeEventTests();
sl@0: 	thePccdControllerCardReadyEventTests();
sl@0: #endif
sl@0: 
sl@0: 	test.Next(_L("Close/free devices"));
sl@0: 	for (i=0;i<TotalSockets;i++)
sl@0: 		PccdDrv[i].Close();
sl@0: 	r=User::FreeLogicalDevice(_L("PccdIf"));
sl@0: 	test(r==KErrNone);
sl@0: 
sl@0: 	test.End();
sl@0: 
sl@0: #if defined (__WINS__)
sl@0: 	for (i=0;i<KMaxLocalDrives;i++)
sl@0: 		Drive[i].Disconnect();
sl@0: #endif
sl@0: 	return(0);
sl@0: 	}
sl@0: