Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
/*
* 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:
*
*/
/**
@file
@internalTechnology
*/
#include "cbulkonlytransport.h"
#include "cbulkonlytransportusbcscldd.h"
#include "usbmsshared.h"
#include "massstoragedebug.h"
#include "cusbmassstorageserver.h"
//This value defined in USB Mass Storage Bulk Only Transrt spec and not supposed to be changed
LOCAL_D const TInt KRequiredNumberOfEndpoints = 2; // in addition to endpoint 0.
LOCAL_D const TInt KUsbNumInterfacesOffset = 4;
#ifdef MSDC_MULTITHREADED
//Only used in DB. The first 2K of KMaxScBufferSize for sending CSW
static const TUint32 KCswBufferSize = 2 * 1024;
#endif
////////////////////////////////////
/**
Called by CBulkOnlyTransportUsbcScLdd to create an instance of CControlInterfaceUsbcScLdd
@param aParent reference to the CBulkOnlyTransportUsbcScLdd
*/
CControlInterfaceUsbcScLdd* CControlInterfaceUsbcScLdd::NewL(CBulkOnlyTransportUsbcScLdd& aParent)
{
CControlInterfaceUsbcScLdd* self = new(ELeave) CControlInterfaceUsbcScLdd(aParent);
CleanupStack::PushL(self);
self->ConstructL();
CActiveScheduler::Add(self);
CleanupStack::Pop();
return self;
}
void CControlInterfaceUsbcScLdd::ConstructL()
{
}
/**
c'tor
@param aParent reference to the CBulkOnlyTransportUsbcScLdd
*/
CControlInterfaceUsbcScLdd::CControlInterfaceUsbcScLdd(CBulkOnlyTransportUsbcScLdd& aParent)
:CActive(EPriorityStandard),
iParent(aParent),
iCurrentState(ENone)
{
}
/**
d'tor
*/
CControlInterfaceUsbcScLdd::~CControlInterfaceUsbcScLdd()
{
__FNLOG("CControlInterfaceUsbcScLdd::~CControlInterfaceUsbcScLdd ");
Cancel();
iEp0Buf.Close();
}
TInt CControlInterfaceUsbcScLdd::OpenEp0()
{
TInt res = iParent.Ldd().OpenEndpoint(iEp0Buf,0);
return res;
}
/**
Called by CBulkOnlyTransport HwStart to start control interface
*/
TInt CControlInterfaceUsbcScLdd::Start()
{
__FNLOG("CControlInterfaceUsbcScLdd::Start ");
TInt res = ReadEp0Data();
return (res);
}
/**
Called by desctructor of CBulkOnlyTransportUsbcScLdd to stop control interface
*/
void CControlInterfaceUsbcScLdd::Stop()
{
__FNLOG("CControlInterfaceUsbcScLdd::Stop ");
if (!IsActive())
{
__PRINT(_L("Not active\n"));
return;
}
__PRINT(_L("\nStopping...\n"));
iCurrentState = ENone;
Cancel();
}
/**
Cancel outstanding request (if any)
*/
void CControlInterfaceUsbcScLdd::DoCancel()
{
__FNLOG("CControlInterfaceUsbcScLdd::DoCancel ");
switch(iCurrentState)
{
case EReadEp0Data:
iParent.Ldd().ReadCancel(KUsbcScEndpointZero);
break;
case ESendMaxLun:
iParent.Ldd().WriteCancel(KUsbcScEndpointZero);
break;
default:
__PRINT(_L("\nWrong state !\n"));
__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceBadState));
}
}
/**
Implement CControlInterfaceUsbcScLdd state machine
*/
void CControlInterfaceUsbcScLdd::RunL()
{
__FNLOG("CControlInterfaceUsbcScLdd::RunL ");
if (iStatus != KErrNone)
{
__PRINT1(_L("Error %d in RunL\n"), iStatus.Int());
//read EP0 again
ReadEp0Data();
return;
}
ReadEp0Data();
}
/**
Actual Read to RDevUsbcScClient BIL
*/
TInt CControlInterfaceUsbcScLdd::ReadUsbEp0()
{
iCurrentState = EReadEp0Data;
iStatus = KRequestPending;
return iEp0Buf.GetBuffer (iEp0Packet,iEp0Size,iEp0Zlp,iStatus);
}
/**
Post a read request to EEndpoint0 to read request header
*/
TInt CControlInterfaceUsbcScLdd::ReadEp0Data()
{
__FNLOG("CControlInterfaceUsbcScLdd::ReadEp0Data ");
if (IsActive())
{
__PRINT(_L("Still active\n"));
return KErrServerBusy;
}
TInt r = KErrNone;
do
{
r = ReadUsbEp0();
if (r == KErrCompletion)
{
iStatus = KErrNone;
DecodeEp0Data();
}
else if (r == KErrNone)
{
SetActive();
}
} while (((r == KErrCompletion) || (r == TEndpointBuffer::KStateChange)) && (!IsActive()));
return KErrNone;
}
/**
Decode request header and do appropriate action - get max LUN info or post a reset request
*/
void CControlInterfaceUsbcScLdd::DecodeEp0Data()
{
__FNLOG("CControlInterfaceUsbcScLdd::DecodeEp0Data ");
if (IsActive())
{
__PRINT(_L("Still active\n"));
__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceStillActive));
return;
}
TPtrC8 ep0ReadDataPtr((TUint8*)iEp0Packet, iEp0Size);
TInt err = iRequestHeader.Decode(ep0ReadDataPtr);
if(err != KErrNone)
return;
switch(iRequestHeader.iRequest)
{
//
// GET MAX LUN (0xFE)
//
case TUsbRequestHdr::EReqGetMaxLun:
{
__PRINT1(_L("DecodeEp0Data : 'Get Max LUN' Request MaxLun = %d"),iParent.MaxLun() );
if ( iRequestHeader.iRequestType != 0xA1 //value from USB MS BOT spec
|| iRequestHeader.iIndex > 15
|| iRequestHeader.iValue != 0
|| iRequestHeader.iLength != 1)
{
__PRINT(_L("GetMaxLun command packet check error"));
iParent.Ldd().EndpointZeroRequestError();
break;
}
TPtr8* ep0WriteDataPtr = NULL;
TUint ep0Length;
iEp0Buf.GetInBufferRange(((TAny*&)ep0WriteDataPtr),ep0Length);
ep0WriteDataPtr->SetLength(1); //Return only 1 byte to host
ep0WriteDataPtr->Fill(0);
ep0WriteDataPtr->Fill(iParent.MaxLun()); // Supported Units
TInt length = ep0WriteDataPtr->Length();
err = iEp0Buf.WriteBuffer((TPtr8*)(ep0WriteDataPtr->Ptr()),length,ETrue,iStatus);
iCurrentState = ESendMaxLun;
SetActive();
return;
}
//
// RESET (0xFF)
//
case TUsbRequestHdr::EReqReset:
{
__PRINT(_L("DecodeEp0Data : 'Mass Storage Reset' Request"));
if ( iRequestHeader.iRequestType != 0x21 //value from USB MS BOT spec
|| iRequestHeader.iIndex > 15
|| iRequestHeader.iValue != 0
|| iRequestHeader.iLength != 0)
{
__PRINT(_L("MSC Reset command packet check error"));
iParent.Ldd().EndpointZeroRequestError();
break;
}
iParent.HwStop();
iParent.Controller().Reset();
iParent.HwStart(ETrue);
err = iParent.Ldd().SendEp0StatusPacket();
return;
}
//
// Unknown?
//
default:
{
__PRINT(_L("DecodeEp0Data : Unknown Request"));
}
}
ReadEp0Data(); //try to get another request
}
//
// --- class CBulkOnlyTransportUsbcScLdd ---------------------------------------------------------
//
CBulkOnlyTransportUsbcScLdd::CBulkOnlyTransportUsbcScLdd(TInt aNumDrives,CUsbMassStorageController& aController)
:CBulkOnlyTransport(aNumDrives, aController)
{
__FNLOG("CBulkOnlyTransportUsbcScLdd::CBulkOnlyTransportUsbcScLdd");
}
/**
Constructs the CBulkOnlyTransportUsbcScLdd object
*/
void CBulkOnlyTransportUsbcScLdd::ConstructL()
{
__FNLOG("CBulkOnlyTransportUsbcScLdd::ConstructL()");
iControlInterface = CControlInterfaceUsbcScLdd::NewL(*this);
iDeviceStateNotifier = CActiveDeviceStateNotifierBase::NewL(*this, *this);
iChunk = new RChunk();
CActiveScheduler::Add(this);
}
CBulkOnlyTransportUsbcScLdd::~CBulkOnlyTransportUsbcScLdd()
{
__FNLOG("CBulkOnlyTransportUsbcScLdd::~CBulkOnlyTransportUsbcScLdd");
if (iInterfaceConfigured)
{
TInt err = iSCReadEndpointBuf.Close();
err = iSCWriteEndpointBuf.Close();
delete iControlInterface ;
delete iDeviceStateNotifier;
delete iChunk;
}
}
RDevUsbcScClient& CBulkOnlyTransportUsbcScLdd::Ldd()
{
return iLdd;
}
/**
Set or unset configuration descriptor for USB MassStorage Bulk Only transport
@param aUnset indicate whether set or unset descriptor
@return KErrNone if operation was completed successfully, errorcode otherwise
*/
TInt CBulkOnlyTransportUsbcScLdd::SetupConfigurationDescriptor(TBool aUnset)
{
__FNLOG("CBulkOnlyTransportUsbcScLdd::SetupConfigurationDescriptor");
TInt ret(KErrNone);
if ((ret = iLdd.Open(0)) != KErrNone)
return ret;
TInt configDescriptorSize(0);
iLdd.GetConfigurationDescriptorSize(configDescriptorSize);
if (static_cast<TUint>(configDescriptorSize) != KUsbDescSize_Config)
{
return KErrCorrupt;
}
TBuf8<KUsbDescSize_Config> configDescriptor;
ret = iLdd.GetConfigurationDescriptor(configDescriptor);
if (ret != KErrNone)
{
return ret;
}
// I beleive that other fields setted up during LDD initialisation
if (aUnset)
{
--configDescriptor[KUsbNumInterfacesOffset];
}
else
{
++configDescriptor[KUsbNumInterfacesOffset];
}
ret = iLdd.SetConfigurationDescriptor(configDescriptor);
if (aUnset)
{
iLdd.Close();
}
return ret;
}
/**
Set up interface descriptor
@return KErrNone if operation was completed successfully, errorcode otherwise
*/
TInt CBulkOnlyTransportUsbcScLdd::SetupInterfaceDescriptors()
{
__FNLOG("CBulkOnlyTransportUsbcScLdd::SetupInterfaceDescriptors");
// Device caps
TUsbDeviceCaps d_caps;
TInt ret = iLdd.DeviceCaps(d_caps);
if (ret != KErrNone)
{
return ret;
}
TInt totalEndpoints = d_caps().iTotalEndpoints;
if (totalEndpoints < KRequiredNumberOfEndpoints)
{
return KErrHardwareNotAvailable;
}
// Endpoint caps
TUsbcEndpointData data[KUsbcMaxEndpoints];
TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data));
ret = iLdd.EndpointCaps(dataptr);
if (ret != KErrNone)
{
return ret;
}
// Set the active interface
TUsbcScInterfaceInfoBuf ifc;
TInt ep_found = 0;
TBool foundBulkIN = EFalse;
TBool foundBulkOUT = EFalse;
for (TInt i = 0; i < totalEndpoints ; i++)
{
const TUsbcEndpointCaps* caps = &data[i].iCaps;
const TInt maxPacketSize = caps->MaxPacketSize();
if (!foundBulkIN &&
(caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirIn)) == (KUsbEpTypeBulk | KUsbEpDirIn))
{
// InEndpoint is going to be our TX (IN, write) endpoint
ifc().iEndpointData[0].iType = KUsbEpTypeBulk;
if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) == KUsbDevCapsFeatureWord1_EndpointResourceAllocV2)
ifc().iEndpointData[0].iFeatureWord1 = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering;
ifc().iEndpointData[0].iDir = KUsbEpDirIn;
ifc().iEndpointData[0].iSize = maxPacketSize;
ifc().iEndpointData[0].iInterval_Hs = 0;
ifc().iEndpointData[0].iBufferSize = KMaxScBufferSize;
foundBulkIN = ETrue;
if (++ep_found == KRequiredNumberOfEndpoints)
{
break;
}
continue;
}
if (!foundBulkOUT &&
(caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirOut)) == (KUsbEpTypeBulk | KUsbEpDirOut))
{
// OutEndpoint is going to be our RX (OUT, read) endpoint
ifc().iEndpointData[1].iType = KUsbEpTypeBulk;
if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) == KUsbDevCapsFeatureWord1_EndpointResourceAllocV2)
ifc().iEndpointData[1].iFeatureWord1 = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering;
ifc().iEndpointData[1].iDir = KUsbEpDirOut;
ifc().iEndpointData[1].iSize = maxPacketSize;
ifc().iEndpointData[1].iInterval_Hs = 0;
ifc().iEndpointData[1].iBufferSize = KMaxScBufferSize;
ifc().iEndpointData[1].iReadSize = KMaxScReadSize;
foundBulkOUT = ETrue;
if (++ep_found == KRequiredNumberOfEndpoints)
{
break;
}
continue;
}
}
if (ep_found != KRequiredNumberOfEndpoints)
{
return KErrHardwareNotAvailable;
}
_LIT16(string, "USB Mass Storage Interface");
ifc().iString = const_cast<TDesC16*>(&string);
ifc().iTotalEndpointsUsed = KRequiredNumberOfEndpoints;
ifc().iClass.iClassNum = 0x08; // Mass Storage
ifc().iClass.iSubClassNum = 0x06; // SCSI Transparent Command Set
ifc().iClass.iProtocolNum = 0x50; // Bulk Only Transport
if (d_caps().iHighSpeed)
{
// Tell the Protocol about it, because it might want to do some
// optimizing too.
iProtocol->ReportHighSpeedDevice();
}
if ((ret = iLdd.SetInterface(0, ifc)) == KErrNone)
{
return (iLdd.FinalizeInterface(iChunk));
}
return ret;
}
void CBulkOnlyTransportUsbcScLdd::ReleaseInterface()
{
iLdd.ReleaseInterface(0);
}
TInt CBulkOnlyTransportUsbcScLdd::StartControlInterface()
{
return iControlInterface->Start();
}
void CBulkOnlyTransportUsbcScLdd::CancelControlInterface()
{
iControlInterface->Cancel();
}
void CBulkOnlyTransportUsbcScLdd::ActivateDeviceStateNotifier()
{
iDeviceStateNotifier->Activate();
}
void CBulkOnlyTransportUsbcScLdd::CancelDeviceStateNotifier()
{
iDeviceStateNotifier->Cancel();
}
void CBulkOnlyTransportUsbcScLdd::CancelReadWriteRequests()
{
__FNLOG("CBulkOnlyTransportUsbcScLdd::CancelReadWriteRequests");
TUsbcScChunkHeader chunkHeader(*iChunk);
for (TInt i = 0; i < chunkHeader.iAltSettings->iNumOfAltSettings; i++)
{
TInt8* endpoint = (TInt8*) (chunkHeader.iAltSettings->iAltTableOffset[i] + (TInt) iChunk->Base());
TInt numOfEps = chunkHeader.GetNumberOfEndpoints(i);
__ASSERT_DEBUG(numOfEps >= 0, User::Invariant());
for (TInt j = 1; j <= numOfEps; j++)
{
TUsbcScHdrEndpointRecord* endpointInf = (TUsbcScHdrEndpointRecord*) &(endpoint[j * chunkHeader.iAltSettings->iEpRecordSize]);
if (endpointInf->Direction() == KUsbScHdrEpDirectionOut)
{
iLdd.ReadCancel(endpointInf->iBufferNo);
}
if (endpointInf->Direction() == KUsbScHdrEpDirectionIn)
{
iLdd.WriteCancel(endpointInf->iBufferNo);
}
}
}
}
void CBulkOnlyTransportUsbcScLdd::AllocateEndpointResources()
{
TUsbcScChunkHeader chunkHeader(*iChunk);
for (TInt i = 0; i < chunkHeader.iAltSettings->iNumOfAltSettings; i++)
{
TInt8* endpoint = (TInt8*) (chunkHeader.iAltSettings->iAltTableOffset[i] + (TInt) iChunk->Base());
for (TInt j = 1; j <= chunkHeader.GetNumberOfEndpoints(i); j++)
{
TUsbcScHdrEndpointRecord* endpointInf = (TUsbcScHdrEndpointRecord*) &(endpoint[j * chunkHeader.iAltSettings->iEpRecordSize]);
if (endpointInf->Direction() == KUsbScHdrEpDirectionOut)
{
iOutEndpoint = j;
}
if (endpointInf->Direction() == KUsbScHdrEpDirectionIn)
{
iInEndpoint = j;
}
}
}
TUsbDeviceCaps d_caps;
TInt err;
TInt ret = iLdd.DeviceCaps(d_caps);
if (ret == KErrNone)
{
if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != KUsbDevCapsFeatureWord1_EndpointResourceAllocV2)
{
__PRINT(_L("CBulkOnlyTransportUsbcScLdd::Start - Setting up DMA and double buffering\n"));
// Set up DMA if possible (errors are non-critical)
err = iLdd.AllocateEndpointResource(iOutEndpoint, EUsbcEndpointResourceDMA);
if (err != KErrNone)
{
__PRINT1(_L("Set DMA on OUT endpoint failed with error code: %d"), err);
}
err = iLdd.AllocateEndpointResource(iInEndpoint, EUsbcEndpointResourceDMA);
if (err != KErrNone)
{
__PRINT1(_L("Set DMA on IN endpoint failed with error code: %d"), err);
}
// Set up Double Buffering if possible (errors are non-critical)
err = iLdd.AllocateEndpointResource(iOutEndpoint, EUsbcEndpointResourceDoubleBuffering);
if (err != KErrNone)
{
__PRINT1(_L("Set Double Buffering on OUT endpoint failed with error code: %d"), err);
}
err = iLdd.AllocateEndpointResource(iInEndpoint, EUsbcEndpointResourceDoubleBuffering);
if (err != KErrNone)
{
__PRINT1(_L("Set Double Buffering on IN endpoint failed with error code: %d"), err);
}
}
}
err = OpenEndpoints();
}
TInt CBulkOnlyTransportUsbcScLdd::OpenEndpoints()
{
TInt res = iLdd.OpenEndpoint(iSCReadEndpointBuf, iOutEndpoint);
if (res == KErrNone)
{
res = iLdd.OpenEndpoint(iSCWriteEndpointBuf, iInEndpoint);
if (res == KErrNone)
{
iSCWriteEndpointBuf.GetInBufferRange((TAny*&)iDataPtr, iInBufferLength);
res = iControlInterface->OpenEp0();
}
return res;
}
return res;
}
TInt CBulkOnlyTransportUsbcScLdd::GetDeviceStatus(TUsbcDeviceState& deviceStatus)
{
return iLdd.DeviceStatus(deviceStatus);
}
void CBulkOnlyTransportUsbcScLdd::FlushData()
{
// Intentionally Left Blank Do Nothing
}
/**
* Read out rest data from OutEndpoint and discard them
*/
void CBulkOnlyTransportUsbcScLdd::ReadAndDiscardData(TInt /*aBytes*/)
{
__FNLOG("CBulkOnlyTransport::ReadAndDiscardData");
TRequestStatus status;
TInt r = KErrNone; // Lets assume there is no data
do
{
iSCReadSize = 0;
status = KErrNone;
r = iSCReadEndpointBuf.TakeBuffer(iSCReadData,iSCReadSize,iReadZlp,status);
iSCReadEndpointBuf.Expire();
}
while (r == KErrCompletion);
if (r == KErrNone)
{
TRequestStatus* stat = &status;
User::RequestComplete(stat, KErrNone);
}
}
/**
Called by the protocol to determine how many bytes of data are available in the read buffer.
@return The number of bytes available in the read buffer
*/
TInt CBulkOnlyTransportUsbcScLdd::BytesAvailable()
{
// Intentionally Left Blank Do Nothing
return 0;
}
void CBulkOnlyTransportUsbcScLdd::StallEndpointAndWaitForClear()
{
__FNLOG("CBulkOnlyTransportUsbcScLdd::StallEndpointAndWaitForClear");
// Now stall this endpoint
__PRINT1(_L("Stalling endpoint %d"), iInEndpoint);
TInt r = iLdd.HaltEndpoint(iInEndpoint);
if (r != KErrNone)
{
__PRINT2(_L("Error: stalling ep %d failed: %d"), iInEndpoint, r);
}
TEndpointState ep_state;
TInt i = 0;
do
{
// Wait for 10ms before checking the ep status
User::After(10000);
iLdd.EndpointStatus(iInEndpoint, ep_state);
if (++i >= 550)
{
// 5.5 secs should be enough (see 9.2.6.1 Request Processing Timing)
__PRINT1(_L("Error: Checked for ep %d de-stall for 5.5s - giving up now"), iInEndpoint);
// We can now only hope for a Reset Recovery
return;
}
} while ((ep_state == EEndpointStateStalled) && iStarted);
__PRINT2(_L("Checked for ep %d de-stall: %d time(s)"), iInEndpoint, i);
}
/**
Read CBW data from the host and decode it.
*/
void CBulkOnlyTransportUsbcScLdd::ReadCBW()
{
__FNLOG("CBulkOnlyTransportUsbcScLdd::ReadCBW");
if (IsActive())
{
__PRINT(_L("Still active\n"));
__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
return;
}
TInt r = KErrNone;
do
{
r = ReadUsb();
if ((r == KErrCompletion) && (iSCReadSize == KCbwLength))
{
iCurrentState = EWaitForCBW;
iStatus = KErrNone;
DecodeCBW();
iSCReadSize = 0;
}
else if (r == KErrNone)
{
iCurrentState = EWaitForCBW;
SetActive();
}
else if ((r == KErrCompletion) && (iSCReadSize != KCbwLength))
{
ExpireData(iSCReadData);
}
}while ((r == KErrCompletion) && (!IsActive()));
}
void CBulkOnlyTransportUsbcScLdd::ExpireData(TAny* aAddress)
{
if (aAddress)
{
iSCReadEndpointBuf.Expire(aAddress);
}
else
{
iSCReadEndpointBuf.Expire();
}
}
void CBulkOnlyTransportUsbcScLdd::ProcessCbwEvent()
{
ReadCBW();
}
/**
Request data form the host for the protocol
@param aLength amount of data (in bytes) to be received from the host
*/
void CBulkOnlyTransportUsbcScLdd::ReadData(TUint /*aLength*/)
{
__FNLOG("CBulkOnlyTransportUsbcScLdd::ReadData");
if (IsActive())
{
__PRINT(_L("Still active\n"));
__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
return;
}
TInt r = KErrNone;
do
{
r = ReadUsb();
iCurrentState = EReadingData;
if (r == KErrCompletion)
{
iReadBufPtr.Set((TUint8*) iSCReadData, iSCReadSize, iSCReadSize);
iStatus = KErrNone;
ProcessDataFromHost();
iSCReadSize = 0;
}
else if (r == KErrNone)
{
iSCReadSize = 0;
SetActive();
}
}while ((r == KErrCompletion) && (!IsActive()));
}
void CBulkOnlyTransportUsbcScLdd::ProcessDataFromHost()
{
TInt ret = KErrNone;
{
if (iReadSetUp)
{
ret = iProtocol->ReadComplete(KErrNone);
}
#ifndef MSDC_MULTITHREADED
ExpireData(iSCReadData);
#endif
TUint deviceDataLength = iSCReadSize; // What was written to the disk // static_cast<TUint>(iReadBuf.Length());
if(ret == KErrCompletion)
{
// The protocol has indicated with KErrCompletion that sufficient
// data is available in the buffer to process the transfer immediately.
//iDataResidue is initially set to host data length as we do not know how much data is there in the 'LDD transfer'.
//After a TakeBuffer call, iSCReadSize in updated and set to deviceDataLength
iDataResidue -= deviceDataLength;
}
else
{
iDataResidue -= deviceDataLength;
// The protocol has indicated that transfer is
// complete, so send the CSW response to the host.
iReadSetUp = EFalse;
if (ret != KErrNone)
{
iCmdStatus = ECommandFailed;
}
if (iDataResidue)
{
__PRINT(_L("Discarding residue"));
// we have to read as much data as available that host PC sends;
// otherwise, bulk-out endpoint will need to keep sending NAK back.
ReadAndDiscardData(iDataResidue);
}
SendCSW(iCbwTag, iDataResidue, iCmdStatus);
}
}
}
void CBulkOnlyTransportUsbcScLdd::WriteUsb(TRequestStatus& aStatus, TPtrC8& aDes, TUint aLength, TBool aZlpRequired)
{
TUint aOffset = (TUint) aDes.Ptr() - (TUint) iChunk->Base();
iSCWriteEndpointBuf.WriteBuffer(aOffset, aLength, aZlpRequired, aStatus);
}
void CBulkOnlyTransportUsbcScLdd::SetCbwPtr()
{
iCbwBufPtr.Set((TUint8*)iSCReadData, iSCReadSize);
}
TPtr8& CBulkOnlyTransportUsbcScLdd::SetCommandBufPtr(TUint aLength)
{
TPtr8 writeBuf((TUint8*) iDataPtr, aLength);
iCommandBufPtr.Set(writeBuf);
return iCommandBufPtr;
}
void CBulkOnlyTransportUsbcScLdd::SetReadDataBufPtr(TUint /*aLength*/)
{
// Do nothing for now
}
TPtr8& CBulkOnlyTransportUsbcScLdd::SetDataBufPtr()
{
TPtr8 writeBuf((TUint8*) iDataPtr, iInBufferLength);
iDataBufPtr.Set(writeBuf);
return iDataBufPtr;
}
void CBulkOnlyTransportUsbcScLdd::SetPaddingBufPtr(TUint aLength)
{
TPtr8 writeBuf((TUint8*) iDataPtr, aLength, aLength);
iPaddingBufPtr.Set(writeBuf);
}
void CBulkOnlyTransportUsbcScLdd::SetCswBufPtr(TUint aLength)
{
TPtr8 writeBuf((TUint8*) iDataPtr, aLength, aLength);
iCswBufPtr.Set(writeBuf);
}
void CBulkOnlyTransportUsbcScLdd::ProcessReadingDataEvent()
{
ReadData();
}
TInt CBulkOnlyTransportUsbcScLdd::ReadUsb(TUint /*aLength*/)
{
__FNLOG("CBulkOnlyTransportUsbcScLdd::ReadUSB");
return iSCReadEndpointBuf.TakeBuffer(iSCReadData,iSCReadSize,iReadZlp,iStatus);
}
void CBulkOnlyTransportUsbcScLdd::DiscardData(TUint aLength)
{
TUint c = 0;
TRequestStatus status;
TInt r = KErrNone;
while (c < aLength)
{
iSCReadSize = 0;
status = KErrNone;
r = iSCReadEndpointBuf.TakeBuffer(iSCReadData,iSCReadSize,iReadZlp,status);
c += iSCReadSize;
if (r == KErrNone)
User::WaitForRequest(status);
if (r == KErrCompletion)
{
iSCReadEndpointBuf.Expire();
}
iSCReadSize = 0;
}
}
void CBulkOnlyTransportUsbcScLdd::WriteToClient(TUint aLength)
{
TUint c = 0;
TRequestStatus status;
TInt r = KErrNone;
while (c < aLength)
{
iSCReadSize = 0;
status = KErrNone;
r = iSCReadEndpointBuf.TakeBuffer(iSCReadData,iSCReadSize,iReadZlp,status);
c += iSCReadSize;
iProtocol->ReadComplete(KErrGeneral);
if (r == KErrNone)
User::WaitForRequest(status);
if (r == KErrCompletion)
{
iSCReadEndpointBuf.Expire();
}
iSCReadSize = 0;
}
}
#ifdef MSDC_MULTITHREADED
void CBulkOnlyTransportUsbcScLdd::GetBufferPointers(TPtr8& aDes1, TPtr8& aDes2)
{
//for DB
TUint length = (TUint) (iInBufferLength - KCswBufferSize) / 2;
TUint8* start = (TUint8*) (iDataPtr) + KCswBufferSize ; // 'first' buffer
aDes1.Set(start, length, length);
start = (TUint8*) (iDataPtr) + KCswBufferSize + length; // 'second' buffer
aDes2.Set(start, length, length);
}
#endif
void CBulkOnlyTransportUsbcScLdd::Activate(TRequestStatus& aStatus, TUint& aDeviceState)
{
iLdd.AlternateDeviceStatusNotify(aStatus, aDeviceState);
}
void CBulkOnlyTransportUsbcScLdd::Cancel()
{
iLdd.AlternateDeviceStatusNotifyCancel();
}