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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // @file endpointwriter.cpp
20 #include <e32base_private.h>
22 #include "endpointwriter.h"
23 #include "testdebug.h"
25 namespace NUnitTesting_USBDI
27 const TUint KMaxTransferBuffer = 0x1000;
30 CEndpointWriter::CEndpointWriter(RDevUsbcClient& aClientDriver,TEndpointNumber aEndpoint)
31 : CActive(EPriorityStandard),
32 iClientDriver(aClientDriver),
36 CActiveScheduler::Add(this);
40 CEndpointWriter::~CEndpointWriter()
47 RDebug::Printf("Freeing %d bytes", iBuffer->Size());
53 void CEndpointWriter::DoCancel()
57 // Cancel the write to the endpoint
59 iClientDriver.WriteCancel(iEndpoint);
63 TUint CEndpointWriter::NumBytesWrittenSoFar()
65 return iNumBytesWritten;
68 void CEndpointWriter::RunL()
72 TInt completionCode(iStatus.Int());
73 RDebug::Printf("Write completed, err=%d",completionCode);
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.
80 TUint totalNumBytesStillToWrite = iTotalNumBytes - iNumBytesWritten;
82 //NB iNumBytesOnCurrentWrite should remain at the requested 'bytes per Write' value until the last iteration
83 iNumBytesOnCurrentWrite = totalNumBytesStillToWrite <= iNumBytesOnCurrentWrite ? totalNumBytesStillToWrite : iNumBytesOnCurrentWrite;
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);
91 RDebug::Printf("First 256 bytes (or all) of data to write");
92 RDebug::RawPrint(writeDesc);
96 Write(writeDesc, useUsb, EFalse);
102 RDebug::Printf("Freeing %d bytes", iBuffer->Size());
106 RDebug::Printf("iBuffer is NULL");
108 if(iTotalNumBytes != 0)
109 //if a repeated write
111 RDebug::Printf("Total Bytes = %d, Bytes Written = %d", iTotalNumBytes, iNumBytesWritten);
115 iNumBytesOnCurrentWrite = 0;
116 iNumBytesWritten = 0;
118 iDataPatternLength = 0;
124 TInt CEndpointWriter::RunError(TInt aError)
133 void CEndpointWriter::Write(const TDesC8& aData, TBool aUseZLP, TBool aCreateBuffer)
137 if(aCreateBuffer == EFalse)
139 RDebug::Printf("Use ZLP %d", aUseZLP?1:0);
140 iClientDriver.Write(iStatus,iEndpoint,aData,aData.Length(),aUseZLP);
146 //Copy aData to this object's buffer
147 //'aData' will go out of scope before the USB driver 'Write' completes
150 iBuffer = HBufC8::NewL(aData.Length());
151 iBufPtr.Set(iBuffer->Des());
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);
163 TInt CEndpointWriter::WriteSynchronous(const TDesC8& aData, TBool aUseZLP)
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());
178 void CEndpointWriter::WriteSynchronousUsingPatternL(const TDesC8& aData, const TUint aNumBytes, const TBool aUseZLP)
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
190 WriteSynchronous(aData.Left(aNumBytes),useZLP);
193 else if(aNumBytes <= KMaxTransferBuffer)
194 //Create a buffer based on the data pattern sent and use just one 'Synchronous Write'
200 TInt repeats = aNumBytes/aData.Length();
201 TInt extraBytes = aNumBytes%aData.Length();
204 iBuffer = HBufC8::NewL(aNumBytes);
205 TPtr8 ptr = iBuffer->Des();
207 for(TUint i =0; i<repeats; i++)
213 ptr.Append(aData.Left(extraBytes));
215 WriteSynchronous(ptr, useZLP);
220 //Create a buffer based on the data pattern sent and use SEVERAL 'Synchronous Write's
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);
228 repeats = aNumBytes/iBufPtr.Length(); //re-use 'repeats'
229 TInt endBytes = aNumBytes%iBufPtr.Length();
230 for(TInt i=0;i<repeats;i++)
232 if(i==(repeats-1)&&endBytes==0)
233 //last loop - request ZLP if appropriate
235 WriteSynchronous(*iBuffer, aUseZLP); //if last 'Write'
239 WriteSynchronous(*iBuffer, EFalse);
244 WriteSynchronous(iBufPtr.Left(endBytes), aUseZLP); //if last 'Write'
251 void CEndpointWriter::WriteSynchronousUsingPatternL(const TDesC8& aData, const TUint aNumBytes)
253 WriteSynchronousUsingPatternL(aData, aNumBytes, ETrue);
256 void CEndpointWriter::WriteSynchronousUsingPatternAndHaltL(const TDesC8& aData, const TUint aNumBytes)
259 WriteSynchronousUsingPatternL(aData, aNumBytes, EFalse);
260 iClientDriver.HaltEndpoint(iEndpoint);
263 void CEndpointWriter::WriteUsingPatternL(const TDesC8& aData, const TUint aNumBytes, const TBool aUseZLP)
267 RDebug::Printf("Allocating %d bytes", aNumBytes);
270 iBuffer = HBufC8::NewL(aNumBytes);
271 RDebug::Printf("Allocated %d bytes", aNumBytes);
272 iBufPtr.Set(iBuffer->Des());
274 TInt repeats = aNumBytes/aData.Length();
275 for(TUint i =0; i<repeats; i++)
277 iBufPtr.Append(aData);
279 if(TInt extraBytes = aNumBytes%aData.Length())
281 iBufPtr.Append(aData.Left(extraBytes));
283 Write(*iBuffer, aUseZLP, EFalse);
286 void CEndpointWriter::WriteInPartsUsingPatternL(const TDesC8& aData, const TUint aNumBytesPerWrite, TUint aTotalNumBytes, const TBool aUseZLP)
291 TInt repeats = aNumBytesPerWrite/aData.Length() + 1;
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);
303 void CEndpointWriter::CreateBigBuffer(const TDesC8& aData, const TUint aRepeats)
305 Create a payload buffer a section of which can always be used for each cyclic 'Write'.
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.
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());
316 for(TUint i =0; i<aRepeats; i++)
318 iBufPtr.Append(aData);