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