diff -r 000000000000 -r a41df078684a kerneltest/f32test/smassstorage/src/tstate.cpp --- /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 +#include + +#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 cbwBuf; +GLDEF_D TBuf8 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 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 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 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); + } +