os/kernelhwsrv/userlibandfileserver/fileserver/smassstorage/cbulkonlytransportusbcscldd.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 "cbulkonlytransportusbcscldd.h"
    26 #include "usbmsshared.h"
    27 #include "massstoragedebug.h"
    28 #include "cusbmassstorageserver.h"
    29 
    30 
    31 //This value defined in USB Mass Storage Bulk Only Transrt spec and not supposed to be changed
    32 LOCAL_D const TInt KRequiredNumberOfEndpoints = 2; // in addition to endpoint 0.
    33 
    34 LOCAL_D const TInt KUsbNumInterfacesOffset = 4;
    35 
    36 #ifdef MSDC_MULTITHREADED
    37 //Only used in DB. The first 2K of KMaxScBufferSize for sending CSW 
    38 static const TUint32 KCswBufferSize = 2 * 1024;
    39 #endif
    40 
    41 ////////////////////////////////////
    42 /**
    43 Called by CBulkOnlyTransportUsbcScLdd to create an instance of CControlInterfaceUsbcScLdd
    44 
    45 @param aParent reference to the CBulkOnlyTransportUsbcScLdd
    46 */
    47 
    48 
    49 CControlInterfaceUsbcScLdd* CControlInterfaceUsbcScLdd::NewL(CBulkOnlyTransportUsbcScLdd& aParent)
    50 	{
    51 	CControlInterfaceUsbcScLdd* self = new(ELeave) CControlInterfaceUsbcScLdd(aParent);
    52 	CleanupStack::PushL(self);
    53 	self->ConstructL();
    54 	CActiveScheduler::Add(self);
    55 	CleanupStack::Pop();
    56 	return self;
    57 	}
    58 
    59 
    60 void CControlInterfaceUsbcScLdd::ConstructL()
    61 	{
    62 	}
    63 
    64 
    65 /**
    66 c'tor
    67 
    68 @param aParent reference to the CBulkOnlyTransportUsbcScLdd
    69 */
    70 CControlInterfaceUsbcScLdd::CControlInterfaceUsbcScLdd(CBulkOnlyTransportUsbcScLdd& aParent)
    71 	:CActive(EPriorityStandard),
    72 	 iParent(aParent),
    73 	 iCurrentState(ENone)
    74 	{
    75 	}
    76 
    77 
    78 /**
    79 d'tor
    80 */
    81 CControlInterfaceUsbcScLdd::~CControlInterfaceUsbcScLdd()
    82 	{
    83 	__FNLOG("CControlInterfaceUsbcScLdd::~CControlInterfaceUsbcScLdd ");
    84 	Cancel();
    85 	iEp0Buf.Close();
    86 	}
    87 
    88 TInt CControlInterfaceUsbcScLdd::OpenEp0()
    89 	{
    90 	TInt res = iParent.Ldd().OpenEndpoint(iEp0Buf,0);
    91 	return res;
    92 	}
    93 
    94 /**
    95 Called by CBulkOnlyTransport HwStart to start control interface
    96 */
    97 TInt CControlInterfaceUsbcScLdd::Start()
    98 	{
    99 	__FNLOG("CControlInterfaceUsbcScLdd::Start ");
   100 	TInt res = ReadEp0Data();
   101 	return (res);
   102 	}
   103 
   104 
   105 /**
   106 Called by desctructor of CBulkOnlyTransportUsbcScLdd to stop control interface
   107 */
   108 void CControlInterfaceUsbcScLdd::Stop()
   109 	{
   110 	__FNLOG("CControlInterfaceUsbcScLdd::Stop ");
   111 	if (!IsActive())
   112 		{
   113 		__PRINT(_L("Not active\n"));
   114 		return;
   115 		}
   116 
   117 	__PRINT(_L("\nStopping...\n"));
   118 
   119 
   120 	iCurrentState = ENone;
   121 
   122 	Cancel();
   123 	}
   124 
   125 
   126 /**
   127 Cancel outstanding request (if any)
   128 */
   129 void CControlInterfaceUsbcScLdd::DoCancel()
   130 	{
   131 	__FNLOG("CControlInterfaceUsbcScLdd::DoCancel ");
   132 	switch(iCurrentState)
   133 		{
   134 		case EReadEp0Data:
   135 			iParent.Ldd().ReadCancel(KUsbcScEndpointZero);
   136 			break;
   137 		case ESendMaxLun:
   138 			iParent.Ldd().WriteCancel(KUsbcScEndpointZero);
   139 			break;
   140 		default:
   141 			__PRINT(_L("\nWrong state !\n"));
   142 			__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceBadState));
   143 		}
   144 	}
   145 
   146 
   147 /**
   148 Implement CControlInterfaceUsbcScLdd state machine
   149 */
   150 void CControlInterfaceUsbcScLdd::RunL()
   151 	{
   152 	__FNLOG("CControlInterfaceUsbcScLdd::RunL ");
   153 	if (iStatus != KErrNone)
   154 		{
   155 		__PRINT1(_L("Error %d in RunL\n"), iStatus.Int());
   156 
   157 		//read EP0  again
   158 		ReadEp0Data();
   159 		return;
   160 		}
   161 
   162 	ReadEp0Data();
   163 	}
   164 
   165 /**
   166 Actual Read to RDevUsbcScClient BIL
   167 */
   168 TInt CControlInterfaceUsbcScLdd::ReadUsbEp0()
   169 	{
   170 	iCurrentState = EReadEp0Data;
   171 	iStatus = KRequestPending;
   172 	return iEp0Buf.GetBuffer (iEp0Packet,iEp0Size,iEp0Zlp,iStatus);
   173 	}
   174 
   175 
   176 /**
   177 Post a read request to EEndpoint0 to read request header
   178 */
   179 TInt CControlInterfaceUsbcScLdd::ReadEp0Data()
   180 	{
   181 	__FNLOG("CControlInterfaceUsbcScLdd::ReadEp0Data ");
   182 	if (IsActive())
   183 		{
   184 		__PRINT(_L("Still active\n"));
   185 		return KErrServerBusy;
   186 		}
   187 
   188 	TInt r = KErrNone;
   189 	do
   190 		{
   191 		r = ReadUsbEp0();
   192 		if (r == KErrCompletion)
   193 			{
   194 			iStatus = KErrNone;
   195 			DecodeEp0Data();
   196 			}
   197 		else if (r == KErrNone)
   198 			{
   199 			SetActive();
   200 			}
   201 		} while (((r == KErrCompletion) || (r == TEndpointBuffer::KStateChange)) && (!IsActive()));
   202 	return KErrNone;
   203 	}
   204 
   205 
   206 /**
   207 Decode request header and do appropriate action - get max LUN info or post a reset request
   208 */
   209 void CControlInterfaceUsbcScLdd::DecodeEp0Data()
   210 	{
   211 	__FNLOG("CControlInterfaceUsbcScLdd::DecodeEp0Data ");
   212 
   213 	if (IsActive())
   214 		{
   215 		__PRINT(_L("Still active\n"));
   216 		__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceStillActive));
   217 		return;
   218 		}
   219 
   220 	TPtrC8 ep0ReadDataPtr((TUint8*)iEp0Packet, iEp0Size);
   221 	TInt err = iRequestHeader.Decode(ep0ReadDataPtr);
   222 
   223 	if(err != KErrNone)
   224 		return;
   225 
   226     switch(iRequestHeader.iRequest)
   227 		{
   228 		//
   229 		// GET MAX LUN (0xFE)
   230 		//
   231 		case TUsbRequestHdr::EReqGetMaxLun:
   232 			{
   233 			__PRINT1(_L("DecodeEp0Data : 'Get Max LUN' Request MaxLun = %d"),iParent.MaxLun() );
   234 
   235             if (   iRequestHeader.iRequestType != 0xA1 //value from USB MS BOT spec
   236                 || iRequestHeader.iIndex > 15
   237                 || iRequestHeader.iValue != 0
   238                 || iRequestHeader.iLength != 1)
   239                 {
   240     		    __PRINT(_L("GetMaxLun command packet check error"));
   241                 iParent.Ldd().EndpointZeroRequestError();
   242                 break;
   243                 }
   244 
   245 			TPtr8* ep0WriteDataPtr = NULL;
   246 			TUint ep0Length;
   247 			iEp0Buf.GetInBufferRange(((TAny*&)ep0WriteDataPtr),ep0Length);
   248 			ep0WriteDataPtr->SetLength(1);	//Return only 1 byte to host
   249 			ep0WriteDataPtr->Fill(0);
   250 			ep0WriteDataPtr->Fill(iParent.MaxLun());	// Supported Units
   251 			TInt length = ep0WriteDataPtr->Length();
   252 			err = iEp0Buf.WriteBuffer((TPtr8*)(ep0WriteDataPtr->Ptr()),length,ETrue,iStatus);
   253 
   254 			iCurrentState = ESendMaxLun;
   255 			SetActive();
   256 
   257 			return;
   258 			}
   259 		//
   260 		// RESET (0xFF)
   261 		//
   262 		case TUsbRequestHdr::EReqReset:
   263 			{
   264 			__PRINT(_L("DecodeEp0Data : 'Mass Storage Reset' Request"));
   265 
   266             if (   iRequestHeader.iRequestType != 0x21 //value from USB MS BOT spec
   267                 || iRequestHeader.iIndex > 15
   268                 || iRequestHeader.iValue != 0
   269                 || iRequestHeader.iLength != 0)
   270                 {
   271 			    __PRINT(_L("MSC Reset command packet check error"));
   272                 iParent.Ldd().EndpointZeroRequestError();
   273                 break;
   274                 }
   275 
   276 			iParent.HwStop();
   277 			iParent.Controller().Reset();
   278 			iParent.HwStart(ETrue);
   279 
   280             err = iParent.Ldd().SendEp0StatusPacket();
   281 			return;
   282 			}
   283 		//
   284 		// Unknown?
   285 		//
   286 		default:
   287 			{
   288 			__PRINT(_L("DecodeEp0Data : Unknown Request"));
   289 
   290 			}
   291 		}
   292 		ReadEp0Data();  //try to get another request
   293 	}
   294 
   295 
   296 //
   297 // --- class CBulkOnlyTransportUsbcScLdd ---------------------------------------------------------
   298 //
   299 
   300 CBulkOnlyTransportUsbcScLdd::CBulkOnlyTransportUsbcScLdd(TInt aNumDrives,CUsbMassStorageController& aController)
   301 	:CBulkOnlyTransport(aNumDrives, aController)
   302 	{
   303 	__FNLOG("CBulkOnlyTransportUsbcScLdd::CBulkOnlyTransportUsbcScLdd");
   304 	}
   305 
   306 /**
   307 Constructs the CBulkOnlyTransportUsbcScLdd object
   308 */
   309 void CBulkOnlyTransportUsbcScLdd::ConstructL()
   310 	{
   311 	__FNLOG("CBulkOnlyTransportUsbcScLdd::ConstructL()");
   312 	iControlInterface = CControlInterfaceUsbcScLdd::NewL(*this);
   313 	iDeviceStateNotifier = CActiveDeviceStateNotifierBase::NewL(*this, *this);
   314 	iChunk = new RChunk();
   315 	CActiveScheduler::Add(this);
   316 	}
   317 
   318 
   319 CBulkOnlyTransportUsbcScLdd::~CBulkOnlyTransportUsbcScLdd()
   320 	{
   321 	__FNLOG("CBulkOnlyTransportUsbcScLdd::~CBulkOnlyTransportUsbcScLdd");
   322 	if (iInterfaceConfigured)
   323 		{
   324 		TInt err = iSCReadEndpointBuf.Close(); 
   325 		err = iSCWriteEndpointBuf.Close();
   326 		delete iControlInterface ;
   327 		delete iDeviceStateNotifier;
   328 		delete iChunk;
   329 		}
   330 	}	
   331 
   332 RDevUsbcScClient& CBulkOnlyTransportUsbcScLdd::Ldd()
   333 	{
   334 	return iLdd;
   335 	}
   336 
   337 /**
   338 Set or unset configuration descriptor for USB MassStorage Bulk Only transport
   339 
   340 @param aUnset indicate whether set or unset descriptor
   341 @return KErrNone if operation was completed successfully, errorcode otherwise
   342 */
   343 TInt CBulkOnlyTransportUsbcScLdd::SetupConfigurationDescriptor(TBool aUnset)
   344 	{
   345 	__FNLOG("CBulkOnlyTransportUsbcScLdd::SetupConfigurationDescriptor");
   346 	TInt ret(KErrNone);
   347 
   348 	if ((ret = iLdd.Open(0)) != KErrNone)
   349 		return ret;
   350 
   351 	TInt configDescriptorSize(0);
   352 	iLdd.GetConfigurationDescriptorSize(configDescriptorSize);
   353 	if (static_cast<TUint>(configDescriptorSize) != KUsbDescSize_Config)
   354 		{
   355 		return KErrCorrupt;
   356 		}
   357 
   358 	TBuf8<KUsbDescSize_Config> configDescriptor;
   359 	ret = iLdd.GetConfigurationDescriptor(configDescriptor);
   360 	if (ret != KErrNone)
   361 		{
   362 		return ret;
   363 		}
   364 
   365 	// I beleive that other fields setted up during LDD initialisation
   366 	if (aUnset)
   367 		{
   368 		--configDescriptor[KUsbNumInterfacesOffset];
   369 		}
   370 	else
   371 		{
   372 		++configDescriptor[KUsbNumInterfacesOffset];
   373 		}
   374 	ret = iLdd.SetConfigurationDescriptor(configDescriptor);
   375 
   376 	if (aUnset)
   377 		{
   378 		iLdd.Close();
   379 		}
   380 
   381 	return ret;
   382 	}
   383 
   384 /**
   385 Set up interface descriptor
   386 
   387 @return KErrNone if operation was completed successfully, errorcode otherwise
   388 */
   389 TInt CBulkOnlyTransportUsbcScLdd::SetupInterfaceDescriptors()
   390 	{
   391 	__FNLOG("CBulkOnlyTransportUsbcScLdd::SetupInterfaceDescriptors");
   392 	// Device caps
   393 	TUsbDeviceCaps d_caps;
   394 	TInt ret = iLdd.DeviceCaps(d_caps);
   395 	if (ret != KErrNone)
   396 		{
   397 		return ret;
   398 		}
   399 	TInt totalEndpoints = d_caps().iTotalEndpoints;
   400 	if (totalEndpoints  < KRequiredNumberOfEndpoints)
   401 		{
   402 		return KErrHardwareNotAvailable;
   403 		}
   404 
   405 	// Endpoint caps
   406 	TUsbcEndpointData data[KUsbcMaxEndpoints];
   407 	TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data));
   408 	ret = iLdd.EndpointCaps(dataptr);
   409 	if (ret != KErrNone)
   410 		{
   411 		return ret;
   412 		}
   413 
   414 	// Set the active interface
   415 	TUsbcScInterfaceInfoBuf ifc;
   416 	TInt ep_found = 0;
   417 	TBool foundBulkIN = EFalse;
   418 	TBool foundBulkOUT = EFalse;
   419 
   420 	for (TInt i = 0; i < totalEndpoints ; i++)
   421 		{
   422 		const TUsbcEndpointCaps* caps = &data[i].iCaps;
   423 		const TInt maxPacketSize = caps->MaxPacketSize();
   424 		if (!foundBulkIN &&
   425 			(caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirIn)) == (KUsbEpTypeBulk | KUsbEpDirIn))
   426 			{
   427 			// InEndpoint is going to be our TX (IN, write) endpoint
   428 			ifc().iEndpointData[0].iType = KUsbEpTypeBulk;
   429 			if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) == KUsbDevCapsFeatureWord1_EndpointResourceAllocV2)
   430 				ifc().iEndpointData[0].iFeatureWord1  = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering;
   431 			ifc().iEndpointData[0].iDir  = KUsbEpDirIn;
   432 			ifc().iEndpointData[0].iSize = maxPacketSize;
   433 			ifc().iEndpointData[0].iInterval_Hs = 0;
   434 			ifc().iEndpointData[0].iBufferSize = KMaxScBufferSize;
   435 			foundBulkIN = ETrue;
   436 			if (++ep_found == KRequiredNumberOfEndpoints)
   437 				{
   438 				break;
   439 				}
   440 			continue;
   441 			}
   442 		if (!foundBulkOUT &&
   443 			(caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirOut)) == (KUsbEpTypeBulk | KUsbEpDirOut))
   444 			{
   445 			// OutEndpoint is going to be our RX (OUT, read) endpoint
   446 			ifc().iEndpointData[1].iType = KUsbEpTypeBulk;
   447 			if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) == KUsbDevCapsFeatureWord1_EndpointResourceAllocV2)
   448 				ifc().iEndpointData[1].iFeatureWord1  = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering;
   449 			ifc().iEndpointData[1].iDir  = KUsbEpDirOut;
   450 			ifc().iEndpointData[1].iSize = maxPacketSize;
   451 			ifc().iEndpointData[1].iInterval_Hs = 0;
   452 			ifc().iEndpointData[1].iBufferSize = KMaxScBufferSize;
   453 			ifc().iEndpointData[1].iReadSize = KMaxScReadSize;
   454 
   455 			foundBulkOUT = ETrue;
   456 			if (++ep_found == KRequiredNumberOfEndpoints)
   457 				{
   458 				break;
   459 				}
   460 			continue;
   461 			}
   462 		}
   463 	if (ep_found != KRequiredNumberOfEndpoints)
   464 		{
   465 		return KErrHardwareNotAvailable;
   466 		}
   467 
   468 	_LIT16(string, "USB Mass Storage Interface");
   469 	ifc().iString = const_cast<TDesC16*>(&string);
   470 	ifc().iTotalEndpointsUsed = KRequiredNumberOfEndpoints;
   471 	ifc().iClass.iClassNum    = 0x08;	// Mass Storage
   472 	ifc().iClass.iSubClassNum = 0x06;	// SCSI Transparent Command Set
   473 	ifc().iClass.iProtocolNum = 0x50;	// Bulk Only Transport
   474 
   475 	if (d_caps().iHighSpeed)
   476 		{
   477 		// Tell the Protocol about it, because it might want to do some
   478 		// optimizing too.
   479 		iProtocol->ReportHighSpeedDevice();
   480 		}
   481 
   482 	if ((ret = iLdd.SetInterface(0, ifc)) == KErrNone)
   483 		{
   484 		return (iLdd.FinalizeInterface(iChunk));
   485 		}
   486 	return ret;
   487 	}
   488 
   489 void CBulkOnlyTransportUsbcScLdd::ReleaseInterface()
   490 	{
   491 	iLdd.ReleaseInterface(0);
   492 	}
   493 
   494 
   495 TInt CBulkOnlyTransportUsbcScLdd::StartControlInterface()
   496 	{
   497 	return iControlInterface->Start();
   498 	}
   499 
   500 void CBulkOnlyTransportUsbcScLdd::CancelControlInterface()
   501 	{
   502 	iControlInterface->Cancel();
   503 	}
   504 
   505 void CBulkOnlyTransportUsbcScLdd::ActivateDeviceStateNotifier()
   506 	{
   507 	iDeviceStateNotifier->Activate();
   508 	}
   509 
   510 void CBulkOnlyTransportUsbcScLdd::CancelDeviceStateNotifier()
   511 	{
   512 	iDeviceStateNotifier->Cancel();
   513 	}
   514 
   515 
   516 void CBulkOnlyTransportUsbcScLdd::CancelReadWriteRequests()
   517 	{
   518 	__FNLOG("CBulkOnlyTransportUsbcScLdd::CancelReadWriteRequests");
   519 	TUsbcScChunkHeader chunkHeader(*iChunk);
   520 	for (TInt i = 0; i < chunkHeader.iAltSettings->iNumOfAltSettings; i++)
   521 		{
   522 		TInt8* endpoint = (TInt8*) (chunkHeader.iAltSettings->iAltTableOffset[i] + (TInt) iChunk->Base());
   523 		TInt numOfEps = chunkHeader.GetNumberOfEndpoints(i);
   524         __ASSERT_DEBUG(numOfEps >= 0, User::Invariant());
   525 		for (TInt j = 1; j <= numOfEps; j++)
   526 			{
   527 			TUsbcScHdrEndpointRecord* endpointInf = (TUsbcScHdrEndpointRecord*) &(endpoint[j * chunkHeader.iAltSettings->iEpRecordSize]);
   528 			if (endpointInf->Direction() == KUsbScHdrEpDirectionOut)
   529 				{
   530 				iLdd.ReadCancel(endpointInf->iBufferNo);
   531 				}
   532 			if (endpointInf->Direction() == KUsbScHdrEpDirectionIn)
   533 				{
   534 				iLdd.WriteCancel(endpointInf->iBufferNo);
   535 				}
   536 			}
   537 		}
   538 	}
   539 
   540 void CBulkOnlyTransportUsbcScLdd::AllocateEndpointResources()
   541 	{
   542 	TUsbcScChunkHeader chunkHeader(*iChunk);
   543 	for (TInt i = 0; i < chunkHeader.iAltSettings->iNumOfAltSettings; i++)
   544 		{
   545 		TInt8* endpoint = (TInt8*) (chunkHeader.iAltSettings->iAltTableOffset[i] + (TInt) iChunk->Base()); 
   546 
   547 		for (TInt j = 1; j <= chunkHeader.GetNumberOfEndpoints(i); j++) 
   548 			{
   549 			TUsbcScHdrEndpointRecord* endpointInf = (TUsbcScHdrEndpointRecord*) &(endpoint[j * chunkHeader.iAltSettings->iEpRecordSize]);
   550 			if (endpointInf->Direction() == KUsbScHdrEpDirectionOut)
   551 				{
   552 				iOutEndpoint = j;
   553 				}
   554 			if (endpointInf->Direction() == KUsbScHdrEpDirectionIn)
   555 				{
   556 				iInEndpoint = j;
   557 				}
   558 			}
   559 		}
   560 
   561 	TUsbDeviceCaps d_caps;
   562 	TInt err;
   563 	TInt ret = iLdd.DeviceCaps(d_caps);
   564 	if (ret == KErrNone)
   565 		{
   566 		if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != KUsbDevCapsFeatureWord1_EndpointResourceAllocV2)
   567 			{		
   568 			__PRINT(_L("CBulkOnlyTransportUsbcScLdd::Start  - Setting up DMA and double buffering\n"));
   569 				// Set up DMA if possible (errors are non-critical)
   570 			err = iLdd.AllocateEndpointResource(iOutEndpoint, EUsbcEndpointResourceDMA);
   571 			if (err != KErrNone)
   572 				{
   573 				__PRINT1(_L("Set DMA on OUT endpoint failed with error code: %d"), err);
   574 				}
   575 			err = iLdd.AllocateEndpointResource(iInEndpoint, EUsbcEndpointResourceDMA);
   576 			if (err != KErrNone)
   577 				{
   578 				__PRINT1(_L("Set DMA on IN endpoint failed with error code: %d"), err);
   579 				}
   580 
   581 				// Set up Double Buffering if possible (errors are non-critical)
   582 			err = iLdd.AllocateEndpointResource(iOutEndpoint, EUsbcEndpointResourceDoubleBuffering);
   583 			if (err != KErrNone)
   584 				{
   585 				__PRINT1(_L("Set Double Buffering on OUT endpoint failed with error code: %d"), err);
   586 				}
   587 			err = iLdd.AllocateEndpointResource(iInEndpoint, EUsbcEndpointResourceDoubleBuffering);
   588 				if (err != KErrNone)
   589 				{
   590 				__PRINT1(_L("Set Double Buffering on IN endpoint failed with error code: %d"), err);
   591 				}
   592 			}
   593 		}
   594 	
   595 	err = OpenEndpoints();
   596 	}
   597 
   598 TInt CBulkOnlyTransportUsbcScLdd::OpenEndpoints()
   599 	{
   600 	TInt res = iLdd.OpenEndpoint(iSCReadEndpointBuf, iOutEndpoint);
   601 	if (res == KErrNone)
   602 		{
   603 		res = iLdd.OpenEndpoint(iSCWriteEndpointBuf, iInEndpoint);
   604 		if (res == KErrNone)
   605 			{
   606 			iSCWriteEndpointBuf.GetInBufferRange((TAny*&)iDataPtr, iInBufferLength);
   607 			res = iControlInterface->OpenEp0();
   608 			}
   609 		return res;
   610 		}
   611 
   612 	return res;
   613 	}
   614 
   615 
   616 TInt CBulkOnlyTransportUsbcScLdd::GetDeviceStatus(TUsbcDeviceState& deviceStatus)
   617 	{
   618 	return iLdd.DeviceStatus(deviceStatus);
   619 	}
   620 
   621 void CBulkOnlyTransportUsbcScLdd::FlushData()
   622 	{
   623 	// Intentionally Left Blank Do Nothing 
   624 	}
   625 
   626 /**
   627  * Read out rest data from OutEndpoint and discard them
   628  */
   629 void CBulkOnlyTransportUsbcScLdd::ReadAndDiscardData(TInt /*aBytes*/)
   630 	{
   631 	__FNLOG("CBulkOnlyTransport::ReadAndDiscardData");
   632 	TRequestStatus status;
   633 	TInt r = KErrNone; // Lets assume there is no data
   634 	do
   635 		{
   636 		iSCReadSize = 0;
   637 		status = KErrNone;
   638 		r = iSCReadEndpointBuf.TakeBuffer(iSCReadData,iSCReadSize,iReadZlp,status);
   639 		iSCReadEndpointBuf.Expire();
   640 		}
   641 	while (r == KErrCompletion);
   642 
   643 	if (r == KErrNone)
   644 		{
   645 		TRequestStatus* stat = &status;
   646 		User::RequestComplete(stat, KErrNone);
   647 		}
   648 	}
   649 
   650 /**
   651 Called by the protocol to determine how many bytes of data are available in the read buffer.
   652 
   653 @return The number of bytes available in the read buffer
   654 */
   655 TInt CBulkOnlyTransportUsbcScLdd::BytesAvailable()
   656 	{
   657 	// Intentionally Left Blank Do Nothing 
   658 	return 0;
   659 	}
   660 
   661 void CBulkOnlyTransportUsbcScLdd::StallEndpointAndWaitForClear()
   662 	{
   663 	__FNLOG("CBulkOnlyTransportUsbcScLdd::StallEndpointAndWaitForClear");
   664 
   665 	// Now stall this endpoint
   666 	__PRINT1(_L("Stalling endpoint %d"), iInEndpoint);
   667 	TInt r = iLdd.HaltEndpoint(iInEndpoint);
   668 	if (r != KErrNone)
   669 		{
   670 		__PRINT2(_L("Error: stalling ep %d failed: %d"), iInEndpoint, r);
   671 		}
   672 	TEndpointState ep_state;
   673 	TInt i = 0;
   674 	do
   675 		{
   676 		// Wait for 10ms before checking the ep status
   677 		User::After(10000);
   678 		iLdd.EndpointStatus(iInEndpoint, ep_state);
   679 		if (++i >= 550)
   680 			{
   681 			// 5.5 secs should be enough (see 9.2.6.1 Request Processing Timing)
   682 			__PRINT1(_L("Error: Checked for ep %d de-stall for 5.5s - giving up now"), iInEndpoint);
   683 			// We can now only hope for a Reset Recovery
   684 			return;
   685 			}
   686 		} while ((ep_state == EEndpointStateStalled) && iStarted);
   687 	__PRINT2(_L("Checked for ep %d de-stall: %d time(s)"), iInEndpoint, i);
   688 	}
   689 
   690 /**
   691 Read CBW data from the host and decode it.
   692 */
   693 void CBulkOnlyTransportUsbcScLdd::ReadCBW()
   694 	{
   695 	__FNLOG("CBulkOnlyTransportUsbcScLdd::ReadCBW");
   696 	if (IsActive())
   697 		{
   698 		__PRINT(_L("Still active\n"));
   699 		__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive)); 
   700 		return;
   701 		}
   702 	TInt r = KErrNone;
   703 	do
   704 		{
   705 		r = ReadUsb();
   706 		if ((r == KErrCompletion) && (iSCReadSize == KCbwLength))  
   707 			{
   708 			iCurrentState = EWaitForCBW;
   709 			iStatus = KErrNone;
   710 			DecodeCBW();
   711 			iSCReadSize = 0;
   712 			}
   713 		else if (r == KErrNone)
   714 			{
   715 			iCurrentState = EWaitForCBW;
   716 			SetActive();
   717 			}
   718 		else if ((r == KErrCompletion) && (iSCReadSize != KCbwLength))
   719 			{
   720 			ExpireData(iSCReadData);
   721 			}
   722 		}while ((r == KErrCompletion) && (!IsActive()));
   723 	}
   724 
   725 void CBulkOnlyTransportUsbcScLdd::ExpireData(TAny* aAddress)
   726 	{
   727 	if (aAddress)
   728 		{
   729 		iSCReadEndpointBuf.Expire(aAddress);
   730 		}
   731 	else
   732 		{
   733 		iSCReadEndpointBuf.Expire();
   734 		}
   735 	}
   736 
   737 void CBulkOnlyTransportUsbcScLdd::ProcessCbwEvent()
   738 	{
   739 	ReadCBW();
   740 	}
   741 
   742 /**
   743 Request data form the host for the protocol
   744 
   745 @param aLength amount of data (in bytes) to be received from the host
   746 */
   747 void CBulkOnlyTransportUsbcScLdd::ReadData(TUint /*aLength*/)
   748 	{
   749 	__FNLOG("CBulkOnlyTransportUsbcScLdd::ReadData");
   750 	if (IsActive())
   751 		{
   752 		__PRINT(_L("Still active\n"));
   753 		__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
   754 		return;
   755 		}
   756 	TInt r = KErrNone;
   757 	do
   758 		{
   759 		r = ReadUsb();
   760 		iCurrentState = EReadingData;
   761 		if (r == KErrCompletion)
   762 			{
   763 			iReadBufPtr.Set((TUint8*) iSCReadData, iSCReadSize, iSCReadSize);
   764 			iStatus = KErrNone;
   765 			ProcessDataFromHost();
   766 			iSCReadSize = 0;
   767 			}
   768 		else if (r == KErrNone)
   769 			{
   770 			iSCReadSize = 0;
   771 			SetActive();
   772 			}
   773 
   774 		}while ((r == KErrCompletion) && (!IsActive()));
   775 	}
   776 
   777 void CBulkOnlyTransportUsbcScLdd::ProcessDataFromHost()
   778 	{
   779 	TInt ret = KErrNone;
   780 		{
   781 		if (iReadSetUp)
   782 			{
   783 			ret = iProtocol->ReadComplete(KErrNone);
   784 			}
   785 #ifndef MSDC_MULTITHREADED
   786 		ExpireData(iSCReadData);
   787 #endif
   788 		TUint deviceDataLength = iSCReadSize; // What was written to the disk // static_cast<TUint>(iReadBuf.Length());
   789 		if(ret == KErrCompletion)
   790 			{
   791 			// The protocol has indicated with KErrCompletion that sufficient
   792 			// data is available in the buffer to process the transfer immediately.
   793 
   794 			//iDataResidue is initially set to host data length as we do not know how much data is there in the 'LDD transfer'. 
   795 			//After a TakeBuffer call, iSCReadSize in updated and set to deviceDataLength
   796 			iDataResidue -= deviceDataLength;
   797 			}
   798 		else
   799 			{
   800 			iDataResidue -= deviceDataLength;
   801 
   802 			// The protocol has indicated that transfer is
   803 			// complete, so send the CSW response to the host.
   804 			iReadSetUp = EFalse;
   805 
   806 			if (ret != KErrNone)
   807 				{
   808 				iCmdStatus = ECommandFailed;
   809 				}
   810 
   811 			if (iDataResidue)
   812 				{
   813 				__PRINT(_L("Discarding residue"));
   814 				// we have to read as much data as available that host PC sends;
   815 				// otherwise, bulk-out endpoint will need to keep sending NAK back.
   816 				ReadAndDiscardData(iDataResidue); 
   817 				}
   818 
   819 			SendCSW(iCbwTag, iDataResidue, iCmdStatus);
   820 			}
   821 		}
   822 	}
   823 
   824 void CBulkOnlyTransportUsbcScLdd::WriteUsb(TRequestStatus& aStatus, TPtrC8& aDes, TUint aLength, TBool aZlpRequired)
   825 	{
   826 	TUint aOffset = (TUint) aDes.Ptr() - (TUint) iChunk->Base();
   827 	iSCWriteEndpointBuf.WriteBuffer(aOffset, aLength, aZlpRequired, aStatus);
   828 	}
   829 
   830 void CBulkOnlyTransportUsbcScLdd::SetCbwPtr()
   831 	{
   832 	iCbwBufPtr.Set((TUint8*)iSCReadData, iSCReadSize);
   833 	}
   834 
   835 TPtr8& CBulkOnlyTransportUsbcScLdd::SetCommandBufPtr(TUint aLength)
   836 	{
   837 	TPtr8 writeBuf((TUint8*) iDataPtr, aLength);
   838 	iCommandBufPtr.Set(writeBuf);
   839 	return iCommandBufPtr;
   840 	}
   841 
   842 void CBulkOnlyTransportUsbcScLdd::SetReadDataBufPtr(TUint /*aLength*/)
   843 	{
   844 	// Do nothing for now 
   845 	}
   846 
   847 TPtr8& CBulkOnlyTransportUsbcScLdd::SetDataBufPtr()
   848 	{
   849 	TPtr8 writeBuf((TUint8*) iDataPtr, iInBufferLength);
   850 	iDataBufPtr.Set(writeBuf);
   851 	return iDataBufPtr;
   852 	}
   853 
   854 void CBulkOnlyTransportUsbcScLdd::SetPaddingBufPtr(TUint aLength)
   855 	{
   856 	TPtr8 writeBuf((TUint8*) iDataPtr, aLength, aLength);
   857 	iPaddingBufPtr.Set(writeBuf);
   858 	}
   859 
   860 void CBulkOnlyTransportUsbcScLdd::SetCswBufPtr(TUint aLength)
   861 	{
   862 	TPtr8 writeBuf((TUint8*) iDataPtr, aLength, aLength);
   863 	iCswBufPtr.Set(writeBuf);
   864 	}
   865 
   866 void CBulkOnlyTransportUsbcScLdd::ProcessReadingDataEvent()
   867 	{
   868 	ReadData();
   869 	}
   870 
   871 TInt CBulkOnlyTransportUsbcScLdd::ReadUsb(TUint /*aLength*/)
   872 	{
   873 	__FNLOG("CBulkOnlyTransportUsbcScLdd::ReadUSB");
   874 	return iSCReadEndpointBuf.TakeBuffer(iSCReadData,iSCReadSize,iReadZlp,iStatus);
   875 	}
   876 
   877 void CBulkOnlyTransportUsbcScLdd::DiscardData(TUint aLength)
   878 	{
   879 	TUint c = 0;
   880 	TRequestStatus status;
   881 	TInt r = KErrNone;
   882 	while (c < aLength)
   883 		{
   884 		iSCReadSize = 0;
   885 		status = KErrNone;
   886 		r = iSCReadEndpointBuf.TakeBuffer(iSCReadData,iSCReadSize,iReadZlp,status);
   887 		c += iSCReadSize;
   888 		if (r == KErrNone)
   889 			User::WaitForRequest(status);
   890 		if (r == KErrCompletion)
   891 			{
   892 			iSCReadEndpointBuf.Expire();
   893 			}
   894 		iSCReadSize = 0;
   895 		}
   896 	}
   897 
   898 void CBulkOnlyTransportUsbcScLdd::WriteToClient(TUint aLength)
   899 	{
   900 	TUint c = 0;
   901 	TRequestStatus status;
   902 	TInt r = KErrNone;
   903 	while (c < aLength)
   904 		{
   905 		iSCReadSize = 0;
   906 		status = KErrNone;
   907 		r = iSCReadEndpointBuf.TakeBuffer(iSCReadData,iSCReadSize,iReadZlp,status);
   908 		c += iSCReadSize;
   909 		iProtocol->ReadComplete(KErrGeneral);
   910 		if (r == KErrNone)
   911 			User::WaitForRequest(status);
   912 		if (r == KErrCompletion)
   913 			{
   914 			iSCReadEndpointBuf.Expire();
   915 			}
   916 		iSCReadSize = 0;
   917 		}
   918 	}
   919 
   920 #ifdef MSDC_MULTITHREADED
   921 void CBulkOnlyTransportUsbcScLdd::GetBufferPointers(TPtr8& aDes1, TPtr8& aDes2)
   922 	{
   923 	//for DB
   924 	TUint length = (TUint) (iInBufferLength - KCswBufferSize) / 2;
   925 
   926 	TUint8* start = (TUint8*) (iDataPtr) + KCswBufferSize ; // 'first' buffer
   927 	aDes1.Set(start, length, length);
   928 
   929 	start = (TUint8*) (iDataPtr) + KCswBufferSize + length; // 'second' buffer
   930 	aDes2.Set(start, length, length);
   931 	}
   932 #endif
   933 
   934 void CBulkOnlyTransportUsbcScLdd::Activate(TRequestStatus& aStatus, TUint& aDeviceState)
   935     {
   936 	iLdd.AlternateDeviceStatusNotify(aStatus, aDeviceState);
   937     }
   938 
   939 
   940 void CBulkOnlyTransportUsbcScLdd::Cancel()
   941     {
   942 	iLdd.AlternateDeviceStatusNotifyCancel();
   943     }
   944 
   945 
   946 
   947