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