1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/usbho/t_usbdi/src/endpointwriter.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,322 @@
1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// @file endpointwriter.cpp
1.18 +// @internalComponent
1.19 +//
1.20 +//
1.21 +
1.22 +#include <e32base.h>
1.23 +#include <e32base_private.h>
1.24 +#include <d32usbc.h>
1.25 +#include "endpointwriter.h"
1.26 +#include "testdebug.h"
1.27 +
1.28 +namespace NUnitTesting_USBDI
1.29 + {
1.30 +const TUint KMaxTransferBuffer = 0x1000;
1.31 +
1.32 +
1.33 +CEndpointWriter::CEndpointWriter(RDevUsbcClient& aClientDriver,TEndpointNumber aEndpoint)
1.34 +: CActive(EPriorityStandard),
1.35 + iClientDriver(aClientDriver),
1.36 + iEndpoint(aEndpoint),
1.37 + iBufPtr(NULL,0)
1.38 + {
1.39 + CActiveScheduler::Add(this);
1.40 + }
1.41 +
1.42 +
1.43 +CEndpointWriter::~CEndpointWriter()
1.44 + {
1.45 + LOG_FUNC
1.46 +
1.47 + Cancel();
1.48 + if(iBuffer)
1.49 + {
1.50 + RDebug::Printf("Freeing %d bytes", iBuffer->Size());
1.51 + }
1.52 + delete iBuffer;
1.53 + }
1.54 +
1.55 +
1.56 +void CEndpointWriter::DoCancel()
1.57 + {
1.58 + LOG_FUNC
1.59 +
1.60 + // Cancel the write to the endpoint
1.61 +
1.62 + iClientDriver.WriteCancel(iEndpoint);
1.63 + }
1.64 +
1.65 +
1.66 +TUint CEndpointWriter::NumBytesWrittenSoFar()
1.67 + {
1.68 + return iNumBytesWritten;
1.69 + }
1.70 +
1.71 +void CEndpointWriter::RunL()
1.72 + {
1.73 + LOG_FUNC
1.74 +
1.75 + TInt completionCode(iStatus.Int());
1.76 + RDebug::Printf("Write completed, err=%d",completionCode);
1.77 +
1.78 + iNumBytesWritten += iNumBytesOnCurrentWrite; // all zero if not a repeated write
1.79 + if(iNumBytesWritten < iTotalNumBytes)
1.80 + //This conditional will not be entered for non-repeat cases because then
1.81 + //'iNumBytesWritten' and 'iTotalNumBytes' will both be zero.
1.82 + {
1.83 + TUint totalNumBytesStillToWrite = iTotalNumBytes - iNumBytesWritten;
1.84 +
1.85 + //NB iNumBytesOnCurrentWrite should remain at the requested 'bytes per Write' value until the last iteration
1.86 + iNumBytesOnCurrentWrite = totalNumBytesStillToWrite <= iNumBytesOnCurrentWrite ? totalNumBytesStillToWrite : iNumBytesOnCurrentWrite;
1.87 +
1.88 + //Only add a ZLP, if requested and if the last 'Write'
1.89 + TBool useUsb = totalNumBytesStillToWrite <= iNumBytesOnCurrentWrite ? iUseZLP : EFalse;
1.90 + TPtrC8 writeDesc = iBufPtr.Mid(iNumBytesWritten%iDataPatternLength, iNumBytesOnCurrentWrite);
1.91 + RDebug::Printf("Total Bytes To Write = %d, Bytes Still To Write = %d, Bytes Written = %d, Bytes on Current 'Write'", iTotalNumBytes, totalNumBytesStillToWrite, iNumBytesWritten, iNumBytesOnCurrentWrite);
1.92 +
1.93 + RDebug::Printf("\n");
1.94 + RDebug::Printf("First 256 bytes (or all) of data to write");
1.95 + RDebug::RawPrint(writeDesc);
1.96 + RDebug::Printf("\n");
1.97 +
1.98 +
1.99 + Write(writeDesc, useUsb, EFalse);
1.100 + }
1.101 + else
1.102 + {
1.103 + if(iBuffer!=NULL)
1.104 + {
1.105 + RDebug::Printf("Freeing %d bytes", iBuffer->Size());
1.106 + }
1.107 + else
1.108 + {
1.109 + RDebug::Printf("iBuffer is NULL");
1.110 + }
1.111 + if(iTotalNumBytes != 0)
1.112 + //if a repeated write
1.113 + {
1.114 + RDebug::Printf("Total Bytes = %d, Bytes Written = %d", iTotalNumBytes, iNumBytesWritten);
1.115 + }
1.116 + delete iBuffer;
1.117 + iBuffer = 0;
1.118 + iNumBytesOnCurrentWrite = 0;
1.119 + iNumBytesWritten = 0;
1.120 + iTotalNumBytes = 0;
1.121 + iDataPatternLength = 0;
1.122 + iUseZLP = EFalse;
1.123 + }
1.124 + }
1.125 +
1.126 +
1.127 +TInt CEndpointWriter::RunError(TInt aError)
1.128 + {
1.129 + LOG_FUNC
1.130 +
1.131 + aError = KErrNone;
1.132 + return aError;
1.133 + }
1.134 +
1.135 +
1.136 +void CEndpointWriter::Write(const TDesC8& aData, TBool aUseZLP, TBool aCreateBuffer)
1.137 + {
1.138 + LOG_FUNC
1.139 +
1.140 + if(aCreateBuffer == EFalse)
1.141 + {
1.142 + RDebug::Printf("Use ZLP %d", aUseZLP?1:0);
1.143 + iClientDriver.Write(iStatus,iEndpoint,aData,aData.Length(),aUseZLP);
1.144 + SetActive();
1.145 + return;
1.146 + }
1.147 +
1.148 +
1.149 + //Copy aData to this object's buffer
1.150 + //'aData' will go out of scope before the USB driver 'Write' completes
1.151 + delete iBuffer;
1.152 + iBuffer = NULL;
1.153 + iBuffer = HBufC8::NewL(aData.Length());
1.154 + iBufPtr.Set(iBuffer->Des());
1.155 + iBufPtr.Copy(aData);
1.156 +
1.157 + // Write the data to the host through the endpoint (host opened pipe)
1.158 + RDebug::Printf("Write Length = %d", iBufPtr.Length());
1.159 + RDebug::RawPrint(iBufPtr);
1.160 + RDebug::Printf("\n");
1.161 + RDebug::Printf("Use ZLP %d", aUseZLP?1:0);
1.162 + iClientDriver.Write(iStatus,iEndpoint,iBufPtr,iBufPtr.Length(),aUseZLP);
1.163 + SetActive();
1.164 + }
1.165 +
1.166 +TInt CEndpointWriter::WriteSynchronous(const TDesC8& aData, TBool aUseZLP)
1.167 + {
1.168 + LOG_FUNC
1.169 +
1.170 + TRequestStatus status = KRequestPending;
1.171 + RDebug::Printf("Write Length = %d", aData.Length());
1.172 + RDebug::RawPrint(aData);
1.173 + RDebug::Printf("\n");
1.174 + RDebug::Printf("Use ZLP %d", aUseZLP?1:0);
1.175 + iClientDriver.Write(status,iEndpoint,aData,aData.Length(),aUseZLP);
1.176 + User::WaitForRequest(status);
1.177 + RDebug::Printf("Write has completed with error %d", status.Int());
1.178 + return status.Int();
1.179 + }
1.180 +
1.181 +void CEndpointWriter::WriteSynchronousUsingPatternL(const TDesC8& aData, const TUint aNumBytes, const TBool aUseZLP)
1.182 + {
1.183 + LOG_FUNC
1.184 +
1.185 + TBool useZLP = EFalse; //only want this if you are making the last call to client Write (=WriteSynchronous)
1.186 + if(aNumBytes <= aData.Length())
1.187 + //Don't need to allocate a buffer and copy to it - write will be done synchronously
1.188 + {
1.189 + if(aUseZLP)
1.190 + {
1.191 + useZLP = ETrue;
1.192 + }
1.193 + WriteSynchronous(aData.Left(aNumBytes),useZLP);
1.194 + }
1.195 +
1.196 + else if(aNumBytes <= KMaxTransferBuffer)
1.197 + //Create a buffer based on the data pattern sent and use just one 'Synchronous Write'
1.198 + {
1.199 + if(aUseZLP)
1.200 + {
1.201 + useZLP = ETrue;
1.202 + }
1.203 + TInt repeats = aNumBytes/aData.Length();
1.204 + TInt extraBytes = aNumBytes%aData.Length();
1.205 + delete iBuffer;
1.206 + iBuffer = NULL;
1.207 + iBuffer = HBufC8::NewL(aNumBytes);
1.208 + TPtr8 ptr = iBuffer->Des();
1.209 + ptr.Zero();
1.210 + for(TUint i =0; i<repeats; i++)
1.211 + {
1.212 + ptr.Append(aData);
1.213 + }
1.214 + if(extraBytes)
1.215 + {
1.216 + ptr.Append(aData.Left(extraBytes));
1.217 + }
1.218 + WriteSynchronous(ptr, useZLP);
1.219 + delete iBuffer;
1.220 + }
1.221 +
1.222 + else
1.223 + //Create a buffer based on the data pattern sent and use SEVERAL 'Synchronous Write's
1.224 + {
1.225 + //Write data in reasonably sized chunks
1.226 + //Create buffer using max whole number of data patterns
1.227 + TInt repeats = KMaxTransferBuffer/aData.Length();
1.228 + CreateBigBuffer(aData, repeats);
1.229 +
1.230 + //Now write data
1.231 + repeats = aNumBytes/iBufPtr.Length(); //re-use 'repeats'
1.232 + TInt endBytes = aNumBytes%iBufPtr.Length();
1.233 + for(TInt i=0;i<repeats;i++)
1.234 + {
1.235 + if(i==(repeats-1)&&endBytes==0)
1.236 + //last loop - request ZLP if appropriate
1.237 + {
1.238 + WriteSynchronous(*iBuffer, aUseZLP); //if last 'Write'
1.239 + }
1.240 + else
1.241 + {
1.242 + WriteSynchronous(*iBuffer, EFalse);
1.243 + }
1.244 + }
1.245 + if(endBytes)
1.246 + {
1.247 + WriteSynchronous(iBufPtr.Left(endBytes), aUseZLP); //if last 'Write'
1.248 + }
1.249 + }
1.250 + delete iBuffer;
1.251 + iBuffer = 0;
1.252 + }
1.253 +
1.254 +void CEndpointWriter::WriteSynchronousUsingPatternL(const TDesC8& aData, const TUint aNumBytes)
1.255 + {
1.256 + WriteSynchronousUsingPatternL(aData, aNumBytes, ETrue);
1.257 + }
1.258 +
1.259 +void CEndpointWriter::WriteSynchronousUsingPatternAndHaltL(const TDesC8& aData, const TUint aNumBytes)
1.260 + {
1.261 + LOG_FUNC
1.262 + WriteSynchronousUsingPatternL(aData, aNumBytes, EFalse);
1.263 + iClientDriver.HaltEndpoint(iEndpoint);
1.264 + }
1.265 +
1.266 +void CEndpointWriter::WriteUsingPatternL(const TDesC8& aData, const TUint aNumBytes, const TBool aUseZLP)
1.267 + {
1.268 + LOG_FUNC
1.269 +
1.270 + RDebug::Printf("Allocating %d bytes", aNumBytes);
1.271 + delete iBuffer;
1.272 + iBuffer = NULL;
1.273 + iBuffer = HBufC8::NewL(aNumBytes);
1.274 + RDebug::Printf("Allocated %d bytes", aNumBytes);
1.275 + iBufPtr.Set(iBuffer->Des());
1.276 + iBufPtr.Zero();
1.277 + TInt repeats = aNumBytes/aData.Length();
1.278 + for(TUint i =0; i<repeats; i++)
1.279 + {
1.280 + iBufPtr.Append(aData);
1.281 + }
1.282 + if(TInt extraBytes = aNumBytes%aData.Length())
1.283 + {
1.284 + iBufPtr.Append(aData.Left(extraBytes));
1.285 + }
1.286 + Write(*iBuffer, aUseZLP, EFalse);
1.287 + }
1.288 +
1.289 +void CEndpointWriter::WriteInPartsUsingPatternL(const TDesC8& aData, const TUint aNumBytesPerWrite, TUint aTotalNumBytes, const TBool aUseZLP)
1.290 + {
1.291 + LOG_FUNC
1.292 +
1.293 + iUseZLP = aUseZLP;
1.294 + TInt repeats = aNumBytesPerWrite/aData.Length() + 1;
1.295 + repeats *= 2;
1.296 + CreateBigBuffer(aData, repeats);
1.297 + iDataPatternLength = aData.Length();
1.298 + iTotalNumBytes = aTotalNumBytes;
1.299 + iNumBytesOnCurrentWrite = aNumBytesPerWrite;
1.300 + iNumBytesWritten = 0;
1.301 + Write(iBufPtr.Mid(iNumBytesWritten%iDataPatternLength, iNumBytesOnCurrentWrite), EFalse, EFalse); //this is not the first 'Write' so do not use a ZLP
1.302 + RDebug::Printf("Write %d bytes",iNumBytesOnCurrentWrite);
1.303 + RDebug::Printf("Total Bytes = %d, Data Pattern Length = %d", iTotalNumBytes, iDataPatternLength);
1.304 + }
1.305 +
1.306 +void CEndpointWriter::CreateBigBuffer(const TDesC8& aData, const TUint aRepeats)
1.307 +/*
1.308 +Create a payload buffer a section of which can always be used for each cyclic 'Write'.
1.309 +*/
1.310 + {
1.311 + //We require a buffer containing a sufficient number of repeats of the data pattern
1.312 + //to allow us simply to use a section of it for any individual 'Write' payload.
1.313 + delete iBuffer;
1.314 + iBuffer = NULL;
1.315 + RDebug::Printf("Data buffer is using %d repeats of string starting...\n\"%S\"", aRepeats, &aData);
1.316 + iBuffer = HBufC8::NewL(aRepeats*aData.Length());
1.317 + iBufPtr.Set(iBuffer->Des());
1.318 + iBufPtr.Zero();
1.319 + for(TUint i =0; i<aRepeats; i++)
1.320 + {
1.321 + iBufPtr.Append(aData);
1.322 + }
1.323 + }
1.324 +
1.325 + }