kerneltest/e32test/usbho/t_usbdi/src/endpointwriter.cpp
changeset 0 a41df078684a
child 253 d37db4dcc88d
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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 	}