0
|
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 |
}
|