// Copyright (c) 2009-2010 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:
//
#include <e32def.h>
#include <e32cmn.h>
#include <e32base.h>
#include <f32file.h>
#include <e32cons.h>
#include <e32debug.h>
#define __E32TEST_EXTENSION__
#include <e32test.h>
#include <e32property.h>
#include "cblockdevicetester.h"
#include "cmsdrive.h"
#include "tmsprintdrive.h"
#include "ttestutils.h"
extern CMsDrive* msDrive;
RTest test(_L("T_MSBOT"));
RFs fsSession;
class RMassStoragePublisher
{
public:
enum TPropertyKeys
{
KBotResetProperty = 1,
KStallProperty = 2
};
RMassStoragePublisher(TPropertyKeys aKey);
~RMassStoragePublisher();
TInt Count();
TSecureId Sid() const;
private:
TPropertyKeys iKey;
};
TSecureId RMassStoragePublisher::Sid() const
{
RProcess process;
return process.SecureId();
}
RMassStoragePublisher::RMassStoragePublisher(TPropertyKeys aKey)
: iKey(aKey)
{
_LIT_SECURITY_POLICY_PASS(KHostMassStoragePolicy);
TInt res = RProperty::Define(iKey,
RProperty::EInt,
KHostMassStoragePolicy,
KHostMassStoragePolicy);
test(res == KErrNone);
// reset the property flag
res = RProperty::Set(Sid(), iKey, 0);
}
RMassStoragePublisher::~RMassStoragePublisher()
{
TInt res = RProperty::Delete(iKey);
test(res == KErrNone || res == KErrNotFound);
}
TInt RMassStoragePublisher::Count()
{
TInt value;
TInt res = RProperty::Get(Sid(), iKey, value);
test_KErrNone(res);
RDebug::Printf("RMassStoragePublisher[%d] res=%d value=%d", iKey, res, value);
return value;
}
/*
class TTestMsBlock
{
public:
void tFileAccess();
void tBlockAccess();
void tRawAccess();
void tLastLbaAccessL();
};
*/
class CTestBot: public CBase
{
public:
static CTestBot* NewL();
~CTestBot();
private:
void ConstructL();
CTestBot();
public:
void tTagMismatch();
void tInvalidSignature();
// No Data
void tNoDataStallCsw();
void tNoDataPhaseError();
// Data OUT
void tDoStallCsw();
void tDoStallData();
void tDoPhaseError();
void tDoResidue();
// Data In
void tDiStallCsw();
void tDiStallData();
void tDiPhaseError();
void tDiResidue();
private:
void CswResetRecovery(CBotTester::TTestCase aTestCase, const TDesC& aTestName);
void NoDataResetRecovery(CBotTester::TTestCase aTestCase, const TDesC& aTestName);
void NoDataClearStall(CBotTester::TTestCase aTestCase, const TDesC& aTestName);
void DataOutClearStall(CBotTester::TTestCase aTestCase, const TDesC& aTestName);
void DataInClearStall(CBotTester::TTestCase aTestCase, const TDesC& aTestName);
private:
CBotTester* iBotTester;
};
_LIT(KBotTest, "Bulk Only Transfer Protocol Test");
_LIT(KTagMismatch, "TagMismatch");
_LIT(KInvalidSignature, "InvalidSignature");
_LIT(KNoDataStallCsw, "NoDataStallCsw");
_LIT(KNoDataPhaseError, "NoDataPhaseError");
_LIT(KDoStallCsw, "DoStallCsw");
_LIT(KDoStallData, "DoStallData");
_LIT(KDoPhaseError, "DoPhaseError");
_LIT(KDoResidue, "DoResidue");
_LIT(KDiStallCsw, "DiStallCsw");
_LIT(KDiStallData, "DiStallData");
_LIT(KDiPhaseError, "DiPhaseError");
_LIT(KDiResidue, "DiResidue");
CTestBot* CTestBot::NewL()
{
CTestBot* r = new (ELeave) CTestBot();
CleanupStack::PushL(r);
r->ConstructL();
CleanupStack::Pop();
return r;
}
void CTestBot::ConstructL()
{
TInt driveNumber = msDrive->DriveNumber();
iBotTester = CBotTester::NewL(driveNumber);
}
CTestBot::CTestBot()
{
}
CTestBot::~CTestBot()
{
delete iBotTester;
}
/**
USB Mass Storage Class Bulk-Only Transport
6.5 Host Error Handling
6.6.1 CBW Not Valid
5.3.3.1 Phase Error
@param aTestCase
@param testName
*/
void CTestBot::CswResetRecovery(CBotTester::TTestCase aTestCase, const TDesC& aTestName)
{
TInt res;
test.Start(aTestName);
RMassStoragePublisher msPublisher(RMassStoragePublisher::KBotResetProperty);
// Set test case in client
res = iBotTester->SetTest(aTestCase);
test_KErrNone(res);
// Enable test condition. File transfer is successful as the file server
// retries in the event of a transfer error.
test.Printf(_L("Writing file\n"));//
res = iBotTester->WriteEnableFile();
test_KErrNone(res);
if (aTestCase == CBotTester::ETestCaseDiPhaseError)
{
test.Printf(_L("Reading file\n"));
res = iBotTester->ReadEnableFile();
}
// Check that Host did a BOT Reset Recovery
TInt botReset = msPublisher.Count();
test(botReset==1);
test.Printf(_L("Host performed Reset Recovery.\n"));
test.End();
}
void CTestBot::NoDataResetRecovery(CBotTester::TTestCase aTestCase, const TDesC& aTestName)
{
TInt res;
test.Start(aTestName);
RMassStoragePublisher msPublisher(RMassStoragePublisher::KBotResetProperty);
// Set test case in client
res = iBotTester->SetTest(aTestCase);
test_KErrNone(res);
// Enable test condition.
res = iBotTester->WriteEnableFile();
test_KErrNone(res);
// Wait for the host to send TEST UNIT READY. The client is configured to
// respond with a Phase Error. Host should perform RESET RECOVERY
// Check that Host did a BOT Reset Recovery
User::After(1000*1000*30);
TInt count = msPublisher.Count();
test(count == 1);
test.End();
}
void CTestBot::NoDataClearStall(CBotTester::TTestCase aTestCase, const TDesC& aTestName)
{
TInt res;
test.Start(aTestName);
RMassStoragePublisher msPublisher(RMassStoragePublisher::KStallProperty);
// Set test case in client
res = iBotTester->SetTest(aTestCase);
test_KErrNone(res);
// Enable test condition.
res = iBotTester->WriteEnableFile();
test_KErrNone(res);
// Wait for the host to send TEST UNIT READY. The client is configured to
// stall this request. Host should clear stall condition and attempt to
// receive CSW again.
/*
// Cause host to send TEST UNIT READY with a client SENSE ERROR condition
res = iBotTester->WriteSenseErrorFile();
test_KErrNone(res);
// read a file
res = iBotTester->ReadTestFile();
// KErrAbort returned due to Media Error
test(KErrNotReady == res);
*/
// Check that host cleared the Stall condition
User::After(1000*1000*30);
TInt i = msPublisher.Count();
test(i == 1);
test.End();
}
void CTestBot::DataOutClearStall(CBotTester::TTestCase aTestCase, const TDesC& aTestName)
{
TInt res;
test.Start(aTestName);
RMassStoragePublisher msPublisher(RMassStoragePublisher::KStallProperty);
// Set test case in client
res = iBotTester->SetTest(aTestCase);
test_KErrNone(res);
// Enable test condition. File transfer is successful as the file server
// retries in the event of a transfer error.
res = iBotTester->WriteEnableFile();
test_KErrNone(res);
if (aTestCase == CBotTester::ETestCaseDoStallData)
{
TLba lba = 0x5;
TLba blocks = 0x4;
test.Printf(_L("Writing data LBA=0x%x Blocks=0x%x\n"), lba, blocks);
res = iBotTester->UpdateBlock(lba, blocks);
res = iBotTester->UpdateBlock(lba, blocks);
res = iBotTester->UpdateBlock(lba, blocks);
res = iBotTester->UpdateBlock(lba, blocks);
res = iBotTester->UpdateBlock(lba, blocks);
res = iBotTester->UpdateBlock(lba, blocks);
res = iBotTester->UpdateBlock(lba, blocks);
res = iBotTester->UpdateBlock(lba, blocks);
res = iBotTester->UpdateBlock(lba, blocks);
}
// Check that Host cleared the Stall condition
TInt i = msPublisher.Count();
test(i == 1);
test.End();
}
void CTestBot::DataInClearStall(CBotTester::TTestCase aTestCase, const TDesC& aTestName)
{
TInt res;
test.Start(aTestName);
RMassStoragePublisher msPublisher(RMassStoragePublisher::KStallProperty);
// Set test case in client
res = iBotTester->SetTest(aTestCase);
test_KErrNone(res);
// Enable test condition. File transfer is successful as the file server
// retries in the event of a transfer error.
res = iBotTester->WriteEnableFile();
test_KErrNone(res);
test.Next(_L("Read file and check Data-In stall\n"));
if (aTestCase == CBotTester::ETestCaseDiStallCsw)
{
res = iBotTester->ReadEnableFile();
test.Printf(_L("File read returned %d.\n"), res);
test_KErrNone(res);
}
else if (aTestCase == CBotTester::ETestCaseDiStallData)
{
res = iBotTester->ReadEnableFile();
test.Printf(_L("File read returned %d.\n"), res);
test_KErrNone(res);
}
// Check that Test client actually stalled. Note that the next CSW is
// invalid and the host will also perform Reset Recovery
TInt botStall = msPublisher.Count();
test(botStall==1);
test.Next(_L("Check next read is successful\n"));
res = iBotTester->ReadEnableFile();
test.Printf(_L("File read returned %d.\n"), res);
test_KErrNone(res);
test.Printf(_L("Host cleared stall on Bulk-In pipe.\n"));
test.End();
}
/**
Tag Mismatch:
1. CSW tag does not match CBW tag
2. CSW is not valid
3. Host shall perform a Reset Recovery
*/
void CTestBot::tTagMismatch()
{
CswResetRecovery(CBotTester::ETestCaseTagMismatch, KTagMismatch);
}
/**
Invalid Signature:
1. CSW Signature is not equal to 53425355h.
2. CSW is not valid.
3. Host shall perform a Reset Recovery.
*/
void CTestBot::tInvalidSignature()
{
CswResetRecovery(CBotTester::ETestCaseInvalidSignature, KInvalidSignature);
}
/**
Hn CSW stall condition
1. Host expects no data transfer and CSW is stalled.
2. Host shall clear the Bulk-In pipe.
3. Host shall attempt to receive the CSW again.
*/
void CTestBot::tNoDataStallCsw()
{
NoDataClearStall(CBotTester::ETestCaseNoDataStallCsw, KNoDataStallCsw);
}
/**
Hn CSW Phase Error status
1. Host expect no data transfer and CSW status = 02h (Phase Error.
2. Host shall peroform a reset recovery.
*/
void CTestBot::tNoDataPhaseError()
{
NoDataResetRecovery(CBotTester::ETestCaseNoDataPhaseError, KNoDataPhaseError);
}
void CTestBot::tDoStallCsw()
{
DataOutClearStall(CBotTester::ETestCaseDoStallCsw, KDoStallCsw);
}
void CTestBot::tDoStallData()
{
DataOutClearStall(CBotTester::ETestCaseDoStallData, KDoStallData);
}
void CTestBot::tDoPhaseError()
{
CswResetRecovery(CBotTester::ETestCaseDoPhaseError, KDoPhaseError);
}
void CTestBot::tDoResidue()
{
TInt res;
test.Start(KDoResidue);
res = iBotTester->SetTest(CBotTester::ETestCaseDoResidue);
test_KErrNone(res);
res = iBotTester->WriteEnableFile();
test_KErrNone(res);
res = iBotTester->WriteEnableFile();
test_KErrNone(res);
res = iBotTester->WriteEnableFile();
test_KErrNone(res);
res = iBotTester->WriteEnableFile();
test_KErrNone(res);
res = iBotTester->WriteEnableFile();
test_KErrNone(res);
test.End();
}
void CTestBot::tDiStallCsw()
{
DataInClearStall(CBotTester::ETestCaseDiStallCsw, KDiStallCsw);
}
void CTestBot::tDiStallData()
{
DataInClearStall(CBotTester::ETestCaseDiStallData, KDiStallData);
}
void CTestBot::tDiPhaseError()
{
CswResetRecovery(CBotTester::ETestCaseDiPhaseError, KDiPhaseError);
}
void CTestBot::tDiResidue()
{
TInt res;
test.Start(KDiResidue);
// First write test file to drive
res = iBotTester->InitReadEnableFile();
test_KErrNone(res);
res = iBotTester->SetTest(CBotTester::ETestCaseDiResidue);
test_KErrNone(res);
res = iBotTester->WriteEnableFile();
test_KErrNone(res);
res = iBotTester->ReadEnableFile();
test_KErrNone(res);
res = iBotTester->ReadEnableFile();
test_KErrNone(res);
res = iBotTester->ReadEnableFile();
test_KErrNone(res);
res = iBotTester->ReadEnableFile();
test_KErrNone(res);
res = iBotTester->ReadEnableFile();
test_KErrNone(res);
res = iBotTester->ReadEnableFile();
test_KErrNone(res);
res = iBotTester->ReadEnableFile();
test_KErrNone(res);
res = iBotTester->ReadEnableFile();
test_KErrNone(res);
test.End();
}
void CallTestsL()
{
test.Start(KBotTest);
CTestBot* tBot = CTestBot::NewL();
test.Next(KTagMismatch);
tBot->tTagMismatch();
test.Next(KInvalidSignature);
tBot->tInvalidSignature();
test.Next(KNoDataStallCsw);
tBot->tNoDataStallCsw();
test.Next(KNoDataPhaseError);
tBot->tNoDataPhaseError();
test.Next(KDoStallCsw);
tBot->tDoStallCsw();
// test.Next(KDoStallData); // not working in test client
// tBot->tDoStallData();
test.Next(KDoPhaseError);
tBot->tDoPhaseError();
test.Next(KDiStallCsw);
tBot->tDiStallCsw();
test.Next(KDiStallData);
tBot->tDiStallData();
test.Next(KDiPhaseError);
tBot->tDiPhaseError();
test.Next(KDoResidue);
tBot->tDoResidue();
test.Next(KDiResidue);
tBot->tDiResidue();
delete tBot;
test.End();
}