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) 2007-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 endpointwriter.cpp
// @internalComponent
//
//
#include <e32base.h>
#include <e32base_private.h>
#include <d32usbc.h>
#include "endpointwriter.h"
#include "testdebug.h"
namespace NUnitTesting_USBDI
{
const TUint KMaxTransferBuffer = 0x1000;
CEndpointWriter::CEndpointWriter(RDevUsbcClient& aClientDriver,TEndpointNumber aEndpoint)
: CActive(EPriorityStandard),
iClientDriver(aClientDriver),
iEndpoint(aEndpoint),
iBufPtr(NULL,0)
{
CActiveScheduler::Add(this);
}
CEndpointWriter::~CEndpointWriter()
{
LOG_FUNC
Cancel();
if(iBuffer)
{
RDebug::Printf("Freeing %d bytes", iBuffer->Size());
}
delete iBuffer;
}
void CEndpointWriter::DoCancel()
{
LOG_FUNC
// Cancel the write to the endpoint
iClientDriver.WriteCancel(iEndpoint);
}
TUint CEndpointWriter::NumBytesWrittenSoFar()
{
return iNumBytesWritten;
}
void CEndpointWriter::RunL()
{
LOG_FUNC
TInt completionCode(iStatus.Int());
RDebug::Printf("Write completed, err=%d",completionCode);
iNumBytesWritten += iNumBytesOnCurrentWrite; // all zero if not a repeated write
if(iNumBytesWritten < iTotalNumBytes)
//This conditional will not be entered for non-repeat cases because then
//'iNumBytesWritten' and 'iTotalNumBytes' will both be zero.
{
TUint totalNumBytesStillToWrite = iTotalNumBytes - iNumBytesWritten;
//NB iNumBytesOnCurrentWrite should remain at the requested 'bytes per Write' value until the last iteration
iNumBytesOnCurrentWrite = totalNumBytesStillToWrite <= iNumBytesOnCurrentWrite ? totalNumBytesStillToWrite : iNumBytesOnCurrentWrite;
//Only add a ZLP, if requested and if the last 'Write'
TBool useUsb = totalNumBytesStillToWrite <= iNumBytesOnCurrentWrite ? iUseZLP : EFalse;
TPtrC8 writeDesc = iBufPtr.Mid(iNumBytesWritten%iDataPatternLength, iNumBytesOnCurrentWrite);
RDebug::Printf("Total Bytes To Write = %d, Bytes Still To Write = %d, Bytes Written = %d, Bytes on Current 'Write'", iTotalNumBytes, totalNumBytesStillToWrite, iNumBytesWritten, iNumBytesOnCurrentWrite);
RDebug::Printf("\n");
RDebug::Printf("First 256 bytes (or all) of data to write");
RDebug::RawPrint(writeDesc);
RDebug::Printf("\n");
Write(writeDesc, useUsb, EFalse);
}
else
{
if(iBuffer!=NULL)
{
RDebug::Printf("Freeing %d bytes", iBuffer->Size());
}
else
{
RDebug::Printf("iBuffer is NULL");
}
if(iTotalNumBytes != 0)
//if a repeated write
{
RDebug::Printf("Total Bytes = %d, Bytes Written = %d", iTotalNumBytes, iNumBytesWritten);
}
delete iBuffer;
iBuffer = 0;
iNumBytesOnCurrentWrite = 0;
iNumBytesWritten = 0;
iTotalNumBytes = 0;
iDataPatternLength = 0;
iUseZLP = EFalse;
}
}
TInt CEndpointWriter::RunError(TInt aError)
{
LOG_FUNC
aError = KErrNone;
return aError;
}
void CEndpointWriter::Write(const TDesC8& aData, TBool aUseZLP, TBool aCreateBuffer)
{
LOG_FUNC
if(aCreateBuffer == EFalse)
{
RDebug::Printf("Use ZLP %d", aUseZLP?1:0);
iClientDriver.Write(iStatus,iEndpoint,aData,aData.Length(),aUseZLP);
SetActive();
return;
}
//Copy aData to this object's buffer
//'aData' will go out of scope before the USB driver 'Write' completes
delete iBuffer;
iBuffer = NULL;
iBuffer = HBufC8::NewL(aData.Length());
iBufPtr.Set(iBuffer->Des());
iBufPtr.Copy(aData);
// Write the data to the host through the endpoint (host opened pipe)
RDebug::Printf("Write Length = %d", iBufPtr.Length());
RDebug::RawPrint(iBufPtr);
RDebug::Printf("\n");
RDebug::Printf("Use ZLP %d", aUseZLP?1:0);
iClientDriver.Write(iStatus,iEndpoint,iBufPtr,iBufPtr.Length(),aUseZLP);
SetActive();
}
TInt CEndpointWriter::WriteSynchronous(const TDesC8& aData, TBool aUseZLP)
{
LOG_FUNC
TRequestStatus status = KRequestPending;
RDebug::Printf("Write Length = %d", aData.Length());
RDebug::RawPrint(aData);
RDebug::Printf("\n");
RDebug::Printf("Use ZLP %d", aUseZLP?1:0);
iClientDriver.Write(status,iEndpoint,aData,aData.Length(),aUseZLP);
User::WaitForRequest(status);
RDebug::Printf("Write has completed with error %d", status.Int());
return status.Int();
}
void CEndpointWriter::WriteSynchronousUsingPatternL(const TDesC8& aData, const TUint aNumBytes, const TBool aUseZLP)
{
LOG_FUNC
TBool useZLP = EFalse; //only want this if you are making the last call to client Write (=WriteSynchronous)
if(aNumBytes <= aData.Length())
//Don't need to allocate a buffer and copy to it - write will be done synchronously
{
if(aUseZLP)
{
useZLP = ETrue;
}
WriteSynchronous(aData.Left(aNumBytes),useZLP);
}
else if(aNumBytes <= KMaxTransferBuffer)
//Create a buffer based on the data pattern sent and use just one 'Synchronous Write'
{
if(aUseZLP)
{
useZLP = ETrue;
}
TInt repeats = aNumBytes/aData.Length();
TInt extraBytes = aNumBytes%aData.Length();
delete iBuffer;
iBuffer = NULL;
iBuffer = HBufC8::NewL(aNumBytes);
TPtr8 ptr = iBuffer->Des();
ptr.Zero();
for(TUint i =0; i<repeats; i++)
{
ptr.Append(aData);
}
if(extraBytes)
{
ptr.Append(aData.Left(extraBytes));
}
WriteSynchronous(ptr, useZLP);
delete iBuffer;
}
else
//Create a buffer based on the data pattern sent and use SEVERAL 'Synchronous Write's
{
//Write data in reasonably sized chunks
//Create buffer using max whole number of data patterns
TInt repeats = KMaxTransferBuffer/aData.Length();
CreateBigBuffer(aData, repeats);
//Now write data
repeats = aNumBytes/iBufPtr.Length(); //re-use 'repeats'
TInt endBytes = aNumBytes%iBufPtr.Length();
for(TInt i=0;i<repeats;i++)
{
if(i==(repeats-1)&&endBytes==0)
//last loop - request ZLP if appropriate
{
WriteSynchronous(*iBuffer, aUseZLP); //if last 'Write'
}
else
{
WriteSynchronous(*iBuffer, EFalse);
}
}
if(endBytes)
{
WriteSynchronous(iBufPtr.Left(endBytes), aUseZLP); //if last 'Write'
}
}
delete iBuffer;
iBuffer = 0;
}
void CEndpointWriter::WriteSynchronousUsingPatternL(const TDesC8& aData, const TUint aNumBytes)
{
WriteSynchronousUsingPatternL(aData, aNumBytes, ETrue);
}
void CEndpointWriter::WriteSynchronousUsingPatternAndHaltL(const TDesC8& aData, const TUint aNumBytes)
{
LOG_FUNC
WriteSynchronousUsingPatternL(aData, aNumBytes, EFalse);
iClientDriver.HaltEndpoint(iEndpoint);
}
void CEndpointWriter::WriteUsingPatternL(const TDesC8& aData, const TUint aNumBytes, const TBool aUseZLP)
{
LOG_FUNC
RDebug::Printf("Allocating %d bytes", aNumBytes);
delete iBuffer;
iBuffer = NULL;
iBuffer = HBufC8::NewL(aNumBytes);
RDebug::Printf("Allocated %d bytes", aNumBytes);
iBufPtr.Set(iBuffer->Des());
iBufPtr.Zero();
TInt repeats = aNumBytes/aData.Length();
for(TUint i =0; i<repeats; i++)
{
iBufPtr.Append(aData);
}
if(TInt extraBytes = aNumBytes%aData.Length())
{
iBufPtr.Append(aData.Left(extraBytes));
}
Write(*iBuffer, aUseZLP, EFalse);
}
void CEndpointWriter::WriteInPartsUsingPatternL(const TDesC8& aData, const TUint aNumBytesPerWrite, TUint aTotalNumBytes, const TBool aUseZLP)
{
LOG_FUNC
iUseZLP = aUseZLP;
TInt repeats = aNumBytesPerWrite/aData.Length() + 1;
repeats *= 2;
CreateBigBuffer(aData, repeats);
iDataPatternLength = aData.Length();
iTotalNumBytes = aTotalNumBytes;
iNumBytesOnCurrentWrite = aNumBytesPerWrite;
iNumBytesWritten = 0;
Write(iBufPtr.Mid(iNumBytesWritten%iDataPatternLength, iNumBytesOnCurrentWrite), EFalse, EFalse); //this is not the first 'Write' so do not use a ZLP
RDebug::Printf("Write %d bytes",iNumBytesOnCurrentWrite);
RDebug::Printf("Total Bytes = %d, Data Pattern Length = %d", iTotalNumBytes, iDataPatternLength);
}
void CEndpointWriter::CreateBigBuffer(const TDesC8& aData, const TUint aRepeats)
/*
Create a payload buffer a section of which can always be used for each cyclic 'Write'.
*/
{
//We require a buffer containing a sufficient number of repeats of the data pattern
//to allow us simply to use a section of it for any individual 'Write' payload.
delete iBuffer;
iBuffer = NULL;
RDebug::Printf("Data buffer is using %d repeats of string starting...\n\"%S\"", aRepeats, &aData);
iBuffer = HBufC8::NewL(aRepeats*aData.Length());
iBufPtr.Set(iBuffer->Des());
iBufPtr.Zero();
for(TUint i =0; i<aRepeats; i++)
{
iBufPtr.Append(aData);
}
}
}