os/kernelhwsrv/kerneltest/e32test/usbho/t_usbdi/src/endpointwriter.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // @file endpointwriter.cpp
    15 // @internalComponent
    16 // 
    17 //
    18 
    19 #include <e32base.h>
    20 #include <e32base_private.h>
    21 #include <d32usbc.h>
    22 #include "endpointwriter.h"
    23 #include "testdebug.h"
    24 
    25 namespace NUnitTesting_USBDI
    26 	{
    27 const TUint KMaxTransferBuffer = 0x1000;
    28 
    29 
    30 CEndpointWriter::CEndpointWriter(RDevUsbcClient& aClientDriver,TEndpointNumber aEndpoint)
    31 :	CActive(EPriorityStandard),
    32 	iClientDriver(aClientDriver),
    33 	iEndpoint(aEndpoint),
    34 	iBufPtr(NULL,0)
    35 	{
    36 	CActiveScheduler::Add(this);
    37 	}
    38 	
    39 					
    40 CEndpointWriter::~CEndpointWriter()
    41 	{
    42 	LOG_FUNC
    43 	
    44 	Cancel();
    45 	if(iBuffer)
    46 		{
    47 		RDebug::Printf("Freeing %d bytes", iBuffer->Size());
    48 		}
    49 	delete iBuffer;
    50 	}
    51 
    52 
    53 void CEndpointWriter::DoCancel()
    54 	{
    55 	LOG_FUNC
    56 	
    57 	// Cancel the write to the endpoint
    58 	
    59 	iClientDriver.WriteCancel(iEndpoint);
    60 	}
    61 	
    62 	
    63 TUint CEndpointWriter::NumBytesWrittenSoFar()
    64 	{
    65 	return iNumBytesWritten;
    66 	}
    67 
    68 void CEndpointWriter::RunL()
    69 	{
    70 	LOG_FUNC
    71 	
    72 	TInt completionCode(iStatus.Int());
    73 	RDebug::Printf("Write completed, err=%d",completionCode);
    74 	
    75 	iNumBytesWritten += iNumBytesOnCurrentWrite; // all zero if not a repeated write
    76 	if(iNumBytesWritten < iTotalNumBytes)
    77 		//This conditional will not be entered for non-repeat cases because then 
    78 		//'iNumBytesWritten' and 'iTotalNumBytes' will both be zero.
    79 		{
    80 		TUint totalNumBytesStillToWrite = iTotalNumBytes - iNumBytesWritten;
    81 
    82 		//NB iNumBytesOnCurrentWrite should remain at the requested 'bytes per Write' value until the last iteration
    83 		iNumBytesOnCurrentWrite = totalNumBytesStillToWrite <= iNumBytesOnCurrentWrite ? totalNumBytesStillToWrite : iNumBytesOnCurrentWrite;
    84 
    85 		//Only add a ZLP, if requested and if the last 'Write'
    86 		TBool useUsb = totalNumBytesStillToWrite <= iNumBytesOnCurrentWrite ? iUseZLP : EFalse;
    87 		TPtrC8 writeDesc = iBufPtr.Mid(iNumBytesWritten%iDataPatternLength, iNumBytesOnCurrentWrite);
    88 		RDebug::Printf("Total Bytes To Write = %d, Bytes Still To Write = %d, Bytes Written = %d, Bytes on Current 'Write'", iTotalNumBytes, totalNumBytesStillToWrite, iNumBytesWritten, iNumBytesOnCurrentWrite);
    89 		 
    90 		RDebug::Printf("\n");
    91 		RDebug::Printf("First 256 bytes (or all) of data to write");
    92 		RDebug::RawPrint(writeDesc);
    93 		RDebug::Printf("\n");
    94 		
    95 		
    96 		Write(writeDesc, useUsb, EFalse);
    97 		}
    98 	else
    99 		{
   100 		if(iBuffer!=NULL)
   101 			{
   102 			RDebug::Printf("Freeing %d bytes", iBuffer->Size());
   103 			}
   104 		else
   105 			{
   106 			RDebug::Printf("iBuffer is NULL");
   107 			}
   108 		if(iTotalNumBytes != 0)
   109 			//if a repeated write
   110 			{
   111 			RDebug::Printf("Total Bytes = %d, Bytes Written = %d", iTotalNumBytes, iNumBytesWritten);
   112 			}
   113 		delete iBuffer;
   114 		iBuffer = 0;
   115 		iNumBytesOnCurrentWrite = 0;
   116 		iNumBytesWritten = 0;
   117 		iTotalNumBytes = 0;
   118 		iDataPatternLength = 0;
   119 		iUseZLP = EFalse;
   120 		}
   121 	}
   122 
   123 
   124 TInt CEndpointWriter::RunError(TInt aError)
   125 	{
   126 	LOG_FUNC
   127 	
   128 	aError = KErrNone;
   129 	return aError;
   130 	}
   131 
   132 
   133 void CEndpointWriter::Write(const TDesC8& aData, TBool aUseZLP, TBool aCreateBuffer)
   134 	{
   135 	LOG_FUNC
   136 	
   137   	if(aCreateBuffer == EFalse)
   138   		{
   139   		RDebug::Printf("Use ZLP %d", aUseZLP?1:0);
   140   		iClientDriver.Write(iStatus,iEndpoint,aData,aData.Length(),aUseZLP);
   141   		SetActive();
   142  		return;
   143   		}
   144 
   145 	
   146 	//Copy aData to this object's buffer
   147 	//'aData' will go out of scope before the USB driver 'Write' completes	
   148 	delete iBuffer;
   149   	iBuffer = NULL;
   150 	iBuffer = HBufC8::NewL(aData.Length());
   151 	iBufPtr.Set(iBuffer->Des());
   152 	iBufPtr.Copy(aData);
   153 
   154 	// Write the data to the host through the endpoint (host opened pipe)
   155 	RDebug::Printf("Write Length = %d", iBufPtr.Length());
   156 	RDebug::RawPrint(iBufPtr);
   157 	RDebug::Printf("\n");
   158 	RDebug::Printf("Use ZLP %d", aUseZLP?1:0);
   159 	iClientDriver.Write(iStatus,iEndpoint,iBufPtr,iBufPtr.Length(),aUseZLP);
   160 	SetActive();
   161 	}
   162 
   163 TInt CEndpointWriter::WriteSynchronous(const TDesC8& aData, TBool aUseZLP)
   164 	{
   165 	LOG_FUNC
   166 	
   167 	TRequestStatus status = KRequestPending;
   168 	RDebug::Printf("Write Length = %d", aData.Length());
   169 	RDebug::RawPrint(aData);
   170 	RDebug::Printf("\n");
   171 	RDebug::Printf("Use ZLP %d", aUseZLP?1:0);
   172 	iClientDriver.Write(status,iEndpoint,aData,aData.Length(),aUseZLP);
   173 	User::WaitForRequest(status);
   174 	RDebug::Printf("Write has completed with error %d", status.Int());
   175 	return status.Int();
   176 	}
   177 
   178 void CEndpointWriter::WriteSynchronousUsingPatternL(const TDesC8& aData, const TUint aNumBytes, const TBool aUseZLP)
   179 	{
   180 	LOG_FUNC
   181 
   182 	TBool useZLP = EFalse; //only want this if you are making the last call to client Write (=WriteSynchronous)
   183 	if(aNumBytes <= aData.Length())
   184 	//Don't need to allocate a buffer and copy to it - write will be done synchronously
   185 		{
   186 		if(aUseZLP)
   187 			{
   188 			useZLP = ETrue;
   189 			}
   190 		WriteSynchronous(aData.Left(aNumBytes),useZLP);
   191 		}
   192 
   193 	else if(aNumBytes <= KMaxTransferBuffer)
   194 	//Create a buffer based on the data pattern sent and use just one 'Synchronous Write'
   195 		{
   196 		if(aUseZLP)
   197 			{
   198 			useZLP = ETrue;
   199 			}
   200 	  	TInt repeats = aNumBytes/aData.Length();
   201 	  	TInt extraBytes = aNumBytes%aData.Length();
   202 	  	delete iBuffer;
   203 	  	iBuffer = NULL;
   204 	 	iBuffer = HBufC8::NewL(aNumBytes);
   205 	 	TPtr8 ptr = iBuffer->Des();
   206 	 	ptr.Zero();
   207 	  	for(TUint i =0; i<repeats; i++)
   208 	  		{
   209 	  		ptr.Append(aData);
   210 	  		}
   211 	  	if(extraBytes)
   212 	  		{
   213 	  		ptr.Append(aData.Left(extraBytes));
   214 	  		}
   215 	  	WriteSynchronous(ptr, useZLP);
   216 	  	delete iBuffer;
   217 		}
   218 
   219 	else
   220 	//Create a buffer based on the data pattern sent and use SEVERAL 'Synchronous Write's
   221 		{
   222 		//Write data in reasonably sized chunks
   223 		//Create buffer using max whole number of data patterns
   224 	  	TInt repeats = KMaxTransferBuffer/aData.Length();
   225 	  	CreateBigBuffer(aData, repeats);
   226 
   227 		//Now write data
   228 	  	repeats = aNumBytes/iBufPtr.Length(); //re-use 'repeats'
   229 	  	TInt endBytes = aNumBytes%iBufPtr.Length();
   230 	  	for(TInt i=0;i<repeats;i++)
   231 	  		{
   232 			if(i==(repeats-1)&&endBytes==0)
   233 				//last loop - request ZLP if appropriate
   234 				{
   235 				WriteSynchronous(*iBuffer, aUseZLP); //if last 'Write'
   236 				}
   237 			else
   238 				{
   239 				WriteSynchronous(*iBuffer, EFalse);
   240 				}
   241 	  		}
   242 	  	if(endBytes)
   243 	  		{
   244 			WriteSynchronous(iBufPtr.Left(endBytes), aUseZLP); //if last 'Write'
   245 	  		}
   246 		}
   247 	delete iBuffer;
   248 	iBuffer = 0;
   249 	}
   250 
   251 void CEndpointWriter::WriteSynchronousUsingPatternL(const TDesC8& aData, const TUint aNumBytes)
   252 	{
   253 	WriteSynchronousUsingPatternL(aData, aNumBytes, ETrue);
   254 	}
   255 
   256 void CEndpointWriter::WriteSynchronousUsingPatternAndHaltL(const TDesC8& aData, const TUint aNumBytes)
   257 	{
   258 	LOG_FUNC
   259 	WriteSynchronousUsingPatternL(aData, aNumBytes, EFalse);
   260 	iClientDriver.HaltEndpoint(iEndpoint);
   261 	}
   262 
   263 void CEndpointWriter::WriteUsingPatternL(const TDesC8& aData, const TUint aNumBytes, const TBool aUseZLP)
   264 	{
   265 	LOG_FUNC
   266 
   267 	RDebug::Printf("Allocating %d bytes", aNumBytes);
   268   	delete iBuffer;
   269   	iBuffer = NULL;
   270 	iBuffer = HBufC8::NewL(aNumBytes);
   271 	RDebug::Printf("Allocated %d bytes", aNumBytes);
   272 	iBufPtr.Set(iBuffer->Des());
   273 	iBufPtr.Zero();
   274 	TInt repeats = aNumBytes/aData.Length();
   275 	for(TUint i =0; i<repeats; i++)
   276 		{
   277 		iBufPtr.Append(aData);
   278 		}
   279 	if(TInt extraBytes = aNumBytes%aData.Length())
   280 		{
   281 		iBufPtr.Append(aData.Left(extraBytes));
   282 		}
   283 	Write(*iBuffer, aUseZLP, EFalse);
   284 	}
   285 
   286 void CEndpointWriter::WriteInPartsUsingPatternL(const TDesC8& aData, const TUint aNumBytesPerWrite, TUint aTotalNumBytes, const TBool aUseZLP)
   287 	{
   288 	LOG_FUNC
   289 
   290 	iUseZLP = aUseZLP;
   291 	TInt repeats = aNumBytesPerWrite/aData.Length() + 1;
   292 	repeats *= 2;
   293 	CreateBigBuffer(aData, repeats);
   294 	iDataPatternLength = aData.Length();
   295 	iTotalNumBytes = aTotalNumBytes;
   296 	iNumBytesOnCurrentWrite = aNumBytesPerWrite;
   297 	iNumBytesWritten = 0;
   298 	Write(iBufPtr.Mid(iNumBytesWritten%iDataPatternLength, iNumBytesOnCurrentWrite), EFalse, EFalse); //this is not the first 'Write' so do not use a ZLP
   299 	RDebug::Printf("Write %d bytes",iNumBytesOnCurrentWrite);
   300 	RDebug::Printf("Total Bytes = %d, Data Pattern Length = %d", iTotalNumBytes, iDataPatternLength);
   301 	}
   302 
   303 void CEndpointWriter::CreateBigBuffer(const TDesC8& aData, const TUint aRepeats)
   304 /*
   305 Create a payload buffer a section of which can always be used for each cyclic 'Write'.
   306 */
   307 	{
   308 	//We require a buffer containing a sufficient number of repeats of the data pattern
   309 	//to allow us simply to use a section of it for any individual 'Write' payload.
   310  	delete iBuffer;
   311  	iBuffer = NULL;
   312  	RDebug::Printf("Data buffer is using %d repeats of string starting...\n\"%S\"", aRepeats, &aData);
   313  	iBuffer = HBufC8::NewL(aRepeats*aData.Length());
   314 	iBufPtr.Set(iBuffer->Des());
   315 	iBufPtr.Zero();
   316  	for(TUint i =0; i<aRepeats; i++)
   317   		{
   318   		iBufPtr.Append(aData);
   319   		}
   320 	}
   321 
   322 	}