kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/transport/botmscserver.cpp
// 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 <e32des8.h>
#include <e32std.h>
#include "msctypes.h"
#include "mscutils.h"
#include "botmsctypes.h"
#include "testman.h"
#include "botmscserver.h"
#include "debug.h"
TDataTransferMan::TDataTransferMan()
: iReadBuf(NULL, 0),
iWriteBuf(NULL, 0)
{
}
void TDataTransferMan::Init()
{
iMode = EDataTransferNoData;
}
/**
Called by the protocol after processing the packet to indicate that more data is
required.
@param aData reference to the data buffer.
*/
void TDataTransferMan::SetModeDataOut(TPtr8& aData)
{
__PRINT1(_L("Length = %d (bytes)\n"), aData.Length());
iReadBuf.Set(aData);
iMode = EDataTransferOut;
}
/**
Called by the protocol after processing the packet to indicate that data should
be written to the host.
@param aData reference to the data buffer.
*/
void TDataTransferMan::SetModeDataIn(TPtrC8& aData)
{
__PRINT1(_L("Length = %d (bytes)\n"), aData.Length());
iWriteBuf.Set(aData);
iMode = EDataTransferIn;
}
TBotServerReq::TBotServerReq()
{
}
void TBotServerReq::DecodeL(const TDesC8& aPtr)
{
if (aPtr.Length() != KCbwLength)
{
User::Leave(KErrUnderflow);
}
// Check reserved bits (must be zero)
if ((aPtr[KCbwLunOffset] & 0xF0) || (aPtr[KCbwCbLengthOffset] & 0xE0))
{
__PRINT(_L("Reserved bits not zero\n"));
User::Leave(KErrArgument);
}
iSignature = LittleEndian::Get32(&aPtr[KCbwSignatureOffset]);
iTag = LittleEndian::Get32(&aPtr[KCbwTagOffset]);
iDataTransferLength = LittleEndian::Get32(&aPtr[KCbwDataTransferLengthOffset]);
iDirection = aPtr[KCbwFlagOffset] ? EDataIn : EDataOut;
iLun = aPtr[KCbwLunOffset] & 0x0F;
iCbLength = aPtr[KCbwCbLengthOffset];
}
TBool TBotServerReq::IsValidCbw() const
{
if (iSignature != 0x43425355)
{
return EFalse;
}
// CBW length checked in DecodeL
return ETrue;
}
TBool TBotServerReq::IsMeaningfulCbw(TInt aMaxLun) const
{
if (iLun > aMaxLun)
{
return EFalse;
}
if (iCbLength < 1 || iCbLength > KMaxCbwcbLength)
{
return EFalse;
}
return ETrue;
}
TBotCsw::TBotCsw(TUint32 aTag, TUint32 aDataResidue, TCswStatus aStatus)
: iTag(aTag),
iDataResidue(aDataResidue),
iStatus(aStatus)
{
}
TBotServerResp::TBotServerResp(TUint32 aTag, TUint32 aDataResidue, TCswStatus aStatus)
: TBotCsw(aTag, aDataResidue, aStatus)
{
}
void TBotServerResp::EncodeL(TDes8& aBuffer) const
{
TUint8* ptr = const_cast<TUint8*>(aBuffer.Ptr());
// dCBWSignature
ptr += KCswSignatureOffset;
*ptr++ = 0x55;
*ptr++ = 0x53;
*ptr++ = 0x42;
*ptr++ = 0x53;
LittleEndian::Put32(&aBuffer[KCswTagOffset], iTag);
LittleEndian::Put32(&aBuffer[KCswDataResidueOffset], iDataResidue);
aBuffer[KCswStatusOffset] = static_cast<TUint8>(iStatus);
}
#ifdef MSDC_TESTMODE
void TBotServerResp::EncodeL(TDes8& aBuffer, TTestParser* aTestParser) const
{
// dCBWSignature
TInt index = KCswSignatureOffset;
aBuffer[index++] = 0x55;
aBuffer[index++] = 0x53;
aBuffer[index++] = 0x42;
aBuffer[index++] = 0x53;
TUint32 tag = iTag;
TCswStatus status = iStatus;
if (aTestParser && aTestParser->Enabled())
{
TTestParser::TTestCase testCase = aTestParser->TestCase();
if (testCase == TTestParser::ETestCaseInvalidSignature)
{
__TESTMODEPRINT1("[x%x] Setting Invalid Signature in CSW", tag);
aTestParser->ClrTestCase();
index = KCswSignatureOffset;
aBuffer[index++] = 0x50;
aBuffer[index++] = 0x50;
aBuffer[index++] = 0x50;
aBuffer[index++] = 0x50;
}
else if (testCase == TTestParser::ETestCaseTagMismatch)
{
__TESTMODEPRINT1("[x%x] Setting invalid tag in CSW", tag);
aTestParser->ClrTestCase();
tag = ~iTag;
}
if (aTestParser->Enabled())
{
if (testCase == TTestParser::ETestCaseDoPhaseError)
{
aTestParser->ClrTestCase();
__TESTMODEPRINT1("[x%x] Setting CSW Phase Error (Data-Out)", tag);
status = TBotCsw::EPhaseError;
}
else if (testCase == TTestParser::ETestCaseDiPhaseError)
{
aTestParser->ClrTestCase();
__TESTMODEPRINT1("[x%x] Setting CSW Phase Error (Data-In)", tag);
status = TBotCsw::EPhaseError;
}
else if (testCase == TTestParser::ETestCaseNoDataPhaseError &&
aTestParser->PhaseErrorEnabled())
{
aTestParser->ClrTestCase();
__TESTMODEPRINT1("[x%x] Setting CSW Phase (no data)", tag);
status = TBotCsw::EPhaseError;
}
else
; // do nothing
}
}
LittleEndian::Put32(&aBuffer[KCswTagOffset], tag);
LittleEndian::Put32(&aBuffer[KCswDataResidueOffset], iDataResidue);
aBuffer[KCswStatusOffset] = static_cast<TUint8>(status);
}
#endif
/**
This function unpacks into the TUsbRequestHdr class from a descriptor with
the alignment that would be introduced on the USB bus.
@param aBuffer Input buffer
@param aTarget Unpacked header.
@return Error.
*/
TInt TBotServerFunctionReq::Decode(const TDesC8& aBuffer)
{
if (aBuffer.Length() < static_cast<TInt>(KRequestHdrSize))
{
__PRINT1(_L("TBotServerFunctionReq::Decode buffer invalid length %d"), aBuffer.Length());
return KErrGeneral;
}
iRequestType = aBuffer[0];
iRequest = static_cast<TEp0Request>(aBuffer[1]);
iValue = static_cast<TUint16>(aBuffer[2] + (aBuffer[3] << 8));
iIndex = static_cast<TUint16>(aBuffer[4] + (aBuffer[5] << 8));
iLength = static_cast<TUint16>(aBuffer[6] + (aBuffer[7] << 8));
__PRINT5(_L("type=%d request=%d value=%d index=%d length=%d"), iRequestType,iRequest,iValue,iIndex,iLength);
return KErrNone;
}
/**
This function determines whether data is required by the host in response
to a message header.
@return TBool Flag indicating whether a data response required.
*/
TBool TBotServerFunctionReq::IsDataResponseRequired() const
{
return (iRequestType & 0x80) ? ETrue : EFalse;
}