kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/transport/cbulkonlytransport.cpp
changeset 0 a41df078684a
child 39 5d2844f35677
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 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 //
       
    15 
       
    16 
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalTechnology
       
    21 */
       
    22 
       
    23 #include <e32base.h>
       
    24 #include <d32usbc.h>
       
    25 
       
    26 #include "mstypes.h"
       
    27 #include "msctypes.h"
       
    28 #include "usbmsclientpanic.h"
       
    29 #include "botmsctypes.h"
       
    30 #include "testman.h"
       
    31 #include "botmscserver.h"
       
    32 
       
    33 #include "mserverprotocol.h"
       
    34 #include "mdevicetransport.h"
       
    35 
       
    36 #include "mstypes.h"
       
    37 #include "botcontrolinterface.h"
       
    38 #include "debug.h"
       
    39 #include "msdebug.h"
       
    40 #include "cusbmassstorageserver.h"
       
    41 #include "cusbmassstoragecontroller.h"
       
    42 #include "drivemanager.h"
       
    43 #include "cbulkonlytransport.h"
       
    44 
       
    45 #define KInEndpoint EEndpoint1
       
    46 #define KOutEndpoint EEndpoint2
       
    47 
       
    48 
       
    49 //-------------------------------------
       
    50 /**
       
    51 Create CBulkOnlyTransport object
       
    52 @param aNumDrives - The number of drives available for MS
       
    53 @param aController - reference to the parent
       
    54 @return pointer to newly created object
       
    55 */
       
    56 CBulkOnlyTransport* CBulkOnlyTransport::NewL(TInt aNumDrives,
       
    57                                              CUsbMassStorageController& aController)
       
    58 	{
       
    59     __MSFNSLOG
       
    60 	if (aNumDrives <=0 || static_cast<TUint>(aNumDrives) > KUsbMsMaxDrives)
       
    61 		{
       
    62 		User::Leave(KErrArgument);
       
    63 		}
       
    64 	CBulkOnlyTransport* self = new(ELeave) CBulkOnlyTransport(aNumDrives, aController);
       
    65 	CleanupStack::PushL(self);
       
    66 	self->ConstructL();
       
    67 	CleanupStack::Pop(self);
       
    68 	return self;
       
    69 	}
       
    70 
       
    71 #ifdef MSDC_TESTMODE
       
    72 CBulkOnlyTransport* CBulkOnlyTransport::NewL(TInt aNumDrives,
       
    73                                              CUsbMassStorageController& aController,
       
    74                                              TTestParser* aTestParser)
       
    75 	{
       
    76     __MSFNSLOG
       
    77 	if (aNumDrives <=0 || static_cast<TUint>(aNumDrives) > KUsbMsMaxDrives)
       
    78 		{
       
    79 		User::Leave(KErrArgument);
       
    80 		}
       
    81 	CBulkOnlyTransport* self = new(ELeave) CBulkOnlyTransport(aNumDrives,
       
    82                                                               aController,
       
    83                                                               aTestParser);
       
    84 	CleanupStack::PushL(self);
       
    85 	self->ConstructL();
       
    86 	CleanupStack::Pop(self);
       
    87 	return self;
       
    88 	}
       
    89 #endif
       
    90 
       
    91 
       
    92 /**
       
    93 c'tor
       
    94 @param aNumDrives - The number of drives available for MS
       
    95 @param aController - reference to the parent
       
    96 */
       
    97 CBulkOnlyTransport::CBulkOnlyTransport(TInt aNumDrives,
       
    98                                        CUsbMassStorageController& aController):
       
    99 	CActive(EPriorityStandard),
       
   100 	iMaxLun(aNumDrives-1),
       
   101 	iController(aController),
       
   102 	iStallAllowed(ETrue)
       
   103 	{
       
   104     __MSFNLOG
       
   105 	}
       
   106 
       
   107 #ifdef MSDC_TESTMODE
       
   108 CBulkOnlyTransport::CBulkOnlyTransport(TInt aNumDrives,
       
   109                                        CUsbMassStorageController& aController,
       
   110                                        TTestParser* aTestParser)
       
   111 :   CActive(EPriorityStandard),
       
   112 	iMaxLun(aNumDrives-1),
       
   113 	iController(aController),
       
   114 	iStallAllowed(ETrue),
       
   115     iTestParser(aTestParser)
       
   116 	{
       
   117     __MSFNLOG
       
   118 	}
       
   119 #endif
       
   120 
       
   121 
       
   122 /**
       
   123 Constructs the CBulkOnlyTranspor object
       
   124 */
       
   125 void CBulkOnlyTransport::ConstructL()
       
   126 	{
       
   127     __MSFNLOG
       
   128 	iBotControlInterface = CBotControlInterface::NewL(*this);
       
   129 	iDeviceStateNotifier = CActiveDeviceStateNotifier::NewL(*this);
       
   130 	CActiveScheduler::Add(this);
       
   131 	}
       
   132 
       
   133 
       
   134 /**
       
   135 Destructor
       
   136 */
       
   137 CBulkOnlyTransport::~CBulkOnlyTransport()
       
   138 	{
       
   139     __MSFNLOG
       
   140 	if (iInterfaceConfigured)
       
   141 		{
       
   142 		Stop();
       
   143 		}
       
   144 	delete iBotControlInterface;
       
   145 	delete iDeviceStateNotifier;
       
   146 	}
       
   147 
       
   148 
       
   149 /**
       
   150 Set or unset configuration descriptor for USB MassStorage Bulk Only transport
       
   151 
       
   152 @param aUnset indicate whether set or unset descriptor
       
   153 @return KErrNone if operation was completed successfully, errorcode otherwise
       
   154 */
       
   155 TInt CBulkOnlyTransport::SetupConfigurationDescriptor(TBool aUnset)
       
   156 	{
       
   157     __MSFNLOG
       
   158 	TInt ret(KErrNone);
       
   159 	TInt configDescriptorSize(0);
       
   160 
       
   161 	iLdd.GetConfigurationDescriptorSize(configDescriptorSize);
       
   162 	if (static_cast<TUint>(configDescriptorSize) != KUsbDescSize_Config)
       
   163 		{
       
   164 		return KErrCorrupt;
       
   165 		}
       
   166 
       
   167 	TBuf8<KUsbDescSize_Config> configDescriptor;
       
   168 	ret = iLdd.GetConfigurationDescriptor(configDescriptor);
       
   169 	if (ret != KErrNone)
       
   170 		{
       
   171 		return ret;
       
   172 		}
       
   173 
       
   174 	// I beleive that other fields setted up during LDD initialisation
       
   175 	if (aUnset)
       
   176 		{
       
   177 		--configDescriptor[KUsbNumInterfacesOffset];
       
   178 		}
       
   179 	else
       
   180 		{
       
   181 		++configDescriptor[KUsbNumInterfacesOffset];
       
   182 		}
       
   183 	ret = iLdd.SetConfigurationDescriptor(configDescriptor);
       
   184 
       
   185 	return ret;
       
   186 	}
       
   187 
       
   188 
       
   189 /**
       
   190 Set up interface descriptor
       
   191 
       
   192 @return KErrNone if operation was completed successfully, errorcode otherwise
       
   193 */
       
   194 TInt CBulkOnlyTransport::SetupInterfaceDescriptors()
       
   195 	{
       
   196     __MSFNLOG
       
   197 	// Device caps
       
   198 	TUsbDeviceCaps d_caps;
       
   199 	TInt ret = iLdd.DeviceCaps(d_caps);
       
   200 	if (ret != KErrNone)
       
   201 		{
       
   202 		return ret;
       
   203 		}
       
   204 	TInt totalEndpoints = d_caps().iTotalEndpoints;
       
   205 	if (totalEndpoints  < KRequiredNumberOfEndpoints)
       
   206 		{
       
   207 		return KErrHardwareNotAvailable;
       
   208 		}
       
   209 
       
   210 	// Endpoint caps
       
   211 	TUsbcEndpointData data[KUsbcMaxEndpoints];
       
   212 	TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data));
       
   213 	ret = iLdd.EndpointCaps(dataptr);
       
   214 	if (ret != KErrNone)
       
   215 		{
       
   216 		return ret;
       
   217 		}
       
   218 
       
   219 	// Set the active interface
       
   220 	TUsbcInterfaceInfoBuf ifc;
       
   221 	TInt ep_found = 0;
       
   222 	TBool foundBulkIN = EFalse;
       
   223 	TBool foundBulkOUT = EFalse;
       
   224 
       
   225 	for (TInt i = 0; i < totalEndpoints ; i++)
       
   226 		{
       
   227 		const TUsbcEndpointCaps* caps = &data[i].iCaps;
       
   228 		const TInt maxPacketSize = caps->MaxPacketSize();
       
   229 		if (!foundBulkIN &&
       
   230 			(caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirIn)) == (KUsbEpTypeBulk | KUsbEpDirIn))
       
   231 			{
       
   232 			// KInEndpoint is going to be our TX (IN, write) endpoint
       
   233 			ifc().iEndpointData[0].iType = KUsbEpTypeBulk;
       
   234 			ifc().iEndpointData[0].iDir  = KUsbEpDirIn;
       
   235 			ifc().iEndpointData[0].iSize = maxPacketSize;
       
   236 			ifc().iEndpointData[0].iInterval_Hs = 0;
       
   237 			foundBulkIN = ETrue;
       
   238 			if (++ep_found == KRequiredNumberOfEndpoints)
       
   239 				{
       
   240 				break;
       
   241 				}
       
   242 			continue;
       
   243 			}
       
   244 		if (!foundBulkOUT &&
       
   245 			(caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirOut)) == (KUsbEpTypeBulk | KUsbEpDirOut))
       
   246 			{
       
   247 			// KOutEndpoint is going to be our RX (OUT, read) endpoint
       
   248 			ifc().iEndpointData[1].iType = KUsbEpTypeBulk;
       
   249 			ifc().iEndpointData[1].iDir  = KUsbEpDirOut;
       
   250 			ifc().iEndpointData[1].iSize = maxPacketSize;
       
   251 			ifc().iEndpointData[1].iInterval_Hs = 0;
       
   252 			foundBulkOUT = ETrue;
       
   253 			if (++ep_found == KRequiredNumberOfEndpoints)
       
   254 				{
       
   255 				break;
       
   256 				}
       
   257 			continue;
       
   258 			}
       
   259 		}
       
   260 	if (ep_found != KRequiredNumberOfEndpoints)
       
   261 		{
       
   262 		return KErrHardwareNotAvailable;
       
   263 		}
       
   264 
       
   265 	_LIT16(string, "USB Mass Storage Interface");
       
   266 	ifc().iString = const_cast<TDesC16*>(&string);
       
   267 	ifc().iTotalEndpointsUsed = KRequiredNumberOfEndpoints;
       
   268 	ifc().iClass.iClassNum    = 0x08;	// Mass Storage
       
   269 	ifc().iClass.iSubClassNum = 0x06;	// SCSI Transparent Command Set
       
   270 	ifc().iClass.iProtocolNum = 0x50;	// Bulk Only Transport
       
   271 
       
   272 	TUint bandwidth_priority = (EUsbcBandwidthOUTDefault | EUsbcBandwidthINDefault);
       
   273 	if (d_caps().iHighSpeed)
       
   274 		{
       
   275 		// If this device supports USB High-speed, then we request 64KB buffers
       
   276 		// (otherwise the default 4KB ones will do).
       
   277 		bandwidth_priority = (EUsbcBandwidthOUTPlus2 | EUsbcBandwidthINPlus2);
       
   278 		// Also, tell the Protocol about it, because it might want to do some
       
   279 		// optimizing too.
       
   280 		iProtocol->ReportHighSpeedDevice();
       
   281 		}
       
   282 	ret = iLdd.SetInterface(0, ifc, bandwidth_priority);
       
   283 	return ret;
       
   284 	}
       
   285 
       
   286 
       
   287 /**
       
   288 Called by the protocol after processing the packet to indicate that more data is required.
       
   289 
       
   290 @param aData reference to the data buffer.
       
   291 */
       
   292 void CBulkOnlyTransport::SetupDataOut(TPtr8& aData)
       
   293     {
       
   294     __MSFNLOG
       
   295     iDataTransferMan.SetModeDataOut(aData);
       
   296     }
       
   297 
       
   298 /**
       
   299 Called by the protocol after processing the packet to indicate that data should be written to the host.
       
   300 
       
   301 @param aData reference to the data buffer.
       
   302 */
       
   303 void CBulkOnlyTransport::SetupDataIn(TPtrC8& aData)
       
   304 	{
       
   305     iDataTransferMan.SetModeDataIn(aData);
       
   306 	}
       
   307 
       
   308 
       
   309 TInt CBulkOnlyTransport::Start()
       
   310 	{
       
   311     __MSFNLOG
       
   312 	TInt err = KErrNone;
       
   313 
       
   314 	if (!iProtocol)
       
   315 		{
       
   316 		return KErrBadHandle;   //protocol should be set up before start
       
   317 		}
       
   318 
       
   319 	if (IsActive())
       
   320 		{
       
   321 		__PRINT(_L("CBulkOnlyTransport::Start  - active before start!\n"));
       
   322 		return KErrInUse;
       
   323 		}
       
   324 
       
   325 	if ((err = iLdd.Open(0))					!= KErrNone ||
       
   326 		(err = SetupConfigurationDescriptor()) 	!= KErrNone ||
       
   327 		(err = SetupInterfaceDescriptors())		!= KErrNone )
       
   328 		{
       
   329 		__PRINT(_L("CBulkOnlyTransport::Start  - Error during descriptors setup!\n"));
       
   330 		return err;
       
   331 		}
       
   332 
       
   333 	iDeviceStateNotifier->Activate();  // activate notifier wich will wait until USB became configured
       
   334 	TUsbcDeviceState deviceStatus = EUsbcDeviceStateDefault;
       
   335 	err = iLdd.DeviceStatus(deviceStatus);
       
   336 	__PRINT1(_L("CBulkOnlyTransport::Start - Device status = %d\n"), deviceStatus);
       
   337 	if (err == KErrNone && deviceStatus == EUsbcDeviceStateConfigured)
       
   338 		{
       
   339 		__PRINT(_L("CBulkOnlyTransport::Start  - Starting bulk only transport\n"));
       
   340 		err = HwStart();
       
   341 		}
       
   342 	iInterfaceConfigured = ETrue;
       
   343 	return err;
       
   344 	}
       
   345 
       
   346 TInt CBulkOnlyTransport::HwStart(TBool aDiscard)
       
   347 	{
       
   348     __MSFNLOG
       
   349 
       
   350     TInt lun = MaxLun();
       
   351     do
       
   352         {
       
   353         Controller().DriveManager().Connect(lun);
       
   354         }
       
   355     while(--lun >= 0);
       
   356 
       
   357 	TInt res = iBotControlInterface->Start() ;
       
   358 
       
   359 	iCurrentState = ENone;
       
   360     iDataTransferMan.Init();
       
   361 	iStarted = ETrue;
       
   362 
       
   363 	// Set up DMA if possible (errors are non-critical)
       
   364 	TInt err = iLdd.AllocateEndpointResource(KOutEndpoint, EUsbcEndpointResourceDMA);
       
   365 	if (err != KErrNone)
       
   366 		{
       
   367 		__PRINT1(_L("Set DMA on OUT endpoint failed with error code: %d"), err);
       
   368 		}
       
   369 	err = iLdd.AllocateEndpointResource(KInEndpoint, EUsbcEndpointResourceDMA);
       
   370 	if (err != KErrNone)
       
   371 		{
       
   372 		__PRINT1(_L("Set DMA on IN endpoint failed with error code: %d"), err);
       
   373 		}
       
   374 
       
   375 	// Set up Double Buffering if possible (errors are non-critical)
       
   376 	err = iLdd.AllocateEndpointResource(KOutEndpoint, EUsbcEndpointResourceDoubleBuffering);
       
   377 	if (err != KErrNone)
       
   378 		{
       
   379 		__PRINT1(_L("Set Double Buffering on OUT endpoint failed with error code: %d"), err);
       
   380 		}
       
   381 	err = iLdd.AllocateEndpointResource(KInEndpoint, EUsbcEndpointResourceDoubleBuffering);
       
   382 	if (err != KErrNone)
       
   383 		{
       
   384 		__PRINT1(_L("Set Double Buffering on IN endpoint failed with error code: %d"), err);
       
   385 		}
       
   386 
       
   387     if (aDiscard)
       
   388 		{
       
   389 		TInt bytes;
       
   390 		const TInt err = iLdd.QueryReceiveBuffer(KOutEndpoint, bytes);
       
   391 		if (err != KErrNone || bytes <= 0)
       
   392 			{
       
   393 			__PRINT1(_L("Error: err=%d bytes=%d"), bytes);
       
   394 			}
       
   395 		else
       
   396 			{
       
   397 			__PRINT1(_L("RxBuffer has %d bytes"), bytes);
       
   398 			FlushDataOut(bytes);
       
   399 			}
       
   400 		}
       
   401 
       
   402 	ClientReadCbw();
       
   403 	return res;
       
   404 	}
       
   405 
       
   406 
       
   407 void CBulkOnlyTransport::HwStop()
       
   408 	{
       
   409     __MSFNLOG
       
   410 	if (iStarted)
       
   411 		{
       
   412         iController.DriveManager().Disconnect();
       
   413 		Cancel();
       
   414 		iBotControlInterface->Cancel();
       
   415 		iProtocol->Cancel();
       
   416 		iStarted = EFalse;
       
   417 		}
       
   418 	}
       
   419 
       
   420 
       
   421 void CBulkOnlyTransport::HwSuspend()
       
   422 	{
       
   423     __MSFNLOG
       
   424     iController.DriveManager().Disconnect();
       
   425 	}
       
   426 
       
   427 
       
   428 void CBulkOnlyTransport::HwResume()
       
   429 	{
       
   430     __MSFNLOG
       
   431     iController.DriveManager().Connect();
       
   432 	}
       
   433 
       
   434 
       
   435 /**
       
   436 Stops the Bulk Only Transport
       
   437 */
       
   438 TInt CBulkOnlyTransport::Stop()
       
   439 	{
       
   440     __MSFNLOG
       
   441 	iBotControlInterface->Cancel();
       
   442 	iDeviceStateNotifier->Cancel();
       
   443 	Cancel();
       
   444 	if  (iInterfaceConfigured)
       
   445 		{
       
   446 		iLdd.ReleaseInterface(0);
       
   447 		SetupConfigurationDescriptor(ETrue);
       
   448 		iLdd.Close();
       
   449 		}
       
   450 	iCurrentState = ENone;
       
   451 	iInterfaceConfigured = EFalse;
       
   452 
       
   453 	return KErrNone;
       
   454 	}
       
   455 
       
   456 
       
   457 /**
       
   458 Read aLength bytes of data from the host into the read buffer.
       
   459 @param aLength The number of bytes to read from the host.
       
   460 */
       
   461 void CBulkOnlyTransport::ClientReadCbw()
       
   462 	{
       
   463     __MSFNLOG
       
   464 	if (IsActive())
       
   465 		{
       
   466 		__PRINT(_L("Still active\n"));
       
   467 		__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsClientPanicCat, EMsBulkOnlyStillActive));
       
   468 		return;
       
   469 		}
       
   470 
       
   471     ReadCbw();
       
   472     }
       
   473 
       
   474 
       
   475 void CBulkOnlyTransport::ReadCbw()
       
   476 	{
       
   477     __MSFNLOG
       
   478 	iCbwBuf.SetMax();
       
   479 	iLdd.ReadUntilShort(iStatus, KOutEndpoint, iCbwBuf, iCbwBuf.Length());
       
   480 	iCurrentState = EWaitForCBW;
       
   481 	SetActive();
       
   482 	}
       
   483 
       
   484 
       
   485 void CBulkOnlyTransport::DoCancel()
       
   486 	{
       
   487     __MSFNLOG
       
   488 	iLdd.WriteCancel(KInEndpoint);
       
   489 	iLdd.ReadCancel(KOutEndpoint);
       
   490 	}
       
   491 
       
   492 
       
   493 void CBulkOnlyTransport::Activate(TInt aReason)
       
   494     {
       
   495     __MSFNLOG
       
   496     SetActive();
       
   497     TRequestStatus* r = &iStatus;
       
   498     User::RequestComplete(r, aReason);
       
   499     }
       
   500 
       
   501 
       
   502 void CBulkOnlyTransport::RunL()
       
   503 	{
       
   504     __MSFNLOG
       
   505 	if (iStatus != KErrNone)
       
   506 		{
       
   507 		__PRINT1(_L("Error %d in RunL, halt endpoints \n"), iStatus.Int());
       
   508 		SetPermError(); //halt endpoints for reset recovery
       
   509 		return;
       
   510 		}
       
   511 
       
   512 	switch (iCurrentState)
       
   513 		{
       
   514         case EWaitForCBW:
       
   515             __PRINT(_L("EWaitForCBW"));
       
   516             TRAPD(err, DecodeCbwL());
       
   517             if (err)
       
   518                 {
       
   519                 // CBW not valid or meaningful
       
   520                 // Specification says: "If the CBW is not valid, the device
       
   521                 // shall STALL the Bulk-In pipe. Also, the device shall either
       
   522                 // STALL the Bulk-Out pipe, or the device shall accept and
       
   523                 // discard any Bulk-Out data. The device shall maintain this
       
   524                 // state until a Reset Recovery." Here we keep bulk-in ep
       
   525                 // stalled and ignore bulk-out ep.
       
   526                 SetPermError();
       
   527                 return;
       
   528                 }
       
   529 			break;
       
   530 
       
   531         case EHandleDataIn:
       
   532             {
       
   533             __PRINT(_L("EHandleDataIn"));
       
   534             iDataTransferMan.SetModeNoData();
       
   535 
       
   536 			if (iDataTransferMan.iDataResidue && iStallAllowed)
       
   537 				{
       
   538 				StallEndpointAndWaitForClear(KInEndpoint);
       
   539 				}
       
   540 #ifdef MSDC_TESTMODE
       
   541             if (iTestParser && iTestParser->Enabled())
       
   542                 {
       
   543                 if (iTestParser->TestCase() == TTestParser::ETestCaseDiStallCsw)
       
   544                     {
       
   545                     iTestParser->ClrTestCase();
       
   546                     __TESTMODEPRINT1("CBW Tag=0x%x: Stalling CSW Data-In", iCbwTag);
       
   547                     StallEndpointAndWaitForClear(KInEndpoint);
       
   548                     }
       
   549                 }
       
   550 #endif
       
   551 			SendCsw(iCbwTag, iDataTransferMan.iDataResidue, iCmdStatus);
       
   552             }
       
   553 			break;
       
   554 
       
   555 		case EHandleDataOut:
       
   556 			{
       
   557             TUint bytesWritten;
       
   558             TInt ret = iProtocol->MediaWritePacket(bytesWritten);
       
   559             iDataTransferMan.iDataResidue -= bytesWritten;
       
   560 
       
   561 			switch(ret)
       
   562                 {
       
   563             case KErrCompletion:
       
   564                 {
       
   565                 // The protocol has indicated with KErrCompletion that
       
   566                 // sufficient data is available in the buffer to process the
       
   567                 // transfer immediately.
       
   568 
       
   569                 TInt deviceDataLength = iDataTransferMan.iReadBuf.Length();
       
   570                 iLdd.Read(iStatus, KOutEndpoint, iDataTransferMan.iReadBuf, deviceDataLength);
       
   571                 SetActive();
       
   572                 }
       
   573                 break;
       
   574             case KErrNotReady:
       
   575                 {
       
   576                 // The protocol has indicated with KErrNotReady that
       
   577                 // insufficient data is available in the buffer, so should wait
       
   578                 // for it to arrive.
       
   579                 TInt deviceDataLength = iDataTransferMan.iReadBuf.Length();
       
   580                 iLdd.Read(iStatus, KOutEndpoint, iDataTransferMan.iReadBuf, deviceDataLength);
       
   581                 SetActive();
       
   582                 }
       
   583                 break;
       
   584             case KErrAbort:
       
   585                 {
       
   586                 iDataTransferMan.SetModeNoData();
       
   587                 iCmdStatus = TBotCsw::ECommandFailed;
       
   588                 if (iDataTransferMan.iDataResidue)
       
   589                     {
       
   590                     __PRINT(_L("Discarding residue"));
       
   591                     FlushDataOut(iDataTransferMan.iTransportResidue);
       
   592                     }
       
   593                 SendCsw(iCbwTag, iDataTransferMan.iDataResidue, iCmdStatus);
       
   594                 }
       
   595                 break;
       
   596 
       
   597             case KErrNone:
       
   598             default:
       
   599                 {
       
   600                 // The protocol has indicated that transfer is complete, so
       
   601                 // send the CSW response to the host.
       
   602                 iDataTransferMan.SetModeNoData();
       
   603 #ifdef MSDC_TESTMODE
       
   604                 if (iDataTransferMan.iDataResidue)
       
   605                     {
       
   606                     TBool done = EFalse;
       
   607                     if (iTestParser && iTestParser->Enabled())
       
   608                         {
       
   609                         TInt testCase = iTestParser->TestCase();
       
   610                         if (testCase == TTestParser::ETestCaseDoStallCsw)
       
   611                             {
       
   612                             iTestParser->ClrTestCase();
       
   613                             __TESTMODEPRINT1("CBW Tag=0x%x: Stalling CSW Data-Out", iCbwTag);
       
   614                             StallEndpointAndWaitForClear(KInEndpoint);
       
   615                             done = ETrue;
       
   616                             }
       
   617                         }
       
   618                     if (!done)
       
   619                         {
       
   620                         __PRINT(_L("Discarding residue"));
       
   621                         // we have to read as much data as available that host PC
       
   622                         // sends; otherwise, bulk-out endpoint will need to keep
       
   623                         // sending NAK back.
       
   624                         FlushDataOut(iDataTransferMan.iDataResidue);
       
   625                         __TESTMODEPRINT2("CBW Tag=0x%x: Residue = x%x",
       
   626                                          iCbwTag, iDataTransferMan.iDataResidue);
       
   627                         }
       
   628                     }
       
   629                 else
       
   630                     {
       
   631                     if (iTestParser && iTestParser->Enabled())
       
   632                         {
       
   633                         TInt testCase = iTestParser->TestCase();
       
   634                         if (testCase == TTestParser::ETestCaseDoStallCsw)
       
   635                             {
       
   636                             iTestParser->ClrTestCase();
       
   637                             __TESTMODEPRINT1("CBW Tag=0x%x: Stalling CSW Data-Out", iCbwTag);
       
   638                             StallEndpointAndWaitForClear(KInEndpoint);
       
   639                             }
       
   640                         }
       
   641                     }
       
   642 
       
   643 #else
       
   644                     if (iDataTransferMan.iDataResidue)
       
   645                         {
       
   646                         __PRINT(_L("Discarding residue"));
       
   647                         // we have to read as much data as available that host PC
       
   648                         // sends; otherwise, bulk-out endpoint will need to keep
       
   649                         // sending NAK back.
       
   650                         FlushDataOut(iDataTransferMan.iDataResidue);
       
   651                         }
       
   652 #endif
       
   653                 SendCsw(iCbwTag, iDataTransferMan.iDataResidue, iCmdStatus);
       
   654                 }
       
   655                 break;  // KErrNone
       
   656                 } // switch
       
   657             }
       
   658 			break;  // EReadingData
       
   659 
       
   660 		case ESendingCSW:
       
   661 			__PRINT(_L("ESendingCSW"));
       
   662 			ReadCbw();
       
   663 			break;
       
   664 
       
   665         case EPermErr:
       
   666 			__PRINT(_L("EPermErr"));
       
   667 			StallEndpointAndWaitForClear(KInEndpoint);
       
   668             break;
       
   669 
       
   670         default:
       
   671 			SetPermError();		// unexpected state
       
   672 		}
       
   673 	}
       
   674 
       
   675 
       
   676 /**
       
   677 Decode the CBW received from the host via KOutEndpoint
       
   678 
       
   679 - If the header is valid, the data content is passed to the parser.
       
   680 - Depending on the command, more data may be transmitted/received.
       
   681 - ...or the CSW is sent (if not a data command).
       
   682 
       
   683 */
       
   684 void CBulkOnlyTransport::DecodeCbwL()
       
   685 	{
       
   686     __MSFNLOG
       
   687     TBotServerReq req;
       
   688     req.DecodeL(iCbwBuf);
       
   689 
       
   690     if (!(req.IsValidCbw() && req.IsMeaningfulCbw(iMaxLun)))
       
   691         {
       
   692         User::Leave(KErrGeneral);
       
   693         }
       
   694 
       
   695     TPtrC8 aData(&iCbwBuf[TBotCbw::KCbwCbOffset], TBotCbw::KMaxCbwcbLength);
       
   696 	//aData.Set(&iCbwBuf[TBotCbw::KCbwCbOffset], TBotCbw::KMaxCbwcbLength);
       
   697     TUint8 lun = req.Lun();
       
   698 
       
   699     iCbwTag  = 	req.Tag();
       
   700     TUint32 hostDataLength = req.DataTransferLength();
       
   701     iDataTransferMan.SetHostDataLen(hostDataLength);
       
   702 
       
   703     TBotServerReq::TCbwDirection dataToHost = req.Direction();
       
   704 
       
   705     __PRINT4(_L("lun =%d, hostDataLength=%d, CBWtag = 0x%X\n, dataToHost=%d\n"),
       
   706              lun, hostDataLength, iCbwTag, dataToHost);
       
   707 
       
   708 	//////////////////////////////////////////////
       
   709 	TBool ret = iProtocol->DecodePacket(aData, lun);
       
   710 	//////////////////////////////////////////////
       
   711 
       
   712 	iStallAllowed = ETrue;
       
   713 
       
   714 	if (!ret)
       
   715 		{
       
   716 		__PRINT(_L("Command Failed\n"));
       
   717 		iCmdStatus = TBotCsw::ECommandFailed;
       
   718 		}
       
   719 	else
       
   720 		{
       
   721 		__PRINT(_L("Command Passed\n"));
       
   722 		iCmdStatus = TBotCsw::ECommandPassed;
       
   723 		}
       
   724 
       
   725 	if (hostDataLength)    // Host expected data transfer
       
   726 		{
       
   727 		if (dataToHost == TBotServerReq::EDataIn)  // send data to host
       
   728 			{
       
   729             if (!iDataTransferMan.IsModeDataIn())
       
   730 				{
       
   731 				__PRINT(_L("Write buffer was not setup\n"));
       
   732 
       
   733 				if (hostDataLength <= KBOTMaxBufSize)
       
   734 					{
       
   735 					// Case 4 or 8"
       
   736 					iBuf.FillZ(hostDataLength);
       
   737 					iLdd.Write(iStatus, KInEndpoint, iBuf, hostDataLength);
       
   738 					SetActive();
       
   739 					iCurrentState = EHandleDataIn;
       
   740 					iStallAllowed = EFalse;
       
   741 					if (iDataTransferMan.IsModeDataOut())
       
   742 						{
       
   743                         //read buffer WAS set up - case (8)
       
   744 						iCmdStatus = TBotCsw::EPhaseError;
       
   745 						}
       
   746 					return;
       
   747 					}
       
   748 				else
       
   749 					{
       
   750                     // Use next block instead of StallEndpointAndWaitForClear(KInEndpoint);
       
   751                     FlushDataIn(hostDataLength);
       
   752 					}
       
   753 
       
   754 				if (iDataTransferMan.IsModeDataOut())
       
   755 					{
       
   756                     //read buffer WAS set up - case (8)
       
   757 					SendCsw(iCbwTag, hostDataLength, TBotCsw::EPhaseError);
       
   758 					//don't care to reset any flag - should get reset recovery
       
   759 					}
       
   760 				else
       
   761 					{
       
   762                     // case (4)
       
   763 					SendCsw(iCbwTag, hostDataLength, iCmdStatus);
       
   764 					}
       
   765 				return;
       
   766 				}
       
   767 
       
   768 //==================
       
   769 			TInt deviceDataLength = iDataTransferMan.iWriteBuf.Length();
       
   770             iDataTransferMan.iDataResidue = hostDataLength - deviceDataLength;
       
   771 
       
   772 #ifdef MSDC_TESTMODE
       
   773             if (iTestParser && iTestParser->Enabled())
       
   774                 {
       
   775                 TInt testCase = iTestParser->TestCase();
       
   776                 if (testCase == TTestParser::ETestCaseDiResidue)
       
   777                     {
       
   778                     __TESTMODEPRINT2("DataIN (Data Residue) %x %x", iTestParser->TestCounter(), hostDataLength);
       
   779 
       
   780                     const TInt KTransferLength = 0x100;
       
   781                     const TInt KResidueA = KTransferLength/4 -10;
       
   782                     const TInt KResidueB = KTransferLength/4 - 10;
       
   783                     if (hostDataLength > KTransferLength)
       
   784                         {
       
   785                         TInt residue = 0;
       
   786                         TInt i = iTestParser->TestCounter();
       
   787                         switch (i)
       
   788                             {
       
   789                             case 0:
       
   790                                 iTestParser->ClrTestCase();
       
   791                                 break;
       
   792                             case 1:
       
   793                                 residue = KResidueA;
       
   794                                 break;
       
   795                             case 2:
       
   796                                 residue = KResidueB;
       
   797                                 break;
       
   798 
       
   799                             default:
       
   800                                 break;
       
   801                             }
       
   802 
       
   803                         //deviceDataLength -= residue;
       
   804                         iDataTransferMan.iDataResidue = residue;
       
   805                         iStallAllowed = EFalse;
       
   806                         iTestParser->DecTestCounter();
       
   807 
       
   808                         __TESTMODEPRINT4("CBW Tag=0x%x: Setting Residue (Data-In) hdl=%x ddl=%x residue=%x",
       
   809                                          iCbwTag, hostDataLength, deviceDataLength, residue);
       
   810                         }
       
   811                     }
       
   812                 }
       
   813 #endif
       
   814 			if (deviceDataLength < hostDataLength && hostDataLength <= KBOTMaxBufSize)
       
   815 				{
       
   816                 // do not pad
       
   817                 // iStallAllowed = ETrue;
       
   818                 // __PRINT1(_L("iBuf.Length=%d\n"),iBuf.Length());
       
   819                 // iLdd.Write(iStatus, KInEndpoint, iBuf, deviceDataLength);
       
   820                 // SetActive();
       
   821                 //iCurrentState = EWritingData;
       
   822 
       
   823                 // pad
       
   824                 iBuf.Zero();
       
   825                 iBuf.Append(iDataTransferMan.iWriteBuf);
       
   826                 iBuf.SetLength(hostDataLength);
       
   827                 iStallAllowed = EFalse;
       
   828                 __PRINT1(_L("iBuf.Length=%d\n"),iBuf.Length());
       
   829                 iLdd.Write(iStatus, KInEndpoint, iBuf, hostDataLength);
       
   830                 SetActive();
       
   831                 iCurrentState = EHandleDataIn;
       
   832 
       
   833 				return;
       
   834 				}
       
   835 
       
   836 			if (deviceDataLength == hostDataLength)
       
   837 				{
       
   838                 //case (6)[==]
       
   839 #ifdef MSDC_TESTMODE
       
   840                 if (iTestParser && iTestParser->Enabled())
       
   841                     {
       
   842                     if (iTestParser->TestCase() == TTestParser::ETestCaseDiStallData)
       
   843                         {
       
   844                         iTestParser->ClrTestCase();
       
   845                         __TESTMODEPRINT1("CBW Tag=0x%x: Stalling CSW Data-In", iCbwTag);
       
   846                         StallEndpointAndWaitForClear(KInEndpoint);
       
   847                         }
       
   848                     }
       
   849 #endif
       
   850 
       
   851 				DataInWriteRequest(deviceDataLength);
       
   852 				return;
       
   853 				}
       
   854 			else if (deviceDataLength < hostDataLength)
       
   855 				{
       
   856                 //case (5)[<]
       
   857 				DataInWriteRequest(deviceDataLength, ETrue);		// Send ZLP
       
   858 				return;
       
   859 				}
       
   860 			else
       
   861 				{
       
   862                 // deviceDataLength > hostDataLength - case (7)
       
   863 				iCmdStatus = TBotCsw::EPhaseError;
       
   864 				iDataTransferMan.iDataResidue = 0;
       
   865 				DataInWriteRequest(hostDataLength);
       
   866 				return;
       
   867 				}
       
   868 			}
       
   869 		else  // read data from host
       
   870 			{
       
   871 			if (!iDataTransferMan.IsModeDataOut())
       
   872 				{
       
   873 				__PRINT(_L("Read buffer was not setup\n"));
       
   874 
       
   875                 // Use next block instead of StallEndpointAndWaitForClear(KOutEndpoint);
       
   876                 FlushDataOut(hostDataLength);
       
   877 				if (iDataTransferMan.IsModeDataIn())
       
   878 					{
       
   879                     //case (10)
       
   880 					SendCsw(iCbwTag, hostDataLength, TBotCsw::EPhaseError);
       
   881 					}
       
   882 				else
       
   883 					{
       
   884                     // case (9)
       
   885 					SendCsw(iCbwTag, hostDataLength, iCmdStatus);
       
   886 					}
       
   887 				return;
       
   888 				}
       
   889 
       
   890 			TInt deviceDataLength = iDataTransferMan.iReadBuf.Length();
       
   891 
       
   892 			if (deviceDataLength <= hostDataLength)
       
   893 				{
       
   894                 // case (11) and (12)
       
   895 #ifdef MSDC_TESTMODE
       
   896                 TBool done = EFalse;
       
   897                 if (iTestParser && iTestParser->Enabled())
       
   898                     {
       
   899                     TInt testCase = iTestParser->TestCase();
       
   900 
       
   901                     if (testCase == TTestParser::ETestCaseDoStallData)
       
   902                         {
       
   903                         iTestParser->ClrTestCase();
       
   904                         // Stall Data Out
       
   905                         __TESTMODEPRINT2("CBW Tag=0x%x:  Stalling Data (Data-Out) Residue = x%x",
       
   906                                          iCbwTag, iDataTransferMan.iDataResidue);
       
   907                         StallEndpointAndWaitForClear(KOutEndpoint);
       
   908                         TInt bytes;
       
   909                         const TInt err = iLdd.QueryReceiveBuffer(KOutEndpoint, bytes);
       
   910                         __PRINT1(_L("Error: err=%d bytes=%d"), bytes);
       
   911                         FlushDataOut(bytes);
       
   912                         }
       
   913                     }
       
   914                 if (!done)
       
   915                     {
       
   916                     DataOutReadRequest(deviceDataLength);
       
   917                     }
       
   918 #else
       
   919 				DataOutRead(deviceDataLength);
       
   920 #endif
       
   921 				return;
       
   922 				}
       
   923 			else
       
   924 				{
       
   925                 // case  (13)
       
   926                 /**
       
   927                  * Comment following line in order to pass compliant test.
       
   928                  * As spec said in case 13:"The device may receive data up to a
       
   929                  * total of dCBWDataTransferLength."
       
   930                  * Here we choose to ignore incoming data.
       
   931                  */
       
   932 				//StallEndpointAndWaitForClear(KOutEndpoint); //Stall Out endpoint
       
   933                 if (iDataTransferMan.IsModeDataOut())
       
   934                     {
       
   935                     iDataTransferMan.SetModeNoData();
       
   936                     iLdd.Read(iStatus, KOutEndpoint, iDataTransferMan.iReadBuf, hostDataLength);
       
   937                     User::WaitForRequest(iStatus);
       
   938                     iProtocol->MediaWriteAbort();
       
   939                     }
       
   940                 SendCsw(iCbwTag, hostDataLength, TBotCsw::EPhaseError);
       
   941 				return;
       
   942 				}
       
   943 			}
       
   944 		}
       
   945 	else  // Host expected no data transfer
       
   946 		{
       
   947 		__PRINT(_L("No data transfer expected\n"));
       
   948 		iDataTransferMan.iDataResidue = 0;
       
   949 		if (!iDataTransferMan.IsModeNoData())
       
   950 			{
       
   951             // case (2) and (3)
       
   952 			SendCsw(iCbwTag, 0, TBotCsw::EPhaseError);
       
   953 			}
       
   954 		else
       
   955 			{
       
   956             //case (1)
       
   957 #ifdef MSDC_TESTMODE
       
   958             if (iTestParser && iTestParser->Enabled())
       
   959                 {
       
   960                 TInt testCase = iTestParser->TestCase();
       
   961                 if (testCase == TTestParser::ETestCaseNoDataStallCsw)
       
   962                     {
       
   963                     __TESTMODEPRINT1("CBW Tag=0x%x: Stalling CSW for Case 1 (Hn=Dn)", iCbwTag);
       
   964                     iTestParser->ClrTestCase();
       
   965                     StallEndpointAndWaitForClear(KInEndpoint);
       
   966                     }
       
   967 
       
   968                 if (testCase == TTestParser::ETestCaseNoDataPhaseError)
       
   969                     {
       
   970                     __TESTMODEPRINT1("CBW Tag=0x%x: Enabling phase error (no data)", iCbwTag);
       
   971                     iTestParser->SetPhaseError();
       
   972                     }
       
   973                 }
       
   974 #endif
       
   975 			SendCsw(iCbwTag, 0, iCmdStatus);
       
   976 			}
       
   977 		}
       
   978 	}
       
   979 
       
   980 
       
   981 /**
       
   982 Initiate stalling of bulk IN endpoint.
       
   983 Used when protocol wants to force host to initiate a reset recovery.
       
   984 */
       
   985 void CBulkOnlyTransport::SetPermError()
       
   986 	{
       
   987     __MSFNLOG
       
   988     iCurrentState = EPermErr;
       
   989     Activate(KErrNone);
       
   990 	}
       
   991 
       
   992 
       
   993 /**
       
   994 Send data provided by protocol to the host
       
   995 
       
   996 @param aLength amount of data (in bytes) to be send to host
       
   997 */
       
   998 void CBulkOnlyTransport::DataInWriteRequest(TUint aLength, TBool aZlpRequired)
       
   999 	{
       
  1000     __MSFNLOG
       
  1001 	iLdd.Write(iStatus, KInEndpoint, iDataTransferMan.iWriteBuf, aLength, aZlpRequired);
       
  1002     iDataTransferMan.iTransportResidue -= aLength;
       
  1003 	iCurrentState = EHandleDataIn;
       
  1004 	SetActive();
       
  1005 	}
       
  1006 
       
  1007 
       
  1008 /**
       
  1009 Request data form the host for the protocol
       
  1010 
       
  1011 @param aLength amount of data (in bytes) to be received from the host
       
  1012 */
       
  1013 void CBulkOnlyTransport::DataOutReadRequest(TUint aLength)
       
  1014 	{
       
  1015     __MSFNLOG
       
  1016 	iLdd.Read(iStatus, KOutEndpoint, iDataTransferMan.iReadBuf, aLength);
       
  1017 	iDataTransferMan.iTransportResidue -= aLength;
       
  1018 	iCurrentState = EHandleDataOut;
       
  1019     SetActive();
       
  1020 	}
       
  1021 
       
  1022 
       
  1023 /**
       
  1024 Send Command Status Wrapper to the host
       
  1025 
       
  1026 @param aTag Echo of Command Block Tag sent by the host.
       
  1027 @param aDataResidue the difference between the amount of data expected by the
       
  1028        host, and the actual amount of data processed by the device.
       
  1029 @param aStatus indicates the success or failure of the command.
       
  1030 */
       
  1031 void CBulkOnlyTransport::SendCsw(TUint aTag, TUint32 aDataResidue, TBotCsw::TCswStatus aStatus)
       
  1032 	{
       
  1033     __MSFNLOG
       
  1034 	__PRINT2(_L("DataResidue = %d, Status = %d \n"), aDataResidue, aStatus);
       
  1035     iCsw.SetLength(TBotCsw::KCswLength);
       
  1036     TBotServerResp resp(iCbwTag, aDataResidue, aStatus);
       
  1037 #ifdef MSDC_TESTMODE
       
  1038     resp.EncodeL(iCsw, iTestParser);
       
  1039 #else
       
  1040     resp.EncodeL(iCsw);
       
  1041 #endif
       
  1042 	iLdd.Write(iStatus, KInEndpoint, iCsw, TBotCsw::KCswLength);
       
  1043 	iCurrentState = ESendingCSW;
       
  1044 	SetActive();
       
  1045 	}
       
  1046 
       
  1047 
       
  1048 /**
       
  1049 Associates the transport with the protocol.  Called during initialization of the controller.
       
  1050 
       
  1051 @param aProtocol reference to the protocol
       
  1052 */
       
  1053 void CBulkOnlyTransport::RegisterProtocol(MServerProtocol& aProtocol)
       
  1054 	{
       
  1055     __MSFNLOG
       
  1056 	iProtocol = &aProtocol;
       
  1057 	}
       
  1058 
       
  1059 
       
  1060 /**
       
  1061 Used by CControlInterface
       
  1062 
       
  1063 @return reference to the controller which instantiate the CBulkOnlyTransport
       
  1064 */
       
  1065 CUsbMassStorageController& CBulkOnlyTransport::Controller()
       
  1066 	{
       
  1067 	return iController;
       
  1068 	}
       
  1069 
       
  1070 
       
  1071 /**
       
  1072 @return the number of logical units supported by the device.
       
  1073 Logical Unit Numbers on the device shall be numbered contiguously starting from LUN
       
  1074 0 to a maximum LUN of 15 (Fh).
       
  1075 */
       
  1076 TInt CBulkOnlyTransport::MaxLun()
       
  1077 	{
       
  1078     __MSFNLOG
       
  1079 	return iMaxLun;
       
  1080 	}
       
  1081 
       
  1082 
       
  1083 /**
       
  1084 Used by CControlInterface
       
  1085 @return reference to USB logical driver
       
  1086 */
       
  1087 RDevUsbcClient& CBulkOnlyTransport::Ldd()
       
  1088 	{
       
  1089 	return iLdd;
       
  1090 	}
       
  1091 
       
  1092 
       
  1093 void CBulkOnlyTransport::StallEndpointAndWaitForClear(TEndpointNumber aEndpoint)
       
  1094 	{
       
  1095     __MSFNLOG
       
  1096 	__ASSERT_DEBUG(aEndpoint != EEndpoint0, User::Panic(KUsbMsClientPanicCat, EMsWrongEndpoint));
       
  1097 
       
  1098 	// Now stall this endpoint
       
  1099 	__PRINT1(_L("Stalling endpoint %d"), aEndpoint);
       
  1100 	__TESTMODEPRINT2("CBW Tag=0x%x: Stalling endpoint %d", iCbwTag, aEndpoint);
       
  1101 	TInt r = iLdd.HaltEndpoint(aEndpoint);
       
  1102 	if (r != KErrNone)
       
  1103 		{
       
  1104 		__PRINT2(_L("Error: stalling ep %d failed: %d"), aEndpoint, r);
       
  1105 		}
       
  1106 	TEndpointState ep_state;
       
  1107 	TInt i = 0;
       
  1108 	do
       
  1109 		{
       
  1110 		// Wait for 10ms before checking the ep status
       
  1111 		User::After(10000);
       
  1112 
       
  1113         if (aEndpoint == KInEndpoint)
       
  1114             {
       
  1115             // Discard BULK-OUT data
       
  1116             TInt bytes;
       
  1117             const TInt err = iLdd.QueryReceiveBuffer(KOutEndpoint, bytes);
       
  1118             if (err != KErrNone || bytes <= 0)
       
  1119                 {
       
  1120                 __PRINT1(_L("Error: err=%d bytes=%d"), bytes);
       
  1121                 }
       
  1122             else
       
  1123                 {
       
  1124                 __PRINT1(_L("RxBuffer has %d bytes"), bytes);
       
  1125                 FlushDataOut(bytes);
       
  1126                 }
       
  1127             }
       
  1128 
       
  1129 		iLdd.EndpointStatus(aEndpoint, ep_state);
       
  1130 		if (++i >= 550)
       
  1131 			{
       
  1132 			// 5.5 secs should be enough (see 9.2.6.1 Request Processing Timing)
       
  1133 			__PRINT1(_L("Error: Checked for ep %d de-stall for 5.5s - giving up now"), aEndpoint);
       
  1134             __TESTMODEPRINT1("Error: Checked for ep %d de-stall for 5.5s - giving up now", aEndpoint);
       
  1135 			// We can now only hope for a Reset Recovery
       
  1136 			return;
       
  1137 			}
       
  1138 		} while ((ep_state == EEndpointStateStalled) && iStarted);
       
  1139 	__PRINT2(_L("Checked for ep %d de-stall: %d time(s)"), aEndpoint, i);
       
  1140     __TESTMODEPRINT2("Checked for ep %d de-stall: %d time(s)", aEndpoint, i);
       
  1141 	}
       
  1142 
       
  1143 
       
  1144 
       
  1145 /**
       
  1146 Called by the protocol to determine how many bytes of data are available in the read buffer.
       
  1147 
       
  1148 @return The number of bytes available in the read buffer
       
  1149 */
       
  1150 TInt CBulkOnlyTransport::BytesAvailable()
       
  1151 	{
       
  1152     __MSFNLOG
       
  1153 	TInt bytes = 0;
       
  1154 	TInt err = iLdd.QueryReceiveBuffer(KOutEndpoint, bytes);
       
  1155 	if (err != KErrNone)
       
  1156 		bytes = 0;
       
  1157 	return bytes;
       
  1158 	}
       
  1159 
       
  1160 
       
  1161 /**
       
  1162  * Read out rest data from KOutEndpoint and discard them
       
  1163  */
       
  1164 void CBulkOnlyTransport::FlushDataOut(TInt aLength)
       
  1165 	{
       
  1166     __MSFNLOG
       
  1167 	iBuf.SetMax();
       
  1168 	TRequestStatus status;
       
  1169 	while (aLength > 0)
       
  1170 		{
       
  1171 		iLdd.ReadOneOrMore(status, KOutEndpoint, iBuf, iBuf.Length());
       
  1172 		User::WaitForRequest(status);
       
  1173 		TInt err = status.Int();
       
  1174 		if (err != KErrNone)
       
  1175 			{
       
  1176 			// Bad.
       
  1177 			break;
       
  1178 			}
       
  1179 		aLength -= iBuf.Length();
       
  1180 		}
       
  1181 	}
       
  1182 
       
  1183 
       
  1184 void CBulkOnlyTransport::FlushDataIn(TInt aLength)
       
  1185     {
       
  1186 	iBuf.SetMax();
       
  1187 	TInt c = 0;
       
  1188     TInt len;
       
  1189 	TRequestStatus status;
       
  1190 	while (c < aLength)
       
  1191 		{
       
  1192         len = aLength - c;
       
  1193 		if (len >  KBOTMaxBufSize)
       
  1194 			{
       
  1195 			len = KBOTMaxBufSize;
       
  1196 			}
       
  1197 		iLdd.Write(status, KInEndpoint, iBuf, len);
       
  1198 		User::WaitForRequest(status);
       
  1199 		c +=  KBOTMaxBufSize;
       
  1200 		}
       
  1201     }
       
  1202 
       
  1203 //
       
  1204 // --- class CActiveDeviceStateNotifier ---------------------------------------------------------
       
  1205 //
       
  1206 CActiveDeviceStateNotifier::CActiveDeviceStateNotifier(CBulkOnlyTransport& aParent)
       
  1207 :   CActive(EPriorityStandard),
       
  1208 	iParent(aParent),
       
  1209 	iDeviceState(EUsbcNoState),
       
  1210 	iOldDeviceState(EUsbcNoState)
       
  1211 	{
       
  1212     __MSFNLOG
       
  1213 	}
       
  1214 
       
  1215 
       
  1216 CActiveDeviceStateNotifier* CActiveDeviceStateNotifier::NewL(CBulkOnlyTransport& aParent)
       
  1217 	{
       
  1218     __MSFNSLOG
       
  1219 	CActiveDeviceStateNotifier* self = new (ELeave) CActiveDeviceStateNotifier(aParent);
       
  1220 	CleanupStack::PushL(self);
       
  1221 	self->ConstructL();
       
  1222 	CActiveScheduler::Add(self);
       
  1223 	CleanupStack::Pop();									// self
       
  1224 	return (self);
       
  1225 	}
       
  1226 
       
  1227 
       
  1228 void CActiveDeviceStateNotifier::ConstructL()
       
  1229 	{
       
  1230     __MSFNLOG
       
  1231 	}
       
  1232 
       
  1233 
       
  1234 CActiveDeviceStateNotifier::~CActiveDeviceStateNotifier()
       
  1235 	{
       
  1236     __MSFNLOG
       
  1237 	Cancel();												// base class
       
  1238 	}
       
  1239 
       
  1240 
       
  1241 void CActiveDeviceStateNotifier::DoCancel()
       
  1242 /**
       
  1243  *
       
  1244  */
       
  1245 	{
       
  1246     __MSFNLOG
       
  1247 	iParent.Ldd().AlternateDeviceStatusNotifyCancel();
       
  1248 	}
       
  1249 
       
  1250 
       
  1251 void CActiveDeviceStateNotifier::RunL()
       
  1252 /**
       
  1253  *
       
  1254  */
       
  1255 	{
       
  1256     __MSFNLOG
       
  1257 	// This displays the device state.
       
  1258 	// In a real world program, the user could take here appropriate action (cancel a
       
  1259 	// transfer request or whatever).
       
  1260 	if (!(iDeviceState & KUsbAlternateSetting))
       
  1261 		{
       
  1262 		switch (iDeviceState)
       
  1263 			{
       
  1264 		case EUsbcDeviceStateUndefined:
       
  1265 			__PRINT(_L("Device State notifier: Undefined\n"));
       
  1266 			iParent.HwStop();
       
  1267 			break;
       
  1268 		case EUsbcDeviceStateAttached:
       
  1269 			__PRINT(_L("Device State notifier: Attached\n"));
       
  1270 			iParent.HwStop();
       
  1271 			break;
       
  1272 		case EUsbcDeviceStatePowered:
       
  1273 			__PRINT(_L("Device State notifier: Powered\n"));
       
  1274 			iParent.HwStop();
       
  1275 			break;
       
  1276 		case EUsbcDeviceStateDefault:
       
  1277 			__PRINT(_L("Device State notifier: Default\n"));
       
  1278 			iParent.HwStop();
       
  1279 			break;
       
  1280 		case EUsbcDeviceStateAddress:
       
  1281 			__PRINT(_L("Device State notifier: Address\n"));
       
  1282 			iParent.HwStop();
       
  1283 			break;
       
  1284 		case EUsbcDeviceStateConfigured:
       
  1285 			__PRINT(_L("Device State notifier: Configured\n"));
       
  1286 			if (iOldDeviceState == EUsbcDeviceStateSuspended)
       
  1287 				{
       
  1288 				iParent.HwResume();
       
  1289 				}
       
  1290 			else
       
  1291 				{
       
  1292 				iParent.HwStart();
       
  1293 				}
       
  1294 			break;
       
  1295 		case EUsbcDeviceStateSuspended:
       
  1296 			__PRINT(_L("Device State notifier: Suspended\n"));
       
  1297 			if (iOldDeviceState == EUsbcDeviceStateConfigured)
       
  1298 				{
       
  1299 				iParent.HwSuspend();
       
  1300 				}
       
  1301 			break;
       
  1302 		default:
       
  1303 			__PRINT(_L("Device State notifier: ***BAD***\n"));
       
  1304 			iParent.HwStop();
       
  1305 			break;
       
  1306 			}
       
  1307 		iOldDeviceState = iDeviceState;
       
  1308 		}
       
  1309 	else if (iDeviceState & KUsbAlternateSetting)
       
  1310 		{
       
  1311 		__PRINT1(_L("Device State notifier: Alternate interface setting has changed: now %d\n"), iDeviceState & ~KUsbAlternateSetting);
       
  1312 		}
       
  1313 	Activate();
       
  1314 	}
       
  1315 
       
  1316 
       
  1317 void CActiveDeviceStateNotifier::Activate()
       
  1318 /**
       
  1319  *
       
  1320  */
       
  1321 	{
       
  1322     __MSFNLOG
       
  1323 	if (IsActive())
       
  1324 		{
       
  1325 		__PRINT(_L("Still active\n"));
       
  1326 		return;
       
  1327 		}
       
  1328 	iParent.Ldd().AlternateDeviceStatusNotify(iStatus, iDeviceState);
       
  1329 	SetActive();
       
  1330 	}