os/kernelhwsrv/kerneltest/e32test/usbho/t_usbdi/src/endpointwriter.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/usbho/t_usbdi/src/endpointwriter.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,322 @@
     1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// @file endpointwriter.cpp
    1.18 +// @internalComponent
    1.19 +// 
    1.20 +//
    1.21 +
    1.22 +#include <e32base.h>
    1.23 +#include <e32base_private.h>
    1.24 +#include <d32usbc.h>
    1.25 +#include "endpointwriter.h"
    1.26 +#include "testdebug.h"
    1.27 +
    1.28 +namespace NUnitTesting_USBDI
    1.29 +	{
    1.30 +const TUint KMaxTransferBuffer = 0x1000;
    1.31 +
    1.32 +
    1.33 +CEndpointWriter::CEndpointWriter(RDevUsbcClient& aClientDriver,TEndpointNumber aEndpoint)
    1.34 +:	CActive(EPriorityStandard),
    1.35 +	iClientDriver(aClientDriver),
    1.36 +	iEndpoint(aEndpoint),
    1.37 +	iBufPtr(NULL,0)
    1.38 +	{
    1.39 +	CActiveScheduler::Add(this);
    1.40 +	}
    1.41 +	
    1.42 +					
    1.43 +CEndpointWriter::~CEndpointWriter()
    1.44 +	{
    1.45 +	LOG_FUNC
    1.46 +	
    1.47 +	Cancel();
    1.48 +	if(iBuffer)
    1.49 +		{
    1.50 +		RDebug::Printf("Freeing %d bytes", iBuffer->Size());
    1.51 +		}
    1.52 +	delete iBuffer;
    1.53 +	}
    1.54 +
    1.55 +
    1.56 +void CEndpointWriter::DoCancel()
    1.57 +	{
    1.58 +	LOG_FUNC
    1.59 +	
    1.60 +	// Cancel the write to the endpoint
    1.61 +	
    1.62 +	iClientDriver.WriteCancel(iEndpoint);
    1.63 +	}
    1.64 +	
    1.65 +	
    1.66 +TUint CEndpointWriter::NumBytesWrittenSoFar()
    1.67 +	{
    1.68 +	return iNumBytesWritten;
    1.69 +	}
    1.70 +
    1.71 +void CEndpointWriter::RunL()
    1.72 +	{
    1.73 +	LOG_FUNC
    1.74 +	
    1.75 +	TInt completionCode(iStatus.Int());
    1.76 +	RDebug::Printf("Write completed, err=%d",completionCode);
    1.77 +	
    1.78 +	iNumBytesWritten += iNumBytesOnCurrentWrite; // all zero if not a repeated write
    1.79 +	if(iNumBytesWritten < iTotalNumBytes)
    1.80 +		//This conditional will not be entered for non-repeat cases because then 
    1.81 +		//'iNumBytesWritten' and 'iTotalNumBytes' will both be zero.
    1.82 +		{
    1.83 +		TUint totalNumBytesStillToWrite = iTotalNumBytes - iNumBytesWritten;
    1.84 +
    1.85 +		//NB iNumBytesOnCurrentWrite should remain at the requested 'bytes per Write' value until the last iteration
    1.86 +		iNumBytesOnCurrentWrite = totalNumBytesStillToWrite <= iNumBytesOnCurrentWrite ? totalNumBytesStillToWrite : iNumBytesOnCurrentWrite;
    1.87 +
    1.88 +		//Only add a ZLP, if requested and if the last 'Write'
    1.89 +		TBool useUsb = totalNumBytesStillToWrite <= iNumBytesOnCurrentWrite ? iUseZLP : EFalse;
    1.90 +		TPtrC8 writeDesc = iBufPtr.Mid(iNumBytesWritten%iDataPatternLength, iNumBytesOnCurrentWrite);
    1.91 +		RDebug::Printf("Total Bytes To Write = %d, Bytes Still To Write = %d, Bytes Written = %d, Bytes on Current 'Write'", iTotalNumBytes, totalNumBytesStillToWrite, iNumBytesWritten, iNumBytesOnCurrentWrite);
    1.92 +		 
    1.93 +		RDebug::Printf("\n");
    1.94 +		RDebug::Printf("First 256 bytes (or all) of data to write");
    1.95 +		RDebug::RawPrint(writeDesc);
    1.96 +		RDebug::Printf("\n");
    1.97 +		
    1.98 +		
    1.99 +		Write(writeDesc, useUsb, EFalse);
   1.100 +		}
   1.101 +	else
   1.102 +		{
   1.103 +		if(iBuffer!=NULL)
   1.104 +			{
   1.105 +			RDebug::Printf("Freeing %d bytes", iBuffer->Size());
   1.106 +			}
   1.107 +		else
   1.108 +			{
   1.109 +			RDebug::Printf("iBuffer is NULL");
   1.110 +			}
   1.111 +		if(iTotalNumBytes != 0)
   1.112 +			//if a repeated write
   1.113 +			{
   1.114 +			RDebug::Printf("Total Bytes = %d, Bytes Written = %d", iTotalNumBytes, iNumBytesWritten);
   1.115 +			}
   1.116 +		delete iBuffer;
   1.117 +		iBuffer = 0;
   1.118 +		iNumBytesOnCurrentWrite = 0;
   1.119 +		iNumBytesWritten = 0;
   1.120 +		iTotalNumBytes = 0;
   1.121 +		iDataPatternLength = 0;
   1.122 +		iUseZLP = EFalse;
   1.123 +		}
   1.124 +	}
   1.125 +
   1.126 +
   1.127 +TInt CEndpointWriter::RunError(TInt aError)
   1.128 +	{
   1.129 +	LOG_FUNC
   1.130 +	
   1.131 +	aError = KErrNone;
   1.132 +	return aError;
   1.133 +	}
   1.134 +
   1.135 +
   1.136 +void CEndpointWriter::Write(const TDesC8& aData, TBool aUseZLP, TBool aCreateBuffer)
   1.137 +	{
   1.138 +	LOG_FUNC
   1.139 +	
   1.140 +  	if(aCreateBuffer == EFalse)
   1.141 +  		{
   1.142 +  		RDebug::Printf("Use ZLP %d", aUseZLP?1:0);
   1.143 +  		iClientDriver.Write(iStatus,iEndpoint,aData,aData.Length(),aUseZLP);
   1.144 +  		SetActive();
   1.145 + 		return;
   1.146 +  		}
   1.147 +
   1.148 +	
   1.149 +	//Copy aData to this object's buffer
   1.150 +	//'aData' will go out of scope before the USB driver 'Write' completes	
   1.151 +	delete iBuffer;
   1.152 +  	iBuffer = NULL;
   1.153 +	iBuffer = HBufC8::NewL(aData.Length());
   1.154 +	iBufPtr.Set(iBuffer->Des());
   1.155 +	iBufPtr.Copy(aData);
   1.156 +
   1.157 +	// Write the data to the host through the endpoint (host opened pipe)
   1.158 +	RDebug::Printf("Write Length = %d", iBufPtr.Length());
   1.159 +	RDebug::RawPrint(iBufPtr);
   1.160 +	RDebug::Printf("\n");
   1.161 +	RDebug::Printf("Use ZLP %d", aUseZLP?1:0);
   1.162 +	iClientDriver.Write(iStatus,iEndpoint,iBufPtr,iBufPtr.Length(),aUseZLP);
   1.163 +	SetActive();
   1.164 +	}
   1.165 +
   1.166 +TInt CEndpointWriter::WriteSynchronous(const TDesC8& aData, TBool aUseZLP)
   1.167 +	{
   1.168 +	LOG_FUNC
   1.169 +	
   1.170 +	TRequestStatus status = KRequestPending;
   1.171 +	RDebug::Printf("Write Length = %d", aData.Length());
   1.172 +	RDebug::RawPrint(aData);
   1.173 +	RDebug::Printf("\n");
   1.174 +	RDebug::Printf("Use ZLP %d", aUseZLP?1:0);
   1.175 +	iClientDriver.Write(status,iEndpoint,aData,aData.Length(),aUseZLP);
   1.176 +	User::WaitForRequest(status);
   1.177 +	RDebug::Printf("Write has completed with error %d", status.Int());
   1.178 +	return status.Int();
   1.179 +	}
   1.180 +
   1.181 +void CEndpointWriter::WriteSynchronousUsingPatternL(const TDesC8& aData, const TUint aNumBytes, const TBool aUseZLP)
   1.182 +	{
   1.183 +	LOG_FUNC
   1.184 +
   1.185 +	TBool useZLP = EFalse; //only want this if you are making the last call to client Write (=WriteSynchronous)
   1.186 +	if(aNumBytes <= aData.Length())
   1.187 +	//Don't need to allocate a buffer and copy to it - write will be done synchronously
   1.188 +		{
   1.189 +		if(aUseZLP)
   1.190 +			{
   1.191 +			useZLP = ETrue;
   1.192 +			}
   1.193 +		WriteSynchronous(aData.Left(aNumBytes),useZLP);
   1.194 +		}
   1.195 +
   1.196 +	else if(aNumBytes <= KMaxTransferBuffer)
   1.197 +	//Create a buffer based on the data pattern sent and use just one 'Synchronous Write'
   1.198 +		{
   1.199 +		if(aUseZLP)
   1.200 +			{
   1.201 +			useZLP = ETrue;
   1.202 +			}
   1.203 +	  	TInt repeats = aNumBytes/aData.Length();
   1.204 +	  	TInt extraBytes = aNumBytes%aData.Length();
   1.205 +	  	delete iBuffer;
   1.206 +	  	iBuffer = NULL;
   1.207 +	 	iBuffer = HBufC8::NewL(aNumBytes);
   1.208 +	 	TPtr8 ptr = iBuffer->Des();
   1.209 +	 	ptr.Zero();
   1.210 +	  	for(TUint i =0; i<repeats; i++)
   1.211 +	  		{
   1.212 +	  		ptr.Append(aData);
   1.213 +	  		}
   1.214 +	  	if(extraBytes)
   1.215 +	  		{
   1.216 +	  		ptr.Append(aData.Left(extraBytes));
   1.217 +	  		}
   1.218 +	  	WriteSynchronous(ptr, useZLP);
   1.219 +	  	delete iBuffer;
   1.220 +		}
   1.221 +
   1.222 +	else
   1.223 +	//Create a buffer based on the data pattern sent and use SEVERAL 'Synchronous Write's
   1.224 +		{
   1.225 +		//Write data in reasonably sized chunks
   1.226 +		//Create buffer using max whole number of data patterns
   1.227 +	  	TInt repeats = KMaxTransferBuffer/aData.Length();
   1.228 +	  	CreateBigBuffer(aData, repeats);
   1.229 +
   1.230 +		//Now write data
   1.231 +	  	repeats = aNumBytes/iBufPtr.Length(); //re-use 'repeats'
   1.232 +	  	TInt endBytes = aNumBytes%iBufPtr.Length();
   1.233 +	  	for(TInt i=0;i<repeats;i++)
   1.234 +	  		{
   1.235 +			if(i==(repeats-1)&&endBytes==0)
   1.236 +				//last loop - request ZLP if appropriate
   1.237 +				{
   1.238 +				WriteSynchronous(*iBuffer, aUseZLP); //if last 'Write'
   1.239 +				}
   1.240 +			else
   1.241 +				{
   1.242 +				WriteSynchronous(*iBuffer, EFalse);
   1.243 +				}
   1.244 +	  		}
   1.245 +	  	if(endBytes)
   1.246 +	  		{
   1.247 +			WriteSynchronous(iBufPtr.Left(endBytes), aUseZLP); //if last 'Write'
   1.248 +	  		}
   1.249 +		}
   1.250 +	delete iBuffer;
   1.251 +	iBuffer = 0;
   1.252 +	}
   1.253 +
   1.254 +void CEndpointWriter::WriteSynchronousUsingPatternL(const TDesC8& aData, const TUint aNumBytes)
   1.255 +	{
   1.256 +	WriteSynchronousUsingPatternL(aData, aNumBytes, ETrue);
   1.257 +	}
   1.258 +
   1.259 +void CEndpointWriter::WriteSynchronousUsingPatternAndHaltL(const TDesC8& aData, const TUint aNumBytes)
   1.260 +	{
   1.261 +	LOG_FUNC
   1.262 +	WriteSynchronousUsingPatternL(aData, aNumBytes, EFalse);
   1.263 +	iClientDriver.HaltEndpoint(iEndpoint);
   1.264 +	}
   1.265 +
   1.266 +void CEndpointWriter::WriteUsingPatternL(const TDesC8& aData, const TUint aNumBytes, const TBool aUseZLP)
   1.267 +	{
   1.268 +	LOG_FUNC
   1.269 +
   1.270 +	RDebug::Printf("Allocating %d bytes", aNumBytes);
   1.271 +  	delete iBuffer;
   1.272 +  	iBuffer = NULL;
   1.273 +	iBuffer = HBufC8::NewL(aNumBytes);
   1.274 +	RDebug::Printf("Allocated %d bytes", aNumBytes);
   1.275 +	iBufPtr.Set(iBuffer->Des());
   1.276 +	iBufPtr.Zero();
   1.277 +	TInt repeats = aNumBytes/aData.Length();
   1.278 +	for(TUint i =0; i<repeats; i++)
   1.279 +		{
   1.280 +		iBufPtr.Append(aData);
   1.281 +		}
   1.282 +	if(TInt extraBytes = aNumBytes%aData.Length())
   1.283 +		{
   1.284 +		iBufPtr.Append(aData.Left(extraBytes));
   1.285 +		}
   1.286 +	Write(*iBuffer, aUseZLP, EFalse);
   1.287 +	}
   1.288 +
   1.289 +void CEndpointWriter::WriteInPartsUsingPatternL(const TDesC8& aData, const TUint aNumBytesPerWrite, TUint aTotalNumBytes, const TBool aUseZLP)
   1.290 +	{
   1.291 +	LOG_FUNC
   1.292 +
   1.293 +	iUseZLP = aUseZLP;
   1.294 +	TInt repeats = aNumBytesPerWrite/aData.Length() + 1;
   1.295 +	repeats *= 2;
   1.296 +	CreateBigBuffer(aData, repeats);
   1.297 +	iDataPatternLength = aData.Length();
   1.298 +	iTotalNumBytes = aTotalNumBytes;
   1.299 +	iNumBytesOnCurrentWrite = aNumBytesPerWrite;
   1.300 +	iNumBytesWritten = 0;
   1.301 +	Write(iBufPtr.Mid(iNumBytesWritten%iDataPatternLength, iNumBytesOnCurrentWrite), EFalse, EFalse); //this is not the first 'Write' so do not use a ZLP
   1.302 +	RDebug::Printf("Write %d bytes",iNumBytesOnCurrentWrite);
   1.303 +	RDebug::Printf("Total Bytes = %d, Data Pattern Length = %d", iTotalNumBytes, iDataPatternLength);
   1.304 +	}
   1.305 +
   1.306 +void CEndpointWriter::CreateBigBuffer(const TDesC8& aData, const TUint aRepeats)
   1.307 +/*
   1.308 +Create a payload buffer a section of which can always be used for each cyclic 'Write'.
   1.309 +*/
   1.310 +	{
   1.311 +	//We require a buffer containing a sufficient number of repeats of the data pattern
   1.312 +	//to allow us simply to use a section of it for any individual 'Write' payload.
   1.313 + 	delete iBuffer;
   1.314 + 	iBuffer = NULL;
   1.315 + 	RDebug::Printf("Data buffer is using %d repeats of string starting...\n\"%S\"", aRepeats, &aData);
   1.316 + 	iBuffer = HBufC8::NewL(aRepeats*aData.Length());
   1.317 +	iBufPtr.Set(iBuffer->Des());
   1.318 +	iBufPtr.Zero();
   1.319 + 	for(TUint i =0; i<aRepeats; i++)
   1.320 +  		{
   1.321 +  		iBufPtr.Append(aData);
   1.322 +  		}
   1.323 +	}
   1.324 +
   1.325 +	}