sl@0: // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // @file PBASE-T_USBDI-1229.cpp sl@0: // @internalComponent sl@0: // sl@0: // sl@0: sl@0: #include "PBASE-T_USBDI-1229.h" sl@0: #include "testpolicy.h" sl@0: #include "modelleddevices.h" sl@0: #include "testliterals.h" sl@0: sl@0: sl@0: sl@0: sl@0: namespace NUnitTesting_USBDI sl@0: { sl@0: const TUint KTotalBytesToTransfer = 1024*64+511; //64kB + 511 bytes sl@0: const TUint KHostNumWriteBytes = 1024*16; sl@0: const TInt KBulkMaxTransferSize = KHostNumWriteBytes + 1000; sl@0: const TInt KDeviceNumReadBytes = 1024; sl@0: sl@0: sl@0: //Make these single bit values ... sl@0: // ... so that their completion can be easily recorded in a bit mask! sl@0: const TUint32 KBulkTransferOutId[KMaxNumOutTransfers] = {1<<0, 1<<1}; sl@0: const TUint32 KBulkTransferIdMask = KBulkTransferOutId[0] | KBulkTransferOutId[1]; sl@0: sl@0: const TInt KUndefinedStep = -102; sl@0: const TInt KUnexpectedTransferID = -103; sl@0: const TInt KErrReturnedDeviceReadBytesTooVariable = -140; sl@0: const TInt KTransferSuccess = +100; sl@0: sl@0: const TUint KRepeatedTimerInterval = 10000; //10ms sl@0: const TUint KBaseTimer = 0; sl@0: const TUint KTestTimer = 1; sl@0: const TUint KMaxTimeDiffPercentage = 60; //on inspection worst result was just under 70% sl@0: const TUint KMaxBytesReadDiffPercentage = 50; sl@0: sl@0: sl@0: sl@0: sl@0: _LIT(KTestCaseId,"PBASE-T_USBDI-1229"); sl@0: const TFunctorTestCase CUT_PBASE_T_USBDI_1229::iFunctor(KTestCaseId); sl@0: sl@0: CUT_PBASE_T_USBDI_1229* CUT_PBASE_T_USBDI_1229::NewL(TBool aHostRole) sl@0: { sl@0: CUT_PBASE_T_USBDI_1229* self = new (ELeave) CUT_PBASE_T_USBDI_1229(aHostRole); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: sl@0: CUT_PBASE_T_USBDI_1229::CUT_PBASE_T_USBDI_1229(TBool aHostRole) sl@0: : CBaseBulkTestCase(KTestCaseId,aHostRole), sl@0: iCaseStep(EInProgress) sl@0: { sl@0: } sl@0: sl@0: sl@0: void CUT_PBASE_T_USBDI_1229::ConstructL() sl@0: { sl@0: BaseBulkConstructL(); sl@0: sl@0: iInBuffer = HBufC8::NewL(KTestBufferLength); sl@0: sl@0: iBulkTestTimer = CBulkTestTimer::NewL(*this); sl@0: sl@0: //Create buffer to contain multiple lots of the payload pattern sl@0: //..so that we may grab cyclic chunks of said payload pattern sl@0: //..this is used to send to the client for validation purposes sl@0: //..AND for the host to send data sl@0: TInt repeats = KHostNumWriteBytes / (KLiteralEnglish5().Length()) + 1 + 1; //1 extra to accommodate start point plus 1 to accomodate remainder in division sl@0: iOutBuffer = HBufC8::NewL(KLiteralEnglish5().Length() * repeats); sl@0: iOutBufferPtr.Set(iOutBuffer->Des()); sl@0: iOutBufferPtr.Zero(); sl@0: for(TInt i=0;iCancel(); sl@0: iOutTransfer[1]->Cancel(); sl@0: } sl@0: sl@0: void CUT_PBASE_T_USBDI_1229::ExtractDeviceReadBytes() sl@0: { sl@0: LOG_FUNC sl@0: sl@0: iControlEp0->LastRequestCompletionTime( iEndTime[KTestTimer]); sl@0: iTimingError = iTimingError == KErrNone ? CheckTimes(KBaseTimer, KTestTimer, KMaxTimeDiffPercentage) : iTimingError; sl@0: ResetTimes(KTestTimer); sl@0: sl@0: RDebug::Printf("Collect client's return of the number of bytes read on its bulk out endpoint ..."); sl@0: TLex8 lex(iInBufferPtr.Left(KNumberStringLength)); sl@0: TUint32 numBytes = 0; sl@0: User::LeaveIfError(lex.Val(numBytes, EDecimal)); sl@0: RDebug::Printf("********************NUM*BYTES****************************"); sl@0: RDebug::Printf(" NUM BYTES READ BY CLIENT ==== %d ==== ", numBytes); sl@0: RDebug::Printf("********************NUM*BYTES****************************"); sl@0: RDebug::Printf("\n"); sl@0: sl@0: if(numBytes != 0) sl@0: //Do not count this case - it may result from the remote resetting when all bulk transfers have completed sl@0: { sl@0: TUint numBytesSinceLast = numBytes - iDeviceNumBytesReadInTotal; sl@0: iDeviceNumBytesReadInTotal = numBytes; sl@0: iDeviceMinTimedNumBytesRead = numBytesSinceLast < iDeviceMinTimedNumBytesRead ? numBytesSinceLast : iDeviceMinTimedNumBytesRead ; sl@0: iDeviceMaxTimedNumBytesRead = numBytesSinceLast > iDeviceMaxTimedNumBytesRead ? numBytesSinceLast : iDeviceMaxTimedNumBytesRead ;; sl@0: } sl@0: } sl@0: sl@0: sl@0: void CUT_PBASE_T_USBDI_1229::PostTransferAction() sl@0: { sl@0: switch(iTransferResult) sl@0: { sl@0: case KErrNone: sl@0: //do nothing sl@0: return; sl@0: sl@0: case KTransferSuccess: sl@0: //indicates data validation failure sl@0: { sl@0: RDebug::Printf("Asking client to post validation recorded on the endpoint on its interface - ready for collection"); sl@0: iCaseStep = ERequestPrepareEndpointValidationResult; sl@0: TRecordedValidationResultRequest request(1,1); sl@0: iControlEp0->SendRequest(request,this); sl@0: } sl@0: return; sl@0: sl@0: default: sl@0: { sl@0: iCaseStep = EFailed; sl@0: RDebug::Print(iMsg); sl@0: TTestCaseFailed request(iTransferResult,iMsg); sl@0: iControlEp0->SendRequest(request,this); sl@0: } sl@0: return; sl@0: } sl@0: } sl@0: sl@0: sl@0: TBool CUT_PBASE_T_USBDI_1229::PerformNextTransfer(TInt aTransferId) sl@0: { sl@0: LOG_FUNC sl@0: sl@0: if(iNumWriteBytesRequested >= KTotalBytesToTransfer) sl@0: { sl@0: RDebug::Printf("All transfers sent - num bytes actually written = %d, num bytes required to be written = %d", iNumWriteBytesRequested, KTotalBytesToTransfer); sl@0: return EFalse; //Not writing any more - signal to user that no more transfers are required sl@0: } sl@0: TUint bytesToWrite = KTotalBytesToTransfer - iNumWriteBytesRequested; sl@0: TUint numWriteBytes = bytesToWrite < KHostNumWriteBytes ? bytesToWrite : KHostNumWriteBytes; sl@0: sl@0: _LITDBG("PerformNextTransfer: None existant transfer ID requested"); sl@0: __ASSERT_DEBUG(aTransferId==KBulkTransferOutId[0] || aTransferId==KBulkTransferOutId[1], User::Panic(lit, KErrArgument)); sl@0: CBulkTransfer& bulkTransfer = aTransferId==KBulkTransferOutId[0]?*iOutTransfer[0]:*iOutTransfer[1]; sl@0: bulkTransfer.TransferOut(iOutBufferPtr.Mid(iNumWriteBytesRequested%(KLiteralEnglish5().Length()), numWriteBytes), EFalse); sl@0: iNumWriteBytesRequested += numWriteBytes; sl@0: sl@0: return ETrue; sl@0: } sl@0: sl@0: sl@0: void CUT_PBASE_T_USBDI_1229::RequestNumBytesSent(TUint8 aTimerIndex) sl@0: { sl@0: iInBufferPtr.Set(iInBuffer->Des()); sl@0: iInBufferPtr.Zero(); //reset sl@0: iInBufferPtr.SetLength(KNumberStringLength); sl@0: TInterfaceGetRecordedNumBytesReadInPayload request(1,1,iInBufferPtr); sl@0: iControlEp0->SendRequest(request,this); sl@0: iControlEp0->LastRequestStartTime( iStartTime[aTimerIndex]); sl@0: } sl@0: sl@0: sl@0: void CUT_PBASE_T_USBDI_1229::Ep0TransferCompleteL(TInt aCompletionCode) sl@0: { sl@0: LOG_FUNC sl@0: sl@0: RDebug::Printf("Ep0TransferCompleteL with aCompletionCode = %d, test step = %d", aCompletionCode, iCaseStep); sl@0: sl@0: if(aCompletionCode != KErrNone) sl@0: { sl@0: if(iCaseStep == EFailed) sl@0: {// ignore error, nad catch the TestFailed method called further down. sl@0: RDebug::Printf("***Failure sending FAIL message to client on endpoint 0***"); sl@0: } sl@0: else sl@0: { sl@0: TBuf<256> msg; sl@0: KillTransfers(); sl@0: _LIT(lit, " Transfer to control endpoint 0 was not successful"); sl@0: msg.Format(lit,aCompletionCode); sl@0: RDebug::Print(msg); sl@0: iCaseStep = EFailed; sl@0: TTestCaseFailed request(aCompletionCode,msg); sl@0: iControlEp0->SendRequest(request,this); sl@0: return; sl@0: } sl@0: } sl@0: sl@0: switch(iCaseStep) sl@0: { sl@0: // Test case passed sl@0: case EPassed: sl@0: TestPassed(); sl@0: break; sl@0: sl@0: // Test case failed sl@0: case EFailed: sl@0: TestFailed(KErrCompletion); sl@0: break; sl@0: sl@0: case EGetTimerBase: sl@0: { sl@0: iControlEp0->LastRequestCompletionTime( iEndTime[KBaseTimer]); sl@0: RDebug::Printf("Asking client for continuous 'Read' and 'Validate'"); sl@0: iCaseStep = ERequestRepeatedReadAndValidate; sl@0: TRepeatedReadAndValidateDataRequest request(1,1,KLiteralEnglish5(),KDeviceNumReadBytes,KTotalBytesToTransfer);// EP2 means endpoint index 2 not the actual endpoint number, here the ep with 32 byte max packet size sl@0: iControlEp0->SendRequest(request,this); sl@0: } sl@0: break; sl@0: sl@0: case ERequestRepeatedReadAndValidate: sl@0: { sl@0: RDebug::Printf("Try to perform ALL transfers"); sl@0: sl@0: iCaseStep = ETransfer; sl@0: sl@0: PerformNextTransfer(KBulkTransferOutId[0]); sl@0: PerformNextTransfer(KBulkTransferOutId[1]); sl@0: _LITDBG("Bulk test timer NOT instanciated"); sl@0: __ASSERT_DEBUG(iBulkTestTimer, User::Panic(lit, KErrGeneral)); sl@0: iBulkTestTimer->After(KRepeatedTimerInterval); sl@0: } sl@0: break; sl@0: sl@0: case ETransfer: sl@0: // we must be getting num bytes read sl@0: ExtractDeviceReadBytes(); sl@0: sl@0: //Restart timer sl@0: _LITDBG("Bulk test timer NOT instanciated"); sl@0: __ASSERT_DEBUG(iBulkTestTimer, User::Panic(lit, KErrGeneral)); sl@0: iBulkTestTimer->After(KRepeatedTimerInterval); sl@0: break; sl@0: sl@0: case EDelayedTransferComplete: sl@0: PostTransferAction(); sl@0: break; sl@0: sl@0: case ERequestPrepareEndpointValidationResult: sl@0: { sl@0: RDebug::Printf("Asking client to prepare the result of its continuous validation"); sl@0: iCaseStep = ERequestValidationResult; sl@0: iInBufferPtr.Set(iInBuffer->Des()); sl@0: iInBufferPtr.Zero(); //reset sl@0: iInBufferPtr.SetLength(KPassFailStringLength); sl@0: TInterfaceGetPayloadRequest request(1,iInBufferPtr); sl@0: iControlEp0->SendRequest(request,this); sl@0: } sl@0: break; sl@0: sl@0: case ERequestValidationResult: sl@0: RDebug::Printf("Collect client's return validation result in a pass or fail string ..."); sl@0: RDebug::RawPrint(*iInBuffer); sl@0: RDebug::Printf("\n"); sl@0: iInBufferPtr.Set(iInBuffer->Des()); sl@0: if(iInBufferPtr.Compare(KClientPassString) == 0) sl@0: { sl@0: RDebug::Printf("Client Validation Result is a PASS"); sl@0: RDebug::Printf("This is the FINAL check - the whole test has a PASSED"); sl@0: iCaseStep = EPassed; sl@0: TTestCasePassed request; sl@0: iControlEp0->SendRequest(request,this); sl@0: } sl@0: else sl@0: { sl@0: TBuf<256> msg; sl@0: _LIT(lit, " Bulk data VALIDATION check was NOT successful"); sl@0: msg.Format(lit); sl@0: RDebug::Print(msg); sl@0: iCaseStep = EFailed; sl@0: TTestCaseFailed request(KErrCorrupt,msg); sl@0: iControlEp0->SendRequest(request,this); sl@0: } sl@0: break; sl@0: sl@0: default: sl@0: RDebug::Printf(" Unknown test step"); sl@0: TestFailed(KErrUnknown); sl@0: break; sl@0: } sl@0: } sl@0: sl@0: void CUT_PBASE_T_USBDI_1229::TransferCompleteL(TInt aTransferId,TInt aCompletionCode) sl@0: { sl@0: LOG_FUNC sl@0: Cancel(); sl@0: sl@0: iTransferResult = KErrNone; sl@0: RDebug::Printf("Transfer completed (id=%d), aCompletionCode = %d, test step = %d",aTransferId, aCompletionCode, iCaseStep); sl@0: sl@0: sl@0: switch(iCaseStep) sl@0: { sl@0: case ETransfer: sl@0: if(aCompletionCode != KErrNone) sl@0: { sl@0: KillTransfers(); sl@0: iTransferResult = KErrCorrupt; sl@0: _LIT(lit, " The transfer completed with an error."); sl@0: iMsg.Format(lit, aCompletionCode); sl@0: break; sl@0: } sl@0: if(aTransferId != KBulkTransferOutId[0] && aTransferId != KBulkTransferOutId[1]) sl@0: { sl@0: iTransferComplete = 0; //reset sl@0: iTransferResult = KUnexpectedTransferID; sl@0: _LIT(lit, " Unexpected transfer ID, wanted %d or %d, got %d"); sl@0: iMsg.Format(lit, iTransferResult, KBulkTransferOutId[0], KBulkTransferOutId[1], aTransferId); sl@0: break; sl@0: } sl@0: RDebug::Printf("Transfer OUT %d completed - num bytes sent = %d", aTransferId, iNumWriteBytesRequested); sl@0: sl@0: if(PerformNextTransfer(aTransferId)==EFalse) sl@0: { sl@0: iTransferComplete |= aTransferId; sl@0: RDebug::Printf("All transfer OUT %ds completed (Transfer Completion Aggregation Mask 0x%x)", aTransferId, iTransferComplete); sl@0: } sl@0: sl@0: if(iTransferResult==KErrNone && (iTransferComplete & KBulkTransferIdMask) == KBulkTransferIdMask) sl@0: { sl@0: /* sl@0: Transfers all complete - now ask device to validate first interface's transfer OUT sl@0: */ sl@0: RDebug::Printf("All Transfers Completed Successfully: Transfer Completion Aggregation Mask 0x%x", iTransferComplete); sl@0: if(iTransferResult==KErrNone) sl@0: { sl@0: iBulkTestTimer->Cancel(); //Cancel Timer sl@0: iTransferResult = KTransferSuccess; sl@0: if(iTimingError == KErrTooBig) sl@0: { sl@0: __PRINT_CONTROL_TRANSFER_TIMER_COMPARISON_WARNING sl@0: iTransferResult = KErrTooBig; sl@0: iTimingError = KErrNone; //reset sl@0: } sl@0: if(KMaxBytesReadDiffPercentage*iDeviceMaxTimedNumBytesRead > KPercent*iDeviceMinTimedNumBytesRead) sl@0: { sl@0: RDebug::Printf("Device APPARENTLY reading rate erratic:-"); sl@0: RDebug::Printf("Min Timed Number of Bytes = %d", iDeviceMinTimedNumBytesRead); sl@0: RDebug::Printf("Max Timed Number of Bytes = %d", iDeviceMaxTimedNumBytesRead); sl@0: iTransferResult = KErrTooBig; sl@0: iDeviceMaxTimedNumBytesRead = 0; sl@0: iDeviceMinTimedNumBytesRead = KMaxTUint; sl@0: } sl@0: } sl@0: } sl@0: break; sl@0: sl@0: default: sl@0: iTransferResult = KUndefinedStep; sl@0: _LIT(lit, " Undefined case step %d reached"); sl@0: iMsg.Format(lit,KUndefinedStep, iCaseStep); sl@0: break; sl@0: } sl@0: sl@0: sl@0: if(iTransferResult == KErrReturnedDeviceReadBytesTooVariable) sl@0: //indicates apparent device read rate validation failure sl@0: { sl@0: iMsg.Format(_L(" Device APPEARS not to be reading bytes at a constant rate"), iTransferResult); sl@0: } sl@0: sl@0: if(iTransferResult == KErrTooBig) sl@0: //indicates timing validation failure sl@0: { sl@0: iMsg.Format(_L(" Timer comparison showed too great a difference in transfer times between the time taken by EP0 transfers with and without a bulk transfer"), iTransferResult); sl@0: } sl@0: sl@0: if(iTransferResult == KErrCompletion) sl@0: //indicates data validation failure sl@0: { sl@0: _LIT(lit, " Client has posted an error discovered in validation"); sl@0: iMsg.Format(lit, iTransferResult); sl@0: } sl@0: sl@0: if(iTransferResult != KErrNone) sl@0: { sl@0: KillTransfers(); //harmless if tranfers are all done sl@0: if(!iControlEp0->IsActive()) sl@0: { sl@0: PostTransferAction(); sl@0: } sl@0: else sl@0: { sl@0: iCaseStep = EDelayedTransferComplete; //so that we move forward when the EP0 transfer has completed sl@0: } sl@0: } sl@0: } sl@0: sl@0: void CUT_PBASE_T_USBDI_1229::DeviceInsertedL(TUint aDeviceHandle) sl@0: { sl@0: LOG_FUNC sl@0: sl@0: Cancel(); sl@0: RDebug::Printf("this - %08x", this); sl@0: sl@0: TBuf<256> msg; sl@0: TInt err = KErrNone; sl@0: if(BaseBulkDeviceInsertedL(aDeviceHandle, EFalse) == EDeviceConfigurationError) sl@0: // Prepare for response from control transfer to client sl@0: { sl@0: err = KErrGeneral; sl@0: _LIT(lit, "Base class DeviceInsertedL failed"); sl@0: msg.Format(lit); sl@0: } sl@0: else sl@0: { sl@0: if(SetUpInterfaceAndPipesL(aDeviceHandle, 2) == EDeviceConfigurationError) sl@0: // Prepare for response from control transfer to client sl@0: { sl@0: err = KErrGeneral; sl@0: _LIT(lit, "Base class SetUpInterfaceAndPipes for Interface 2 failed"); sl@0: msg.Format(lit); sl@0: } sl@0: else sl@0: { sl@0: sl@0: iOutTransfer[0] = new (ELeave) CBulkTransfer(iTestPipeInterface1BulkOut,iUsbInterface1,KBulkMaxTransferSize,*this,KBulkTransferOutId[0]); sl@0: iOutTransfer[1] = new (ELeave) CBulkTransfer(iTestPipeInterface1BulkOut,iUsbInterface1,KBulkMaxTransferSize,*this,KBulkTransferOutId[1]); sl@0: sl@0: // Initialise the descriptors for transfer sl@0: RDebug::Printf("Initialising the transfer descriptors - interface 1"); sl@0: err = iUsbInterface1.InitialiseTransferDescriptors(); sl@0: if(err != KErrNone) sl@0: { sl@0: _LIT(lit, " Unable to initialise transfer descriptors"); sl@0: msg.Format(lit,err); sl@0: } sl@0: } sl@0: } sl@0: if(err != KErrNone) sl@0: { sl@0: RDebug::Print(msg); sl@0: iCaseStep = EFailed; sl@0: TTestCaseFailed request(err,msg); sl@0: iControlEp0->SendRequest(request,this); sl@0: } sl@0: else sl@0: { sl@0: iCaseStep = EGetTimerBase; sl@0: iDeviceMinTimedNumBytesRead = KMaxTUint; sl@0: iDeviceMaxTimedNumBytesRead = 0; sl@0: iDeviceNumBytesReadInTotal = 0; sl@0: RequestNumBytesSent(KBaseTimer); sl@0: } sl@0: } sl@0: sl@0: void CUT_PBASE_T_USBDI_1229::HandleBulkTestTimerFired() sl@0: { sl@0: if(iCaseStep == ETransfer) sl@0: { sl@0: RequestNumBytesSent(KTestTimer); sl@0: } sl@0: } sl@0: sl@0: } //end namespace