kerneltest/f32test/smassstorage/src/tstate.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/f32test/smassstorage/src/tstate.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,460 @@
+// Copyright (c) 2004-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:
+// Implementation of generic finite state machine state
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+*/
+
+#include <f32file.h>
+#include <testusbc.h>
+
+#include "tstate.h"
+#include "t_ms_main.h"
+#include "scsicmdbuilder.h"
+#include "cpropertywatch.h"
+
+_LIT(KMsFs, "MassStorageFileSystem");
+
+GLREF_D RFs fs;
+GLREF_D TInt removalDrvNo;
+GLREF_D TUint8 testLun;
+
+GLDEF_D TBuf8<KCbwLength> cbwBuf; 
+GLDEF_D TBuf8<KCswLength> cswBuf;
+
+GLDEF_D TInt dCBWTag = 1234567;    // arbitrary, any number would do for this test.
+GLDEF_D RDevTestUsbcClient usbcClient;
+
+/**
+Unmount FAT and mount MSFS.
+
+@param driveNumber
+*/
+LOCAL_C void MountMsFs(TInt driveNumber)
+	{
+	test.Printf(_L("MountMsFs driveNumber=%d\n"), driveNumber); 
+
+	TInt err = KErrNone;
+	
+	TFileName oldFs;
+	err = fs.FileSystemName(oldFs, driveNumber);
+	test.Printf(_L("FAT file system name %S; error code %d\n"), &oldFs, err);
+	test(err == KErrNone || err == KErrNotFound);
+	if(err==KErrNone)
+		{
+		test.Printf(_L("Unmounting FAT FS %S\n"), &oldFs); 
+	    err = fs.DismountFileSystem(oldFs, driveNumber);
+	   	test.Printf(_L("%S Dismount %c: %d\n"), &oldFs,'A' + driveNumber, err);
+	    test(err == KErrNone);
+		}
+	
+	test.Printf(_L("Mounting MSFS\n")); 
+	err = fs.MountFileSystem(KMsFs, driveNumber);
+	test.Printf(_L("MSFS Mount %c:   %d\n"), 'A' + driveNumber, err);
+	}
+
+/**
+Unmount MSFS and mount FAT.
+
+@param driveNumber
+*/
+LOCAL_C void UnmountMsFs(TInt driveNumber)
+	{
+	test.Printf(_L("UnmountMsFs driveNumber=%d\n"), driveNumber); 
+	TInt err = fs.DismountFileSystem(KMsFs, driveNumber);
+
+	test.Printf(_L("MSFS Dismount:%d\n"), err);
+	test(err == KErrNone);
+
+	err = fs.MountFileSystem(_L("FAT"), driveNumber);
+   	test.Printf(_L("FAT Mount:    %d\n"), err);
+	}
+
+LOCAL_C TBool SendAndReceive(TInt aStatus = 0)
+	{
+    test.Printf(_L("SendAndReceive\n"));
+    TRequestStatus status;
+    usbcClient.HostWrite(status, EEndpoint1, cbwBuf, KCbwLength); 
+    User::WaitForRequest(status);
+    test(KErrNone == status.Int());
+
+    // Read CSW
+    test.Printf(_L("Reading CSW\n"));
+    usbcClient.HostRead(status, EEndpoint2, cswBuf, KCswLength);
+    User::WaitForRequest(status);
+    test(KErrNone == status.Int());
+
+    // Check dCSWTag
+    TInt recvedCBWTag = extractInt(&cswBuf[4]);
+    test(dCBWTag == recvedCBWTag);
+     
+    // Check bCSWStatus
+    TInt bCSWStatus = cswBuf[KCswLength - 1];
+    test.Printf(_L("CSW status: %d\n"), bCSWStatus);
+    return(bCSWStatus == aStatus);
+	}
+	
+//////////////////////////////////////////////////////////////
+
+void
+TDisconnected::MoveTo(TInt aStateId) const
+	{
+    switch (aStateId)
+    	{
+        case EUsbMsDriveState_Connecting:
+            MoveToConnecting();
+            break;
+    	case EUsbMsDriveState_Connected:
+    		MoveToConnected();
+    		break;	
+        default:
+            test.Printf(_L("Cannot reach %d from %d\n"), GetStateId(), aStateId);
+            test(EFalse);
+    	}
+	}
+
+void
+TDisconnected::MoveToConnecting() const
+	{
+    test.Printf(_L("Moving to connecting state\n"));
+   	MountMsFs(removalDrvNo);	
+	
+	// send test unit ready message
+	BuildTestUnitReady();
+	createCBW(cbwBuf, ++dCBWTag, 0, 0, scsiCmdBuf, testLun);
+	test(SendAndReceive(1));		// 1: the unit is not ready!
+	}
+
+void
+TDisconnected::MoveToConnected() const
+	{
+    test.Printf(_L("Moving to connected state\n"));
+   	MountMsFs(removalDrvNo);
+
+	BuildTestUnitReady();
+	createCBW(cbwBuf, ++dCBWTag, 0, 0, scsiCmdBuf, testLun);
+	test(SendAndReceive(1));
+	}
+
+//////////////////////////////////////////////////////////////
+
+void
+TConnecting::MoveTo(TInt aStateId) const
+	{
+    switch (aStateId)
+    	{
+       	case EUsbMsState_Written:
+           	MoveToWritten();
+            break;
+       	default:
+           	test.Printf(_L("Cannot reach %d from %d\n"), GetStateId(), aStateId);
+           	test(EFalse);
+    	}
+	}
+	
+void TConnecting::MoveToWritten() const
+	{
+	test.Printf(_L("Moving to written state\n"));
+	
+	// Mount MS file system 
+	MountMsFs(removalDrvNo);
+	
+	BuildTestUnitReady();
+	createCBW(cbwBuf, ++dCBWTag, 0, 0, scsiCmdBuf, testLun);
+	test(SendAndReceive(1));
+
+	// Write 1k bytes using testldd. 
+	// 0x2A: opcode for write (10); 10: starting sector; 2: total sectors
+	BuildReadWrite(0x2A, 10, 2);
+	// 0: indicates host writing
+	createCBW(cbwBuf, ++dCBWTag, KKiloBytes, 0, scsiCmdBuf, testLun);
+		
+    // Send write command
+    test.Printf(_L("Sending CBW write cmd\n"));
+    TRequestStatus status;
+    usbcClient.HostWrite(status, EEndpoint1, cbwBuf, KCbwLength); 
+    User::WaitForRequest(status);
+    test(KErrNone == status.Int());
+    
+	// Write actual data. We don't care the contents.
+    TBuf8<KKiloBytes> writeBuf;	
+	writeBuf.SetLength(KKiloBytes);
+	usbcClient.HostWrite(status, EEndpoint1, writeBuf, KKiloBytes); 
+    User::WaitForRequest(status);
+    test(KErrNone == status.Int());
+
+    // Check CSW status
+    // Read CSW
+    test.Printf(_L("Reading CSW\n"));
+    usbcClient.HostRead(status, EEndpoint2, cswBuf, KCswLength);
+    User::WaitForRequest(status);
+    test(KErrNone == status.Int());
+
+    // Check dCSWTag
+    TInt recvedCBWTag = extractInt(&cswBuf[4]);
+    test(dCBWTag == recvedCBWTag);
+     
+    // Check bCSWStatus
+    TInt bCSWStatus = cswBuf[KCswLength - 1];
+    test.Printf(_L("CSW status: %d\n"), bCSWStatus);
+    test(bCSWStatus == 0);	
+	}
+
+//////////////////////////////////////////////////////////////
+
+void
+TConnected::MoveTo(TInt aStateId) const
+	{
+    switch (aStateId)
+    	{
+       	case EUsbMsDriveState_Active:
+           	MoveToActive();
+            break;
+       	default:
+           	test.Printf(_L("Cannot reach %d from %d\n"), GetStateId(), aStateId);
+           	test(EFalse);
+    	}
+	}
+
+void
+TConnected::MoveToActive() const
+	{
+    test.Printf(_L("Moving to active state\n"));
+    
+    // send prevent medium removal using testld
+    // 1: prevent medium removal
+    BuildMediumRemoval(1);
+    createCBW(cbwBuf, ++dCBWTag, 0, 0, scsiCmdBuf, testLun);
+
+	if(!SendAndReceive())
+		{
+		// Prevent Media Removal command not supported
+		test.Printf(_L("Prevent Media Removal command not supported, issuing read instead\n"));
+	
+		// Read 1k bytes using testldd. 
+		// 0x28: opcode for read (10); 10: starting sector; 2: total sectors
+		BuildReadWrite(0x28, 10, 2);
+		// 0x80: indicates host writing
+		createCBW(cbwBuf, ++dCBWTag, KKiloBytes, 0x80, scsiCmdBuf, testLun);
+			
+		// Send read command
+		test.Printf(_L("Sending CBW read cmd\n"));
+		TRequestStatus status;
+		usbcClient.HostWrite(status, EEndpoint1, cbwBuf, KCbwLength); 
+		User::WaitForRequest(status);
+		test(KErrNone == status.Int());
+    
+		// Read actual data. We don't care the contents.
+		TBuf8<KKiloBytes> readBuf;	
+		readBuf.SetLength(KKiloBytes);
+		usbcClient.HostRead(status, EEndpoint2, readBuf, KKiloBytes); 
+		User::WaitForRequest(status);
+		test(KErrNone == status.Int());
+
+		// Check CSW status
+		// Read CSW
+		test.Printf(_L("Reading CSW\n"));
+		usbcClient.HostRead(status, EEndpoint2, cswBuf, KCswLength);
+		User::WaitForRequest(status);
+		test(KErrNone == status.Int());
+
+		// Check dCSWTag
+		TInt recvedCBWTag = extractInt(&cswBuf[4]);
+		test(dCBWTag == recvedCBWTag);
+     
+		// Check bCSWStatus
+		TInt bCSWStatus = cswBuf[KCswLength - 1];
+		test.Printf(_L("CSW status: %d\n"), bCSWStatus);
+		test(bCSWStatus == 0);
+		}
+	}
+
+//////////////////////////////////////////////////////////////
+
+void
+TActive::MoveTo(TInt aStateId) const
+	{
+    switch (aStateId)
+    	{
+       	case EUsbMsDriveState_Locked:
+           	MoveToLocked();
+            break;
+    	case EUsbMsDriveState_Disconnecting:
+    		MoveToDisconnecting();
+    		break;
+       	default:
+           	test.Printf(_L("Cannot reach %d from %d\n"), GetStateId(), aStateId);
+           	test(EFalse);
+    	}
+	}
+
+void
+TActive::MoveToLocked() const
+	{
+    test.Printf(_L("Moving to locked state\n"));
+    // To be implemented. Wait for lock defect fix
+	}
+	
+void
+TActive::MoveToDisconnecting() const
+	{
+    test.Printf(_L("Moving to disconnecting state\n"));
+    
+    // send allow medium removal using testld
+    // 0: allow medium removal
+    BuildMediumRemoval(0);
+    createCBW(cbwBuf, ++dCBWTag, 0, 0, scsiCmdBuf, testLun);
+	if(!SendAndReceive())
+		test.Printf(_L("Prevent Media Removal command not supported, no need to allow\n"));
+	
+	// Now the state is connected, let's move to disconnecting state
+	// by sending a stop unit command
+	
+	// 0: stop unit
+	BuildStartStopUnit(0);
+	createCBW(cbwBuf, ++dCBWTag, 0, 0, scsiCmdBuf, testLun);
+	test(SendAndReceive());
+	}
+
+//////////////////////////////////////////////////////////////
+
+void
+TLocked::MoveTo(TInt aStateId) const
+	{
+    switch (aStateId)
+    	{
+       	case EUsbMsDriveState_Disconnecting:
+           	MoveToDisconnecting();
+            break;
+       	default:
+           	test.Printf(_L("Cannot reach %d from %d\n"), GetStateId(), aStateId);
+           	test(EFalse);
+    	}
+	}
+
+void
+TLocked::MoveToDisconnecting() const
+	{
+    test.Printf(_L("Moving to disconnecting state\n"));
+    // To be implemented once lock issue is resolved
+	}
+
+//////////////////////////////////////////////////////////////
+
+void
+TDisconnecting::MoveTo(TInt aStateId) const
+	{
+    switch (aStateId)
+    	{
+       	case EUsbMsDriveState_Disconnected:
+           	MoveToDisconnected();
+            break;
+       	default:
+           	test.Printf(_L("Cannot reach %d from %d\n"), GetStateId(), aStateId);
+           	test(EFalse);
+    	}
+	}
+
+void
+TDisconnecting::MoveToDisconnected() const
+	{
+    test.Printf(_L("Moving to disconnected state\n"));
+    UnmountMsFs(removalDrvNo);
+	}
+
+//////////////////////////////////////////////////////////////
+
+void
+TWritten::MoveTo(TInt aStateId) const
+	{
+    switch (aStateId)
+    	{
+       	case EUsbMsState_Read:
+           	MoveToRead();
+            break;
+       	default:
+           	test.Printf(_L("Cannot reach %d from %d\n"), GetStateId(), aStateId);
+           	test(EFalse);
+    	}
+	}
+
+void
+TWritten::MoveToRead() const
+	{
+    test.Printf(_L("Moving to read state\n"));
+	
+	// Read 1k bytes using testldd. 
+	// 0x28: opcode for read (10); 10: starting sector; 2: total sectors
+	BuildReadWrite(0x28, 10, 2);
+	// 0x80: indicates host writing
+	createCBW(cbwBuf, ++dCBWTag, KKiloBytes, 0x80, scsiCmdBuf, testLun);
+		
+    // Send read command
+    test.Printf(_L("Sending CBW read cmd\n"));
+    TRequestStatus status;
+    usbcClient.HostWrite(status, EEndpoint1, cbwBuf, KCbwLength); 
+    User::WaitForRequest(status);
+    test(KErrNone == status.Int());
+    
+	// Read actual data. We don't care the contents.
+    TBuf8<KKiloBytes> readBuf;	
+	readBuf.SetLength(KKiloBytes);
+	usbcClient.HostRead(status, EEndpoint2, readBuf, KKiloBytes); 
+    User::WaitForRequest(status);
+    test(KErrNone == status.Int());
+
+    // Check CSW status
+    // Read CSW
+    test.Printf(_L("Reading CSW\n"));
+    usbcClient.HostRead(status, EEndpoint2, cswBuf, KCswLength);
+    User::WaitForRequest(status);
+    test(KErrNone == status.Int());
+
+    // Check dCSWTag
+    TInt recvedCBWTag = extractInt(&cswBuf[4]);
+    test(dCBWTag == recvedCBWTag);
+     
+    // Check bCSWStatus
+    TInt bCSWStatus = cswBuf[KCswLength - 1];
+    test.Printf(_L("CSW status: %d\n"), bCSWStatus);
+    test(bCSWStatus == 0);		
+	}
+
+//////////////////////////////////////////////////////////////
+
+void
+TRead::MoveTo(TInt aStateId) const
+	{
+    switch (aStateId)
+    	{
+       	case EUsbMsDriveState_Disconnected:
+           	MoveToDisconnected();
+            break;
+       	default:
+           	test.Printf(_L("Cannot reach %d from %d\n"), GetStateId(), aStateId);
+           	test(EFalse);
+    	}
+	}
+
+void
+TRead::MoveToDisconnected() const
+	{
+    test.Printf(_L("Moving to disconnected state\n"));
+    UnmountMsFs(removalDrvNo);
+	}
+