os/kernelhwsrv/userlibandfileserver/fileserver/smassstorage/cbulkonlytransportusbcldd.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     5 * under the terms of the License "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description:
    15 *
    16 */
    17 
    18 
    19 /**
    20  @file
    21  @internalTechnology
    22 */
    23 
    24 #include "cbulkonlytransport.h"
    25 #include "cbulkonlytransportusbcldd.h"
    26 #include "usbmsshared.h"
    27 #include "massstoragedebug.h"
    28 #include "cusbmassstorageserver.h"
    29 
    30 #define InEndpoint EEndpoint1
    31 #define OutEndpoint EEndpoint2
    32 
    33 //This value defined in USB Mass Storage Bulk Only Transrt spec and not supposed to be changed
    34 LOCAL_D const TInt KRequiredNumberOfEndpoints = 2; // in addition to endpoint 0.
    35 
    36 LOCAL_D const TInt KUsbNumInterfacesOffset = 4;
    37 
    38 ////////////////////////////////////
    39 /**
    40 Called by CBulkOnlyTransportUsbcLdd to create an instance of CControlInterfaceUsbcLdd
    41 
    42 @param aParent reference to the CBulkOnlyTransportUsbcLdd
    43 */
    44 
    45 
    46 CControlInterfaceUsbcLdd* CControlInterfaceUsbcLdd::NewL(CBulkOnlyTransportUsbcLdd& aParent)
    47 	{
    48 	CControlInterfaceUsbcLdd* self = new(ELeave) CControlInterfaceUsbcLdd(aParent);
    49 	CleanupStack::PushL(self);
    50 	self->ConstructL();
    51 	CActiveScheduler::Add(self);
    52 	CleanupStack::Pop();
    53 	return self;
    54 	}
    55 
    56 
    57 void CControlInterfaceUsbcLdd::ConstructL()
    58 	{
    59 	}
    60 
    61 
    62 /**
    63 c'tor
    64 
    65 @param aParent reference to the CBulkOnlyTransportUsbcLdd
    66 */
    67 CControlInterfaceUsbcLdd::CControlInterfaceUsbcLdd(CBulkOnlyTransportUsbcLdd& aParent)
    68 	:CActive(EPriorityStandard),
    69 	 iParent(aParent),
    70 	 iCurrentState(ENone)
    71 	{
    72 	}
    73 
    74 
    75 /**
    76 d'tor
    77 */
    78 CControlInterfaceUsbcLdd::~CControlInterfaceUsbcLdd()
    79 	{
    80 	__FNLOG("CControlInterfaceUsbcLdd::~CControlInterfaceUsbcLdd ");
    81 	Cancel();
    82 	}
    83 
    84 
    85 /**
    86 Called by CBulkOnlyTransport HwStart to start control interface
    87 */
    88 TInt CControlInterfaceUsbcLdd::Start()
    89 	{
    90 	__FNLOG("CControlInterfaceUsbcLdd::Start ");
    91 	TInt res = ReadEp0Data();
    92 	return (res);
    93 	}
    94 
    95 
    96 /**
    97 Called by desctructor of CBulkOnlyTransportUsbcLdd to stop control interface
    98 */
    99 void CControlInterfaceUsbcLdd::Stop()
   100 	{
   101 	__FNLOG("CControlInterfaceUsbcLdd::Stop ");
   102 	if (!IsActive())
   103 		{
   104 		__PRINT(_L("Not active\n"));
   105 		return;
   106 		}
   107 
   108 	__PRINT(_L("\nStopping...\n"));
   109 
   110 
   111 	iCurrentState = ENone;
   112 
   113 	Cancel();
   114 	}
   115 
   116 
   117 /**
   118 Cancel outstanding request (if any)
   119 */
   120 void CControlInterfaceUsbcLdd::DoCancel()
   121 	{
   122 	__FNLOG("CControlInterfaceUsbcLdd::DoCancel ");
   123 	switch(iCurrentState)
   124 		{
   125 		case EReadEp0Data:
   126 			iParent.Ldd().ReadCancel(EEndpoint0);
   127 			break;
   128 		case ESendMaxLun:
   129 			iParent.Ldd().WriteCancel(EEndpoint0);
   130 			break;
   131 		default:
   132 			__PRINT(_L("\nWrong state !\n"));
   133 			__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceBadState));
   134 		}
   135 	}
   136 
   137 
   138 /**
   139 Implement CControlInterfaceUsbcLdd state machine
   140 */
   141 void CControlInterfaceUsbcLdd::RunL()
   142 	{
   143 	__FNLOG("CControlInterfaceUsbcLdd::RunL ");
   144 	if (iStatus != KErrNone)
   145 		{
   146 		__PRINT1(_L("Error %d in RunL\n"), iStatus.Int());
   147 
   148 		//read EP0  again
   149 		ReadEp0Data();
   150 		return;
   151 		}
   152 
   153 	switch (iCurrentState)
   154 		{
   155 		case ESendMaxLun:
   156 			ReadEp0Data();
   157 			break;
   158 
   159 		case EReadEp0Data:
   160 			DecodeEp0Data();
   161 			break;
   162 
   163 		default:
   164 			__PRINT(_L("  error: (Shouldn't end up here...)\n"));
   165 			__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceBadState));
   166 			break;
   167 		}
   168 	return;
   169 	}
   170 
   171 
   172 /**
   173 Post a read request to EEndpoint0 to read request header
   174 */
   175 TInt CControlInterfaceUsbcLdd::ReadEp0Data()
   176 	{
   177 	__FNLOG("CControlInterfaceUsbcLdd::ReadEp0Data ");
   178 	if (IsActive())
   179 		{
   180 		__PRINT(_L("Still active\n"));
   181 		return KErrServerBusy;
   182 		}
   183 	iParent.Ldd().Read(iStatus, EEndpoint0, iData, KRequestHdrSize);
   184 
   185 	iCurrentState = EReadEp0Data;
   186 
   187 	SetActive();
   188 	return KErrNone;
   189 	}
   190 
   191 
   192 /**
   193 Decode request header and do appropriate action - get max LUN info or post a reset request
   194 */
   195 void CControlInterfaceUsbcLdd::DecodeEp0Data()
   196 	{
   197 	__FNLOG("CControlInterfaceUsbcLdd::DecodeEp0Data ");
   198 	if (IsActive())
   199 		{
   200 		__PRINT(_L("Still active\n"));
   201 		__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceStillActive));
   202 		return;
   203 		}
   204 
   205 	TInt err = iRequestHeader.Decode(iData);
   206 
   207 	if(err != KErrNone)
   208 		return;
   209 
   210     switch(iRequestHeader.iRequest)
   211 		{
   212 		//
   213 		// GET MAX LUN (0xFE)
   214 		//
   215 		case TUsbRequestHdr::EReqGetMaxLun:
   216 			{
   217 			__PRINT1(_L("DecodeEp0Data : 'Get Max LUN' Request MaxLun = %d"),iParent.MaxLun() );
   218 
   219             if (   iRequestHeader.iRequestType != 0xA1 //value from USB MS BOT spec
   220                 || iRequestHeader.iIndex > 15
   221                 || iRequestHeader.iValue != 0
   222                 || iRequestHeader.iLength != 1)
   223                 {
   224     		    __PRINT(_L("GetMaxLun command packet check error"));
   225                 iParent.Ldd().EndpointZeroRequestError();
   226                 break;
   227                 }
   228 			iData.FillZ(1);  //Return only 1 byte to host
   229 			iData[0] = static_cast<TUint8>(iParent.MaxLun());	// Supported Units
   230 			iParent.Ldd().Write(iStatus, EEndpoint0, iData, 1);
   231 
   232 			iCurrentState = ESendMaxLun;
   233 			SetActive();
   234 
   235 			return;
   236 			}
   237 		//
   238 		// RESET (0xFF)
   239 		//
   240 		case TUsbRequestHdr::EReqReset:
   241 			{
   242 			__PRINT(_L("DecodeEp0Data : 'Mass Storage Reset' Request"));
   243 
   244             if (   iRequestHeader.iRequestType != 0x21 //value from USB MS BOT spec
   245                 || iRequestHeader.iIndex > 15
   246                 || iRequestHeader.iValue != 0
   247                 || iRequestHeader.iLength != 0)
   248                 {
   249 			    __PRINT(_L("MSC Reset command packet check error"));
   250                 iParent.Ldd().EndpointZeroRequestError();
   251                 break;
   252                 }
   253 			iParent.HwStop();
   254 			iParent.Controller().Reset();
   255 			iParent.HwStart(ETrue);
   256 
   257             err = iParent.Ldd().SendEp0StatusPacket();
   258 
   259 			return;
   260 			}
   261 		//
   262 		// Unknown?
   263 		//
   264 		default:
   265 			{
   266 			__PRINT(_L("DecodeEp0Data : Unknown Request"));
   267 
   268 			}
   269 		}
   270 		ReadEp0Data();  //try to get another request
   271 	}
   272 
   273 
   274 //
   275 // --- class CBulkOnlyTransportUsbcLdd ---------------------------------------------------------
   276 //
   277 
   278 CBulkOnlyTransportUsbcLdd::CBulkOnlyTransportUsbcLdd(TInt aNumDrives,CUsbMassStorageController& aController)
   279 	:CBulkOnlyTransport(aNumDrives, aController),
   280 	 iSwap(ETrue)
   281 	{
   282 	__FNLOG("CBulkOnlyTransportUsbcLdd::CBulkOnlyTransportUsbcLdd");
   283 	}
   284 
   285 /**
   286 Constructs the CBulkOnlyTransportUsbcLdd object
   287 */
   288 void CBulkOnlyTransportUsbcLdd::ConstructL()
   289 	{
   290 	__FNLOG("CBulkOnlyTransportUsbcLdd::ConstructL()");
   291 	iControlInterface = CControlInterfaceUsbcLdd::NewL(*this);
   292 	iDeviceStateNotifier = CActiveDeviceStateNotifierBase::NewL(*this, *this);
   293 	CActiveScheduler::Add(this);
   294 	}
   295 
   296 CBulkOnlyTransportUsbcLdd::~CBulkOnlyTransportUsbcLdd()
   297 	{
   298 	__FNLOG("CBulkOnlyTransportUsbcLdd::~CBulkOnlyTransportUsbcLdd");
   299 	if (iInterfaceConfigured)
   300 		{
   301 		delete iControlInterface ;
   302 		delete iDeviceStateNotifier;
   303 		}
   304 	}	
   305 
   306 RDevUsbcClient& CBulkOnlyTransportUsbcLdd::Ldd()
   307 	{
   308 	return iLdd;
   309 	}
   310 
   311 
   312 /**
   313 Set or unset configuration descriptor for USB MassStorage Bulk Only transport
   314 
   315 @param aUnset indicate whether set or unset descriptor
   316 @return KErrNone if operation was completed successfully, errorcode otherwise
   317 */
   318 TInt CBulkOnlyTransportUsbcLdd::SetupConfigurationDescriptor(TBool aUnset)
   319 	{
   320 	__FNLOG("CBulkOnlyTransportUsbcLdd::SetupConfigurationDescriptor");
   321 	TInt ret(KErrNone);
   322 	
   323 		if ((ret = iLdd.Open(0)) != KErrNone)
   324 			return ret;
   325 
   326 	TInt configDescriptorSize(0);
   327 	iLdd.GetConfigurationDescriptorSize(configDescriptorSize);
   328 	if (static_cast<TUint>(configDescriptorSize) != KUsbDescSize_Config)
   329 		{
   330 		return KErrCorrupt;
   331 		}
   332 
   333 	TBuf8<KUsbDescSize_Config> configDescriptor;
   334 	ret = iLdd.GetConfigurationDescriptor(configDescriptor);
   335 	if (ret != KErrNone)
   336 		{
   337 		return ret;
   338 		}
   339 
   340 	// I beleive that other fields setted up during LDD initialisation
   341 	if (aUnset)
   342 		{
   343 		--configDescriptor[KUsbNumInterfacesOffset];
   344 		}
   345 	else
   346 		{
   347 		++configDescriptor[KUsbNumInterfacesOffset];
   348 		}
   349 	ret = iLdd.SetConfigurationDescriptor(configDescriptor);
   350 
   351 	if (aUnset)
   352 		{
   353 		iLdd.Close();
   354 		}
   355 	return ret;
   356 	}
   357 
   358 /**
   359 Set up interface descriptor
   360 
   361 @return KErrNone if operation was completed successfully, errorcode otherwise
   362 */
   363 TInt CBulkOnlyTransportUsbcLdd::SetupInterfaceDescriptors()
   364 	{
   365 	__FNLOG("CBulkOnlyTransportUsbcLdd::SetupInterfaceDescriptors");
   366 	// Device caps
   367 	TUsbDeviceCaps d_caps;
   368 	TInt ret = iLdd.DeviceCaps(d_caps);
   369 	if (ret != KErrNone)
   370 		{
   371 		return ret;
   372 		}
   373 	TInt totalEndpoints = d_caps().iTotalEndpoints;
   374 	if (totalEndpoints  < KRequiredNumberOfEndpoints)
   375 		{
   376 		return KErrHardwareNotAvailable;
   377 		}
   378 
   379 	// Endpoint caps
   380 	TUsbcEndpointData data[KUsbcMaxEndpoints];
   381 	TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data));
   382 	ret = iLdd.EndpointCaps(dataptr);
   383 	if (ret != KErrNone)
   384 		{
   385 		return ret;
   386 		}
   387 
   388 	// Set the active interface
   389 	TUsbcInterfaceInfoBuf ifc;
   390 	TInt ep_found = 0;
   391 	TBool foundBulkIN = EFalse;
   392 	TBool foundBulkOUT = EFalse;
   393 
   394 	for (TInt i = 0; i < totalEndpoints ; i++)
   395 		{
   396 		const TUsbcEndpointCaps* caps = &data[i].iCaps;
   397 		const TInt maxPacketSize = caps->MaxPacketSize();
   398 		if (!foundBulkIN &&
   399 			(caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirIn)) == (KUsbEpTypeBulk | KUsbEpDirIn))
   400 			{
   401 			// InEndpoint is going to be our TX (IN, write) endpoint
   402 			ifc().iEndpointData[0].iType = KUsbEpTypeBulk;
   403 			if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) == KUsbDevCapsFeatureWord1_EndpointResourceAllocV2)
   404 				ifc().iEndpointData[0].iFeatureWord1  = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering;
   405 			ifc().iEndpointData[0].iDir  = KUsbEpDirIn;
   406 			ifc().iEndpointData[0].iSize = maxPacketSize;
   407 			ifc().iEndpointData[0].iInterval_Hs = 0;
   408 			foundBulkIN = ETrue;
   409 			if (++ep_found == KRequiredNumberOfEndpoints)
   410 				{
   411 				break;
   412 				}
   413 			continue;
   414 			}
   415 		if (!foundBulkOUT &&
   416 			(caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirOut)) == (KUsbEpTypeBulk | KUsbEpDirOut))
   417 			{
   418 			// OutEndpoint is going to be our RX (OUT, read) endpoint
   419 			ifc().iEndpointData[1].iType = KUsbEpTypeBulk;
   420 			if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) == KUsbDevCapsFeatureWord1_EndpointResourceAllocV2)
   421 				ifc().iEndpointData[1].iFeatureWord1  = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering;
   422 			ifc().iEndpointData[1].iDir  = KUsbEpDirOut;
   423 			ifc().iEndpointData[1].iSize = maxPacketSize;
   424 			ifc().iEndpointData[1].iInterval_Hs = 0;
   425 			foundBulkOUT = ETrue;
   426 			if (++ep_found == KRequiredNumberOfEndpoints)
   427 				{
   428 				break;
   429 				}
   430 			continue;
   431 			}
   432 		}
   433 	if (ep_found != KRequiredNumberOfEndpoints)
   434 		{
   435 		return KErrHardwareNotAvailable;
   436 		}
   437 
   438 	_LIT16(string, "USB Mass Storage Interface");
   439 	ifc().iString = const_cast<TDesC16*>(&string);
   440 	ifc().iTotalEndpointsUsed = KRequiredNumberOfEndpoints;
   441 	ifc().iClass.iClassNum    = 0x08;	// Mass Storage
   442 	ifc().iClass.iSubClassNum = 0x06;	// SCSI Transparent Command Set
   443 	ifc().iClass.iProtocolNum = 0x50;	// Bulk Only Transport
   444 
   445 	TUint bandwidth_priority = (EUsbcBandwidthOUTDefault | EUsbcBandwidthINDefault);
   446 	if (d_caps().iHighSpeed)
   447 		{
   448 		// If this device supports USB High-speed, then we request 64KB buffers
   449 		// (otherwise the default 4KB ones will do).
   450 		bandwidth_priority = (EUsbcBandwidthOUTPlus2 | EUsbcBandwidthINPlus2);
   451 		// Also, tell the Protocol about it, because it might want to do some
   452 		// optimizing too.
   453 		iProtocol->ReportHighSpeedDevice();
   454 		}
   455 	ret = iLdd.SetInterface(0, ifc, bandwidth_priority);
   456 	return ret;
   457 	}
   458 
   459 void CBulkOnlyTransportUsbcLdd::ReleaseInterface()
   460 	{
   461 	iLdd.ReleaseInterface(0);
   462 	}
   463 
   464 TInt CBulkOnlyTransportUsbcLdd::StartControlInterface()
   465 	{
   466 	return iControlInterface->Start();
   467 	}
   468 
   469 void CBulkOnlyTransportUsbcLdd::CancelControlInterface()
   470 	{
   471 	iControlInterface->Cancel();
   472 	}
   473 
   474 void CBulkOnlyTransportUsbcLdd::ActivateDeviceStateNotifier()
   475 	{
   476 	iDeviceStateNotifier->Activate();
   477 	}
   478 
   479 void CBulkOnlyTransportUsbcLdd::CancelDeviceStateNotifier()
   480 	{
   481 	iDeviceStateNotifier->Cancel();
   482 	}
   483 
   484 void CBulkOnlyTransportUsbcLdd::CancelReadWriteRequests()
   485 	{
   486 	__FNLOG("CBulkOnlyTransportUsbcLdd::CancelReadWriteRequests");
   487 	iLdd.WriteCancel(InEndpoint);
   488 	iLdd.ReadCancel(OutEndpoint);
   489 	}
   490 
   491 void CBulkOnlyTransportUsbcLdd::AllocateEndpointResources()
   492 	{
   493 	TUsbDeviceCaps d_caps;
   494 	TInt ret = iLdd.DeviceCaps(d_caps);
   495 	if (ret == KErrNone)
   496 		{
   497 		if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != KUsbDevCapsFeatureWord1_EndpointResourceAllocV2)
   498 			{
   499 				// Set up DMA if possible (errors are non-critical)
   500 			TInt err = iLdd.AllocateEndpointResource(OutEndpoint, EUsbcEndpointResourceDMA);
   501 			if (err != KErrNone)
   502 				{
   503 				__PRINT1(_L("Set DMA on OUT endpoint failed with error code: %d"), err);
   504 				}
   505 			err = iLdd.AllocateEndpointResource(InEndpoint, EUsbcEndpointResourceDMA);
   506 			if (err != KErrNone)
   507 				{
   508 				__PRINT1(_L("Set DMA on IN endpoint failed with error code: %d"), err);
   509 				}
   510 
   511 				// Set up Double Buffering if possible (errors are non-critical)
   512 			err = iLdd.AllocateEndpointResource(OutEndpoint, EUsbcEndpointResourceDoubleBuffering);
   513 			if (err != KErrNone)
   514 				{
   515 				__PRINT1(_L("Set Double Buffering on OUT endpoint failed with error code: %d"), err);
   516 				}
   517 			err = iLdd.AllocateEndpointResource(InEndpoint, EUsbcEndpointResourceDoubleBuffering);
   518 			if (err != KErrNone)
   519 				{
   520 				__PRINT1(_L("Set Double Buffering on IN endpoint failed with error code: %d"), err);
   521 				}
   522 			}
   523 		}
   524 	}
   525 
   526 TInt CBulkOnlyTransportUsbcLdd::GetDeviceStatus(TUsbcDeviceState& deviceStatus)
   527 	{
   528 	return iLdd.DeviceStatus(deviceStatus);
   529 	}
   530 
   531 void CBulkOnlyTransportUsbcLdd::FlushData()
   532 	{
   533 	TInt bytes;
   534 	const TInt err = iLdd.QueryReceiveBuffer(OutEndpoint, bytes);
   535 	if (err != KErrNone || bytes <= 0)
   536 		{
   537 		__PRINT1(_L("Error: err=%d bytes=%d"), bytes);
   538 		}
   539 	else
   540 		{
   541 		__PRINT1(_L("RxBuffer has %d bytes"), bytes);
   542 		ReadAndDiscardData(bytes);
   543 		}
   544 	}
   545 /**
   546  * Read out rest data from OutEndpoint and discard them
   547  */
   548 void CBulkOnlyTransportUsbcLdd::ReadAndDiscardData(TInt aBytes)
   549 	{
   550 	__FNLOG("CBulkOnlyTransportUsbcLdd::ReadAndDiscardData");
   551 	iDiscardBuf.SetMax();
   552 	const TUint bufsize = static_cast<TUint>(iDiscardBuf.Length());
   553 	TRequestStatus status;
   554 	while (aBytes > 0)
   555 		{
   556 		__PRINT1(_L("Bytes still to be read: %d\n"), aBytes);
   557 		iLdd.ReadOneOrMore(status, OutEndpoint, iDiscardBuf, bufsize);
   558 		User::WaitForRequest(status);
   559 		TInt err = status.Int();
   560 		if (err != KErrNone)
   561 			{
   562 			// Bad.
   563 			break;
   564 			}
   565 		aBytes -= iDiscardBuf.Length();
   566 		}
   567 	}
   568 
   569 /**
   570 Called by the protocol to determine how many bytes of data are available in the read buffer.
   571 
   572 @return The number of bytes available in the read buffer
   573 */
   574 TInt CBulkOnlyTransportUsbcLdd::BytesAvailable()
   575 	{
   576 	TInt bytes = 0;
   577 	TInt err = iLdd.QueryReceiveBuffer(OutEndpoint, bytes);
   578 	if (err != KErrNone)
   579 		bytes = 0;
   580 	return bytes;
   581 	}
   582 
   583 
   584 void CBulkOnlyTransportUsbcLdd::StallEndpointAndWaitForClear()
   585 	{
   586 	__FNLOG("CBulkOnlyTransportUsbcLdd::StallEndpointAndWaitForClear");
   587 
   588 	// Now stall this endpoint
   589 	__PRINT1(_L("Stalling endpoint %d"), InEndpoint);
   590 	TInt r = iLdd.HaltEndpoint(InEndpoint);
   591 	if (r != KErrNone)
   592 		{
   593 		__PRINT2(_L("Error: stalling ep %d failed: %d"), InEndpoint, r);
   594 		}
   595 	TEndpointState ep_state;
   596 	TInt i = 0;
   597 	do
   598 		{
   599 		// Wait for 10ms before checking the ep status
   600 		User::After(10000);
   601 		iLdd.EndpointStatus(InEndpoint, ep_state);
   602 		if (++i >= 550)
   603 			{
   604 			// 5.5 secs should be enough (see 9.2.6.1 Request Processing Timing)
   605 			__PRINT1(_L("Error: Checked for ep %d de-stall for 5.5s - giving up now"), InEndpoint);
   606 			// We can now only hope for a Reset Recovery
   607 			return;
   608 			}
   609 		} while ((ep_state == EEndpointStateStalled) && iStarted);
   610 	__PRINT2(_L("Checked for ep %d de-stall: %d time(s)"), InEndpoint, i);
   611 	}
   612 
   613 
   614 /**
   615 Read CBW data (KCbwLength) from the host into the read buffer.
   616 */
   617 void CBulkOnlyTransportUsbcLdd::ReadCBW()
   618 	{
   619 	__FNLOG("CBulkOnlyTransportUsbcLdd::ReadCBW");
   620 	if (IsActive())
   621 		{
   622 		__PRINT(_L("Still active\n"));
   623 		__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
   624 		return;
   625 		}
   626 
   627 	iCbwBuf.SetMax();
   628 	iLdd.ReadUntilShort(iStatus, OutEndpoint, iCbwBuf, KCbwLength);
   629 
   630 	iCurrentState = EWaitForCBW;
   631 	SetActive();
   632 	}
   633 
   634 void CBulkOnlyTransportUsbcLdd::ExpireData(TAny* /*aAddress*/)
   635 	{
   636 	// Intentionally left blank
   637 	}
   638 
   639 void CBulkOnlyTransportUsbcLdd::ProcessCbwEvent()
   640 	{
   641 	DecodeCBW();
   642 	}
   643 
   644 
   645 /**
   646 Request data form the host for the protocol
   647 
   648 @param aLength amount of data (in bytes) to be received from the host
   649 */
   650 void CBulkOnlyTransportUsbcLdd::ReadData(TUint aLength)
   651 	{
   652 	__FNLOG("CBulkOnlyTransportUsbcLdd::ReadData");
   653 	if (IsActive())
   654 		{
   655 		__PRINT(_L("Still active\n"));
   656 		__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
   657 		return;
   658 		}
   659 	
   660 	SetReadDataBufPtr(aLength);
   661 	iLdd.Read(iStatus, OutEndpoint, iReadBufPtr, aLength);
   662 
   663 	iCurrentState = EReadingData;
   664 	SetActive();
   665 	}
   666 
   667 void CBulkOnlyTransportUsbcLdd::WriteUsb(TRequestStatus& aStatus, TPtrC8& aDes, TUint aLength, TBool aZlpRequired)
   668 	{
   669 	iLdd.Write(aStatus, InEndpoint, aDes, aLength, aZlpRequired);
   670 	}
   671 
   672 void CBulkOnlyTransportUsbcLdd::SetCbwPtr()
   673 	{
   674 	iCbwBufPtr.Set(iCbwBuf.Ptr(), iCbwBuf.Length());
   675 	}
   676 
   677 TPtr8& CBulkOnlyTransportUsbcLdd::SetCommandBufPtr(TUint aLength)
   678 	{
   679 	iCommandBufPtr.Set((TUint8*) iCommandBuf.Ptr(), aLength, aLength );
   680 	return iCommandBufPtr;
   681 	}
   682 
   683 void CBulkOnlyTransportUsbcLdd::SetReadDataBufPtr(TUint aLength) //Write10(Host->Device
   684 	{
   685 	if (iSwap)
   686 		{
   687 		iDataBuf1.SetLength(aLength);
   688 		iReadBufPtr.Set(iDataBuf1.LeftTPtr(iDataBuf1.Length()));
   689 		iSwap = EFalse;
   690 		}
   691 	else
   692 		{
   693 		iDataBuf2.SetLength(aLength);
   694 		iReadBufPtr.Set(iDataBuf2.LeftTPtr(iDataBuf2.Length()));
   695 		iSwap = ETrue;
   696 		}
   697 	}
   698 
   699 TPtr8& CBulkOnlyTransportUsbcLdd::SetDataBufPtr() //Read10(Device->Host)
   700 	{
   701 	if (iSwap)
   702 		{
   703 		iDataBufPtr.Set((TUint8*) iDataBuf1.Ptr(), KMaxBufSize, KMaxBufSize);
   704 		iSwap = EFalse;
   705 		}
   706 	else
   707 		{
   708 		iDataBufPtr.Set((TUint8*) iDataBuf2.Ptr(), KMaxBufSize, KMaxBufSize);
   709 		iSwap = ETrue;
   710 		}
   711 	return iDataBufPtr;
   712 	}
   713 
   714 void CBulkOnlyTransportUsbcLdd::SetPaddingBufPtr(TUint aLength)
   715 	{
   716 	iPaddingBufPtr.Set((TUint8*) iBuf.Ptr(), aLength, aLength );
   717 	}
   718 
   719 
   720 void CBulkOnlyTransportUsbcLdd::SetCswBufPtr(TUint aLength)
   721 	{
   722 	iCswBufPtr.Set((TUint8*) iCswBuf.Ptr(), aLength, aLength );
   723 	}
   724 
   725 void CBulkOnlyTransportUsbcLdd::ProcessReadingDataEvent()
   726 	{
   727 	TInt ret = KErrNone;
   728     FOREVER
   729 		{
   730 		if (iReadSetUp)
   731 			{
   732 			ret = iProtocol->ReadComplete(KErrNone);
   733 			}
   734 
   735 		TUint deviceDataLength = iBufSize; // This is the amount (maximum in case of SC Ldd) to be read next.
   736 
   737 		if(ret == KErrCompletion)
   738 			{
   739 			// The protocol has indicated with KErrCompletion that sufficient
   740 			// data is available in the buffer to process the transfer immediately.
   741 
   742 			iDataResidue -= iReadBufPtr.Length();
   743 			SetReadDataBufPtr(deviceDataLength);
   744 
   745 			iLdd.Read(iStatus, OutEndpoint, iReadBufPtr, deviceDataLength);
   746 			User::WaitForRequest(iStatus);
   747 			if (iStatus != KErrNone)
   748 				{
   749 				// An error occurred - halt endpoints for reset recovery
   750 				__PRINT1(_L("Error %d in EReadingData, halt endpoints \n"), iStatus.Int());
   751 				SetPermError();
   752 				return;
   753 				}
   754 			}
   755 		else if(ret == KErrNotReady)
   756 			{
   757 			// The protocol has indicated with KErrNotReady that insufficient
   758 			// data is available in the buffer, so should wait for it to arrive
   759 
   760             iDataResidue -= iReadBufPtr.Length();
   761 			ReadData(deviceDataLength);
   762 			break;
   763 			}
   764 		else
   765 			{
   766 			// The protocol has indicated that transfer is
   767 			// complete, so send the CSW response to the host.
   768 			iDataResidue -= iReadBufPtr.Length();
   769 			iReadSetUp = EFalse;
   770 
   771 			if (ret != KErrNone)
   772 				{
   773 				iCmdStatus = ECommandFailed;
   774 				}
   775 
   776 			if (iDataResidue)
   777 				{
   778 				__PRINT(_L("Discarding residue"));
   779 				// we have to read as much data as available that host PC sends;
   780 				// otherwise, bulk-out endpoint will need to keep sending NAK back.
   781 				ReadAndDiscardData(iDataResidue);
   782 				}
   783 			SendCSW(iCbwTag, iDataResidue, iCmdStatus);
   784 			break;
   785 			}
   786 		}
   787 
   788 	}
   789 
   790 void CBulkOnlyTransportUsbcLdd::DiscardData(TUint aLength)
   791 	{
   792 	iBuf.SetLength(KBOTMaxBufSize);
   793 	TUint c = 0;
   794 	TRequestStatus status;
   795 	while (c < aLength)
   796 		{
   797 		TInt len;
   798 		if (aLength - c >  KBOTMaxBufSize)
   799 			{
   800 			len = KBOTMaxBufSize;
   801 			}
   802 		else
   803 			{
   804 			len = aLength - c;
   805 			}
   806 
   807 		iLdd.Read(status, OutEndpoint, iBuf, len);
   808 		User::WaitForRequest(status);
   809 		c +=  KBOTMaxBufSize;
   810 		}
   811 	}
   812 
   813 void CBulkOnlyTransportUsbcLdd::WriteToClient(TUint aLength)
   814 	{
   815 	SetDataBufPtr();
   816 	iLdd.Read(iStatus, OutEndpoint, iDataBufPtr, aLength);
   817     User::WaitForRequest(iStatus);
   818     iProtocol->ReadComplete(KErrGeneral);
   819 	}
   820 
   821 #ifdef MSDC_MULTITHREADED
   822 void CBulkOnlyTransportUsbcLdd::GetBufferPointers(TPtr8& aDes1, TPtr8& aDes2)
   823 	{
   824 	aDes1.Set((TUint8*) iDataBuf1.Ptr(), KMaxBufSize, KMaxBufSize);
   825 	aDes2.Set((TUint8*) iDataBuf2.Ptr(), KMaxBufSize, KMaxBufSize);
   826 	}
   827 #endif
   828 
   829 void CBulkOnlyTransportUsbcLdd::Activate(TRequestStatus& aStatus, TUint& aDeviceState)
   830     {
   831 	iLdd.AlternateDeviceStatusNotify(aStatus, aDeviceState);
   832     }
   833 
   834 
   835 void CBulkOnlyTransportUsbcLdd::Cancel()
   836     {
   837 	iLdd.AlternateDeviceStatusNotifyCancel();
   838     }
   839 
   840 
   841 
   842