Update contrib.
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 testinterfacebase.cpp
19 #include "testdevicebase.h"
20 #include "testinterfacebase.h"
21 #include "testinterfacesettingbase.h"
22 #include "testdebug.h"
23 #include "controltransferrequests.h"
24 #include "endpointwriter.h"
27 namespace NUnitTesting_USBDI
31 CInterfaceBase::CInterfaceBase(RUsbTestDevice& aTestDevice,const TDesC16& aName)
32 : iDevice(aTestDevice),
33 iInterfaceName(aName),
34 iCurrentAlternateInterfaceSetting(0) // The default alternate interface setting will be zero when opened
38 CInterfaceBase::~CInterfaceBase()
44 delete iSelectionWatcher;
46 // Release all interfaces
49 // Destroy the endpoint 0 reader
52 // Destroy interface settings
53 iAlternateSettings.ResetAndDestroy();
55 // Close the channel to the driver
56 iClientDriver.Close();
60 void CInterfaceBase::BaseConstructL()
63 // Open channel to driver
64 TInt err(iClientDriver.Open(0));
67 RDebug::Printf("<Error %d> Unable to open a channel to USB client driver",err);
71 // Start the watcher for host selecting alternate interface settings
72 iSelectionWatcher = CAlternateInterfaceSelectionWatcher::NewL(iClientDriver,*this);
75 iStallWatcher = new (ELeave) CEndpointStallWatcher(iClientDriver);
77 // Create the Ep0 reader/writer
78 iEp0Reader = new (ELeave) CControlEndpointReader(iClientDriver,*this);
79 iEp0Writer = new (ELeave) CEndpointWriter(iClientDriver,EEndpoint0);
81 // Hide bus from host while interfaces are being set up
82 iClientDriver.DeviceDisconnectFromHost();
86 void CInterfaceBase::AddInterfaceSettingL(CInterfaceSettingBase* aInterfaceSetting)
90 // Append to the container
91 TInt err(iAlternateSettings.Append(aInterfaceSetting));
94 RDebug::Printf("<Error %d> Unable to add interface setting",err);
98 // Get the current number of alternate interface settings
99 TInt alternateSettingNumber(iAlternateSettings.Count()-1);
101 TUint endpointSettingCount(aInterfaceSetting->iInterfaceInfo().iTotalEndpointsUsed);
103 if(endpointSettingCount > 0)
105 RDebug::Printf("%u endpoint(s) to configure for this interface setting",endpointSettingCount);
107 // Device capabilities
108 TUsbDeviceCaps devCaps;
109 err = iClientDriver.DeviceCaps(devCaps);
112 RDebug::Printf("<Error %d> Unable to retrieve device capabilities",err);
116 // Endpoint capabilities
117 TUsbcEndpointData endpointCaps[KUsbcMaxEndpoints];
118 TPtr8 dataptr(reinterpret_cast<TUint8*>(endpointCaps), sizeof(endpointCaps), sizeof(endpointCaps));
119 err = iClientDriver.EndpointCaps(dataptr);
122 RDebug::Printf("<Error %d> Unable to get endpoint capabilities",err);
126 TInt totalEndpoints(devCaps().iTotalEndpoints);
128 // Loop through available hardware endpoints to find suitable one
129 // i.e. endpoints that can be configured
134 for(; epIndex<totalEndpoints; epIndex++)
136 RDebug::Printf("Examining hardware endpoint %u",epIndex);
137 const TUsbcEndpointData ep = endpointCaps[epIndex];
139 // Check the endpoint index to see if already claimed
142 RDebug::Printf("...its free");
143 const TUsbcEndpointCaps caps(ep.iCaps);
145 // Information about the endpoint we are looking for
146 TUsbcEndpointInfo& endpointSpec = aInterfaceSetting->iInterfaceInfo().iEndpointData[epCount];
148 if( (caps.iTypesAndDir & (endpointSpec.iDir | endpointSpec.iType)) ==
149 (endpointSpec.iDir | endpointSpec.iType) )
151 // Found suitable endpoint
153 // Create the reader/writer for this endpoint
155 if(endpointSpec.iDir == KUsbEpDirIn)
157 // Create an endpoint writer for this endpoint
159 aInterfaceSetting->CreateEndpointWriterL(iClientDriver,(epCount+1));
160 RDebug::Printf("Created endpoint writer for endpoint%d",epCount+1);
162 else if(endpointSpec.iDir == KUsbEpDirOut)
164 // Create an endpoint reader for this endpoint
166 aInterfaceSetting->CreateEndpointReaderL(iClientDriver,epCount+1);
167 RDebug::Printf("Created endpoint reader for endpoint%d",epCount+1);
170 epCount++; // Increment to next endpoint spec
171 RDebug::Printf("Endpoint %u configured",epCount);
172 endpointSpec.iSize = caps.MaxPacketSize();
174 if(epCount >= endpointSettingCount)
176 // Found all desired endpoints
183 RDebug::Printf("...its busy");
187 RDebug::Printf("Configure %u out of %u endpoints",epCount,endpointSettingCount);
189 if(epCount < endpointSettingCount)
191 RDebug::Printf("<Error %d> Only managed to configure %u out of %u endpoints",KErrNotFound,epCount,endpointSettingCount);
192 User::Leave(KErrNotFound);
197 RDebug::Printf("No endpoints for this interface setting");
200 // Add the new setting to the device
201 err = iClientDriver.SetInterface(alternateSettingNumber,aInterfaceSetting->iInterfaceInfo);
204 RDebug::Printf("<Error %d> Unable to set the alternate interface setting %d",err,alternateSettingNumber);
208 RDebug::Printf("Alternate interface setting %d set",alternateSettingNumber);
212 TInt CInterfaceBase::StallEndpoint(TUint16 aEndpointNumber)
216 RDebug::Printf("Stalling endpoint%d",aEndpointNumber);
217 return iClientDriver.HaltEndpoint(static_cast<TEndpointNumber>(aEndpointNumber));
221 CInterfaceSettingBase& CInterfaceBase::AlternateSetting(TInt aSettingNumber) const
223 return *iAlternateSettings[aSettingNumber];
227 TInt CInterfaceBase::InterfaceSettingCount() const
229 return iAlternateSettings.Count();
233 TUint32 CInterfaceBase::ExtractNumberL(const TDesC8& aPayload)
237 // Read the number of repeats and the data supplied by the host, on the specified endpoint
238 TLex8 lex(aPayload.Left(KNumberStringLength));
240 User::LeaveIfError(lex.Val(numBytes, EDecimal));
241 RDebug::Printf("Writing %d bytes using string pattern below to IN endpoint",numBytes);
242 RDebug::RawPrint(aPayload.Mid(KNumberStringLength));
243 RDebug::Printf(""); //new line
247 void CInterfaceBase::ExtractTwoNumbersL(const TDesC8& aPayload, TUint32& aFirstNum, TUint32& aSecondNum)
251 // Read the number of repeats and the data supplied by the host, on the specified endpoint
252 TLex8 lex1(aPayload.Left(KNumberStringLength));
253 User::LeaveIfError(lex1.Val(aFirstNum, EDecimal));
254 TLex8 lex2(aPayload.Mid(KNumberStringLength, KNumberStringLength));
255 User::LeaveIfError(lex2.Val(aSecondNum, EDecimal));
256 RDebug::Printf("Writing or Reading a total of %d bytes in repeats of %d bytes using string pattern below to IN endpoint",aFirstNum,aSecondNum);
257 RDebug::RawPrint(aPayload.Mid(2*KNumberStringLength));
258 RDebug::Printf(""); //new line
262 void CInterfaceBase::AlternateInterfaceSelectedL(TInt aAlternateInterfaceSetting)
265 RDebug::Printf("Interface %S:",&iInterfaceName);
266 iCurrentAlternateInterfaceSetting = aAlternateInterfaceSetting;
270 TInt CInterfaceBase::ProcessRequestL(TUint8 aRequest,TUint16 aValue,TUint16 aIndex,
271 TUint16 aDataReqLength,const TDesC8& aPayload)
274 RDebug::Printf("Interface %S:",&iInterfaceName);
278 case KVendorEmptyRequest:
279 // Acknowledge the request and do nothing
280 iEp0Reader->Acknowledge();
282 RDebug::Printf("Request: Empty");
285 case KVendorPutPayloadRequest:
286 // Acknowledge the request
287 iEp0Reader->Acknowledge();
289 RDebug::Printf("Put payload");
290 if(aPayload.Compare(_L8("DEADBEEF")) != 0)
292 RDebug::Printf("<Error %d> Payload not as expected",KErrCorrupt);
293 iDevice.ReportError(KErrCorrupt);
297 case KVendorGetPayloadRequest:
299 RDebug::Printf("Get payload");
300 __ASSERT_DEBUG(iAuxBuffer, User::Panic(_L("Trying to write non-allocated buffer"), KErrGeneral));
301 RDebug::Printf("iAuxBuffer = ....");
302 RDebug::RawPrint(*iAuxBuffer);
303 RDebug::Printf("\n");
305 //Perform synchronous write to EP0
306 //This allows the subsequent 'Read' request to
308 TInt ret = iEp0Writer->WriteSynchronous(*iAuxBuffer, ETrue);
309 RDebug::Printf("Write (from interface callback) executed with error %d", ret);
313 case KVendorGetRecordedNumBytesReadInPayloadRequest:
316 iAuxBuffer = HBufC8::NewL(KNumberStringLength);
317 TPtr8 ptr(iAuxBuffer->Des());
319 retValue = AlternateSetting(iCurrentAlternateInterfaceSetting).NumBytesReadSoFarL(aValue);
321 ptr.Format(KNumberFormatString, retValue);
323 //Perform synchronous write to EP0
324 //This allows the subsequent 'Read' request to
326 TInt ret = iEp0Writer->WriteSynchronous(*iAuxBuffer, ETrue);
327 RDebug::Printf("Write (from interface callback) executed with error %d", ret);
331 case KVendorGetRecordedNumBytesWrittenInPayloadRequest:
334 iAuxBuffer = HBufC8::NewL(KNumberStringLength);
335 TPtr8 ptr(iAuxBuffer->Des());
337 retValue = AlternateSetting(iCurrentAlternateInterfaceSetting).NumBytesWrittenSoFarL(aValue);
339 ptr.Format(KNumberFormatString, retValue);
341 //Perform synchronous write to EP0
342 //This allows the subsequent 'Read' request to
344 TInt ret = iEp0Writer->WriteSynchronous(*iAuxBuffer, ETrue);
345 RDebug::Printf("Write (from interface callback) executed with error %d", ret);
349 case KVendorWriteToEndpointRequest:
350 // Acknowledge the request
351 iEp0Reader->Acknowledge();
353 RDebug::Printf("Writing %d bytes to IN endpoint (index %d)",aPayload.Length(),aValue);
355 // Write the data supplied by the host, back to the host though the specified endpoint
357 AlternateSetting(iCurrentAlternateInterfaceSetting).WriteSpecifiedDataToEndpointL(aPayload,aValue);
360 case KVendorCancelWriteToEndpointRequest:
361 // Acknowledge the request
362 iEp0Reader->Acknowledge();
364 RDebug::Printf("CANCEL Writing to IN endpoint (index %d)",aValue);
366 // CANCEL writing the data supplied by the host, back to the host though the specified endpoint
368 AlternateSetting(iCurrentAlternateInterfaceSetting).CancelWriteDataToEndpointL(aValue);
371 case KVendorPatternWriteToEndpointRequest:
373 // Acknowledge the request
374 iEp0Reader->Acknowledge();
376 // Read the number of repeats and the data supplied by the host, on the specified endpoint
377 TUint32 numBytes = ExtractNumberL(aPayload);
379 // Write the data supplied by the host, back to the host though the specified endpoint
380 AlternateSetting(iCurrentAlternateInterfaceSetting).WriteSpecifiedDataToEndpointL(aPayload.Mid(KNumberStringLength),numBytes,aValue);
384 case KVendorPatternWriteSynchronousToEndpointRequest:
386 // Acknowledge the request
387 iEp0Reader->Acknowledge();
389 // Read the number of repeats and the data supplied by the host, on the specified endpoint
390 TUint32 numBytes = ExtractNumberL(aPayload);
392 // Write the data supplied by the host, back to the host though the specified endpoint
393 AlternateSetting(iCurrentAlternateInterfaceSetting).WriteSynchronousSpecifiedDataToEndpointL(aPayload.Mid(KNumberStringLength),numBytes,aValue);
397 case KVendorPatternWriteSynchronousToAndHaltEndpointRequest:
399 // Acknowledge the request
400 iEp0Reader->Acknowledge();
402 // Read the number of repeats and the data supplied by the host, on the specified endpoint
403 TUint32 numBytes = ExtractNumberL(aPayload);
405 // Write the data supplied by the host, back to the host though the specified endpoint
406 AlternateSetting(iCurrentAlternateInterfaceSetting).WriteSynchronousSpecifiedDataToAndHaltEndpointL(aPayload.Mid(KNumberStringLength),numBytes,aValue);
410 case KVendorRepeatedReadAndValidateDataRequest:
412 // Acknowledge the request
413 iEp0Reader->Acknowledge();
415 // Read the number of bytes to read in total and per individual 'Read' together with the data supplied by the host, on the specified endpoint
416 TUint32 numBytesPerRead = 0;
417 TUint32 totalNumBytes = 0;
418 ExtractTwoNumbersL(aPayload, numBytesPerRead, totalNumBytes);
419 RDebug::Printf("Extracted: Number of Bytes per Read = %d, Total Number of Bytes = %d",numBytesPerRead,totalNumBytes);
421 // Write the data supplied by the host, back to the host though the specified endpoint
422 AlternateSetting(iCurrentAlternateInterfaceSetting).RepeatedReadAndValidateFromEndpointL(aPayload.Mid(KTwoNumberStringLength),numBytesPerRead,totalNumBytes,aValue);
426 case KVendorRepeatedPatternWriteDataRequest:
428 // Acknowledge the request
429 iEp0Reader->Acknowledge();
431 // Read the number of bytes to write in total and per individual 'Write' together with the data supplied by the host, on the specified endpoint
432 TUint32 numBytesPerWrite = 0;
433 TUint32 totalNumBytes = 0;
434 ExtractTwoNumbersL(aPayload, numBytesPerWrite, totalNumBytes);
435 RDebug::Printf("Extracted: Number of Bytes per Read = %d, Total Number of Bytes = %d",numBytesPerWrite,totalNumBytes);
437 // Write the data supplied by the host, back to the host though the specified endpoint
438 AlternateSetting(iCurrentAlternateInterfaceSetting).RepeatedWriteSpecifiedDataToEndpointL(aPayload.Mid(KTwoNumberStringLength),numBytesPerWrite,totalNumBytes,aValue);
442 case KVendorWriteCachedReadRequest:
444 // Acknowledge the request
445 iEp0Reader->Acknowledge();
447 TUint16 readEndpoint = aValue >> 8; //HI 8 buts
448 TUint16 writeEndpoint = aValue & 0x00ff; //LO 8 bits
450 RDebug::Printf("Writing data cached on OUT endpoint (index %d) to IN endpoint (index %d)",readEndpoint,writeEndpoint);
452 // Write the data supplied by the host, back to the host though the specified endpoint
454 AlternateSetting(iCurrentAlternateInterfaceSetting).WriteCachedEndpointDataToEndpointL(readEndpoint,writeEndpoint);
458 case KVendorWriteSynchronousCachedReadRequest:
460 // Acknowledge the request
461 iEp0Reader->Acknowledge();
463 TUint16 readEndpoint = aValue >> 8; //HI 8 buts
464 TUint16 writeEndpoint = aValue & 0x00ff; //LO 8 bits
466 RDebug::Printf("Writing data cached on OUT endpoint (index %d) to IN endpoint (index %d)",readEndpoint,writeEndpoint);
468 // Write the data supplied by the host, back to the host though the specified endpoint
470 AlternateSetting(iCurrentAlternateInterfaceSetting).WriteSynchronousCachedEndpointDataToEndpointL(readEndpoint,writeEndpoint);
474 case KVendorSplitWriteSynchronousCachedReadRequest:
476 // Acknowledge the request
477 iEp0Reader->Acknowledge();
479 TUint16 readEndpoint = aValue >> 8; //HI 8 buts
480 TUint16 writeEndpoint = aValue & 0x00ff; //LO 8 bits
481 RDebug::Printf("Writing data cached on OUT endpoint (index %d) to IN endpoint (index %d) in sections of....",readEndpoint,writeEndpoint);
483 // Read the number of bytes to use for each Write
484 TUint numBytes[KNumSplitWriteSections];
485 TUint numBytesWritten = 0;
486 for(TUint i=0; i<KNumSplitWriteSections; ++i)
488 TLex8 lex(aPayload.Mid(i*KNumberStringLength, KNumberStringLength));
489 User::LeaveIfError(lex.Val(numBytes[i], EDecimal));
490 RDebug::Printf("%d bytes", numBytes[i]);
491 // Write the data supplied by the host, back to the host though the specified endpoint
492 AlternateSetting(iCurrentAlternateInterfaceSetting).WriteSynchronousCachedEndpointDataToEndpointL(readEndpoint,writeEndpoint,numBytesWritten,numBytes[i]);
493 // Updates bytes written for next round of 'for'loop
494 numBytesWritten += numBytes[i];
499 case KVendorReadFromEndpointRequest:
501 // Acknowledge the request
502 iEp0Reader->Acknowledge();
504 // Read the amount of data supplied by the host, on the specified endpoint
507 User::LeaveIfError(lex.Val(numBytes, EDecimal));
508 RDebug::Printf("Reading %d bytes on OUT endpoint (index %d)",numBytes,aValue);
509 AlternateSetting(iCurrentAlternateInterfaceSetting).ReadDataFromEndpointL(numBytes,aValue);
513 case KVendorReadFromAndHaltEndpointRequest:
515 // Acknowledge the request
516 iEp0Reader->Acknowledge();
518 // Read the amount of data supplied by the host, on the specified endpoint
521 User::LeaveIfError(lex.Val(numBytes, EDecimal));
522 RDebug::Printf("Reading %d bytes on OUT endpoint (index %d) ... then halting endpoint",numBytes,aValue);
523 AlternateSetting(iCurrentAlternateInterfaceSetting).ReadDataFromAndHaltEndpointL(numBytes,aValue);
527 case KVendorCancelAnyReadFromEndpointRequest:
529 // Acknowledge the request
530 iEp0Reader->Acknowledge();
532 RDebug::Printf("CANCEL Reading on OUT endpoint (index %d)",aValue);
533 AlternateSetting(iCurrentAlternateInterfaceSetting).CancelAnyReadDataFromEndpointL(aValue);
537 case KVendorReadUntilShortFromEndpointRequest:
539 // Acknowledge the request
540 iEp0Reader->Acknowledge();
542 // Read the amount of data supplied by the host, on the specified endpoint
545 User::LeaveIfError(lex.Val(numBytes, EDecimal));
546 RDebug::Printf("Reading %d bytes on OUT endpoint (index %d)",numBytes,aValue);
547 AlternateSetting(iCurrentAlternateInterfaceSetting).ReadDataUntilShortFromEndpointL(numBytes,aValue);
551 case KVendorStringValidationRequest:
553 // Acknowledge the request
554 iEp0Reader->Acknowledge();
556 // Read the number of repeats and the data supplied by the host, on the specified endpoint
557 TLex8 lex(aPayload.Left(KNumberStringLength));
558 RDebug::Printf("NUMBER STRING LENGTH CALCULATED AS %d",KNumberStringLength);
560 User::LeaveIfError(lex.Val(numBytes, EDecimal));
561 RDebug::Printf("Validation");
562 RDebug::Printf("Checking %d bytes using string pattern below exist in the buffer for endpoint %d",numBytes,aValue);
563 RDebug::RawPrint(aPayload.Mid(KNumberStringLength));
566 iAuxBuffer = HBufC8::NewL(KPassFailStringLength);
567 TPtr8 ptr(iAuxBuffer->Des());
568 if(AlternateSetting(iCurrentAlternateInterfaceSetting).ValidateCachedEndpointDataL(aPayload.Mid(KNumberStringLength),numBytes,aValue))
570 ptr.Copy(KClientPassString);
574 ptr.Copy(KClientFailString);
579 case KVendorRecordedValidationResultRequest:
581 // Acknowledge the request
582 iEp0Reader->Acknowledge();
585 iAuxBuffer = HBufC8::NewL(KPassFailStringLength);
586 TPtr8 ptr(iAuxBuffer->Des());
587 if(AlternateSetting(iCurrentAlternateInterfaceSetting).CachedEndpointResultL(aValue))
589 ptr.Copy(KClientPassString);
593 ptr.Copy(KClientFailString);
598 case KVendorUnrespondRequest:
599 // Do not acknowledge this request
601 RDebug::Printf("Unrespond request: continually NAK the host");
604 case KVendorStallRequest:
606 // Stall the specified endpoint
607 iEp0Reader->Acknowledge();
608 RDebug::Printf("Stalling endpoint%d",aValue);
609 TInt err = StallEndpoint(aValue);
612 RDebug::Printf("<Error %d> unable to stall endpoint index %d",err,aValue);
613 iDevice.ReportError(err);
618 // Maybe forward to derived classes
626 void CInterfaceBase::StartEp0Reading()
630 iEp0Reader->ReadRequestsL();
634 void CInterfaceBase::StopEp0Reading()
638 iEp0Reader->Cancel();