userlibandfileserver/fileserver/smassstorage/cbulkonlytransportusbcscldd.cpp
changeset 0 a41df078684a
child 13 46fffbe7b5a7
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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 			ifc().iEndpointData[0].iDir  = KUsbEpDirIn;
       
   430 			ifc().iEndpointData[0].iSize = maxPacketSize;
       
   431 			ifc().iEndpointData[0].iInterval_Hs = 0;
       
   432 			ifc().iEndpointData[0].iBufferSize = KMaxScBufferSize;
       
   433 			foundBulkIN = ETrue;
       
   434 			if (++ep_found == KRequiredNumberOfEndpoints)
       
   435 				{
       
   436 				break;
       
   437 				}
       
   438 			continue;
       
   439 			}
       
   440 		if (!foundBulkOUT &&
       
   441 			(caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirOut)) == (KUsbEpTypeBulk | KUsbEpDirOut))
       
   442 			{
       
   443 			// OutEndpoint is going to be our RX (OUT, read) endpoint
       
   444 			ifc().iEndpointData[1].iType = KUsbEpTypeBulk;
       
   445 			ifc().iEndpointData[1].iDir  = KUsbEpDirOut;
       
   446 			ifc().iEndpointData[1].iSize = maxPacketSize;
       
   447 			ifc().iEndpointData[1].iInterval_Hs = 0;
       
   448 			ifc().iEndpointData[1].iBufferSize = KMaxScBufferSize;
       
   449 			ifc().iEndpointData[1].iReadSize = KMaxScReadSize;
       
   450 
       
   451 			foundBulkOUT = ETrue;
       
   452 			if (++ep_found == KRequiredNumberOfEndpoints)
       
   453 				{
       
   454 				break;
       
   455 				}
       
   456 			continue;
       
   457 			}
       
   458 		}
       
   459 	if (ep_found != KRequiredNumberOfEndpoints)
       
   460 		{
       
   461 		return KErrHardwareNotAvailable;
       
   462 		}
       
   463 
       
   464 	_LIT16(string, "USB Mass Storage Interface");
       
   465 	ifc().iString = const_cast<TDesC16*>(&string);
       
   466 	ifc().iTotalEndpointsUsed = KRequiredNumberOfEndpoints;
       
   467 	ifc().iClass.iClassNum    = 0x08;	// Mass Storage
       
   468 	ifc().iClass.iSubClassNum = 0x06;	// SCSI Transparent Command Set
       
   469 	ifc().iClass.iProtocolNum = 0x50;	// Bulk Only Transport
       
   470 
       
   471 	if (d_caps().iHighSpeed)
       
   472 		{
       
   473 		// Tell the Protocol about it, because it might want to do some
       
   474 		// optimizing too.
       
   475 		iProtocol->ReportHighSpeedDevice();
       
   476 		}
       
   477 
       
   478 	if ((ret = iLdd.SetInterface(0, ifc)) == KErrNone)
       
   479 		{
       
   480 		return (iLdd.FinalizeInterface(iChunk));
       
   481 		}
       
   482 	return ret;
       
   483 	}
       
   484 
       
   485 void CBulkOnlyTransportUsbcScLdd::ReleaseInterface()
       
   486 	{
       
   487 	iLdd.ReleaseInterface(0);
       
   488 	}
       
   489 
       
   490 
       
   491 TInt CBulkOnlyTransportUsbcScLdd::StartControlInterface()
       
   492 	{
       
   493 	return iControlInterface->Start();
       
   494 	}
       
   495 
       
   496 void CBulkOnlyTransportUsbcScLdd::CancelControlInterface()
       
   497 	{
       
   498 	iControlInterface->Cancel();
       
   499 	}
       
   500 
       
   501 void CBulkOnlyTransportUsbcScLdd::ActivateDeviceStateNotifier()
       
   502 	{
       
   503 	iDeviceStateNotifier->Activate();
       
   504 	}
       
   505 
       
   506 void CBulkOnlyTransportUsbcScLdd::CancelDeviceStateNotifier()
       
   507 	{
       
   508 	iDeviceStateNotifier->Cancel();
       
   509 	}
       
   510 
       
   511 
       
   512 void CBulkOnlyTransportUsbcScLdd::CancelReadWriteRequests()
       
   513 	{
       
   514 	__FNLOG("CBulkOnlyTransportUsbcScLdd::CancelReadWriteRequests");
       
   515 	TUsbcScChunkHeader chunkHeader(*iChunk);
       
   516 	for (TInt i = 0; i < chunkHeader.iAltSettings->iNumOfAltSettings; i++)
       
   517 		{
       
   518 		TInt8* endpoint = (TInt8*) (chunkHeader.iAltSettings->iAltTableOffset[i] + (TInt) iChunk->Base());
       
   519 		TInt numOfEps = chunkHeader.GetNumberOfEndpoints(i);
       
   520         __ASSERT_DEBUG(numOfEps >= 0, User::Invariant());
       
   521 		for (TInt j = 1; j <= numOfEps; j++)
       
   522 			{
       
   523 			TUsbcScHdrEndpointRecord* endpointInf = (TUsbcScHdrEndpointRecord*) &(endpoint[j * chunkHeader.iAltSettings->iEpRecordSize]);
       
   524 			if (endpointInf->Direction() == KUsbScHdrEpDirectionOut)
       
   525 				{
       
   526 				iLdd.ReadCancel(endpointInf->iBufferNo);
       
   527 				}
       
   528 			if (endpointInf->Direction() == KUsbScHdrEpDirectionIn)
       
   529 				{
       
   530 				iLdd.WriteCancel(endpointInf->iBufferNo);
       
   531 				}
       
   532 			}
       
   533 		}
       
   534 	}
       
   535 
       
   536 void CBulkOnlyTransportUsbcScLdd::AllocateEndpointResources()
       
   537 	{
       
   538 	TUsbcScChunkHeader chunkHeader(*iChunk);
       
   539 	for (TInt i = 0; i < chunkHeader.iAltSettings->iNumOfAltSettings; i++)
       
   540 		{
       
   541 		TInt8* endpoint = (TInt8*) (chunkHeader.iAltSettings->iAltTableOffset[i] + (TInt) iChunk->Base()); 
       
   542 
       
   543 		for (TInt j = 1; j <= chunkHeader.GetNumberOfEndpoints(i); j++) 
       
   544 			{
       
   545 			TUsbcScHdrEndpointRecord* endpointInf = (TUsbcScHdrEndpointRecord*) &(endpoint[j * chunkHeader.iAltSettings->iEpRecordSize]);
       
   546 			if (endpointInf->Direction() == KUsbScHdrEpDirectionOut)
       
   547 				{
       
   548 				iOutEndpoint = j;
       
   549 				}
       
   550 			if (endpointInf->Direction() == KUsbScHdrEpDirectionIn)
       
   551 				{
       
   552 				iInEndpoint = j;
       
   553 				}
       
   554 			}
       
   555 		}
       
   556 		
       
   557 	__PRINT(_L("CBulkOnlyTransportUsbcScLdd::Start  - Setting up DMA and double buffering\n"));
       
   558 	// Set up DMA if possible (errors are non-critical)
       
   559 	TInt err = iLdd.AllocateEndpointResource(iOutEndpoint, EUsbcEndpointResourceDMA);
       
   560 	if (err != KErrNone)
       
   561 		{
       
   562 		__PRINT1(_L("Set DMA on OUT endpoint failed with error code: %d"), err);
       
   563 		}
       
   564 	err = iLdd.AllocateEndpointResource(iInEndpoint, EUsbcEndpointResourceDMA);
       
   565 	if (err != KErrNone)
       
   566 		{
       
   567 		__PRINT1(_L("Set DMA on IN endpoint failed with error code: %d"), err);
       
   568 		}
       
   569 
       
   570 	// Set up Double Buffering if possible (errors are non-critical)
       
   571 	err = iLdd.AllocateEndpointResource(iOutEndpoint, EUsbcEndpointResourceDoubleBuffering);
       
   572 	if (err != KErrNone)
       
   573 		{
       
   574 		__PRINT1(_L("Set Double Buffering on OUT endpoint failed with error code: %d"), err);
       
   575 		}
       
   576 	err = iLdd.AllocateEndpointResource(iInEndpoint, EUsbcEndpointResourceDoubleBuffering);
       
   577 	if (err != KErrNone)
       
   578 		{
       
   579 		__PRINT1(_L("Set Double Buffering on IN endpoint failed with error code: %d"), err);
       
   580 		}
       
   581 
       
   582 	
       
   583 	err = OpenEndpoints();
       
   584 	}
       
   585 
       
   586 TInt CBulkOnlyTransportUsbcScLdd::OpenEndpoints()
       
   587 	{
       
   588 	TInt res = iLdd.OpenEndpoint(iSCReadEndpointBuf, iOutEndpoint);
       
   589 	if (res == KErrNone)
       
   590 		{
       
   591 		res = iLdd.OpenEndpoint(iSCWriteEndpointBuf, iInEndpoint);
       
   592 		if (res == KErrNone)
       
   593 			{
       
   594 			iSCWriteEndpointBuf.GetInBufferRange((TAny*&)iDataPtr, iInBufferLength);
       
   595 			res = iControlInterface->OpenEp0();
       
   596 			}
       
   597 		return res;
       
   598 		}
       
   599 
       
   600 	return res;
       
   601 	}
       
   602 
       
   603 
       
   604 TInt CBulkOnlyTransportUsbcScLdd::GetDeviceStatus(TUsbcDeviceState& deviceStatus)
       
   605 	{
       
   606 	return iLdd.DeviceStatus(deviceStatus);
       
   607 	}
       
   608 
       
   609 void CBulkOnlyTransportUsbcScLdd::FlushData()
       
   610 	{
       
   611 	// Intentionally Left Blank Do Nothing 
       
   612 	}
       
   613 
       
   614 /**
       
   615  * Read out rest data from OutEndpoint and discard them
       
   616  */
       
   617 void CBulkOnlyTransportUsbcScLdd::ReadAndDiscardData(TInt /*aBytes*/)
       
   618 	{
       
   619 	__FNLOG("CBulkOnlyTransport::ReadAndDiscardData");
       
   620 	TRequestStatus status;
       
   621 	TInt r = KErrNone; // Lets assume there is no data
       
   622 	do
       
   623 		{
       
   624 		iSCReadSize = 0;
       
   625 		status = KErrNone;
       
   626 		r = iSCReadEndpointBuf.TakeBuffer(iSCReadData,iSCReadSize,iReadZlp,status);
       
   627 		iSCReadEndpointBuf.Expire();
       
   628 		}
       
   629 	while (r == KErrCompletion);
       
   630 
       
   631 	if (r == KErrNone)
       
   632 		{
       
   633 		TRequestStatus* stat = &status;
       
   634 		User::RequestComplete(stat, KErrNone);
       
   635 		}
       
   636 	}
       
   637 
       
   638 /**
       
   639 Called by the protocol to determine how many bytes of data are available in the read buffer.
       
   640 
       
   641 @return The number of bytes available in the read buffer
       
   642 */
       
   643 TInt CBulkOnlyTransportUsbcScLdd::BytesAvailable()
       
   644 	{
       
   645 	// Intentionally Left Blank Do Nothing 
       
   646 	return 0;
       
   647 	}
       
   648 
       
   649 void CBulkOnlyTransportUsbcScLdd::StallEndpointAndWaitForClear()
       
   650 	{
       
   651 	__FNLOG("CBulkOnlyTransportUsbcScLdd::StallEndpointAndWaitForClear");
       
   652 
       
   653 	// Now stall this endpoint
       
   654 	__PRINT1(_L("Stalling endpoint %d"), iInEndpoint);
       
   655 	TInt r = iLdd.HaltEndpoint(iInEndpoint);
       
   656 	if (r != KErrNone)
       
   657 		{
       
   658 		__PRINT2(_L("Error: stalling ep %d failed: %d"), iInEndpoint, r);
       
   659 		}
       
   660 	TEndpointState ep_state;
       
   661 	TInt i = 0;
       
   662 	do
       
   663 		{
       
   664 		// Wait for 10ms before checking the ep status
       
   665 		User::After(10000);
       
   666 		iLdd.EndpointStatus(iInEndpoint, ep_state);
       
   667 		if (++i >= 550)
       
   668 			{
       
   669 			// 5.5 secs should be enough (see 9.2.6.1 Request Processing Timing)
       
   670 			__PRINT1(_L("Error: Checked for ep %d de-stall for 5.5s - giving up now"), iInEndpoint);
       
   671 			// We can now only hope for a Reset Recovery
       
   672 			return;
       
   673 			}
       
   674 		} while ((ep_state == EEndpointStateStalled) && iStarted);
       
   675 	__PRINT2(_L("Checked for ep %d de-stall: %d time(s)"), iInEndpoint, i);
       
   676 	}
       
   677 
       
   678 /**
       
   679 Read CBW data from the host and decode it.
       
   680 */
       
   681 void CBulkOnlyTransportUsbcScLdd::ReadCBW()
       
   682 	{
       
   683 	__FNLOG("CBulkOnlyTransportUsbcScLdd::ReadCBW");
       
   684 	if (IsActive())
       
   685 		{
       
   686 		__PRINT(_L("Still active\n"));
       
   687 		__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive)); 
       
   688 		return;
       
   689 		}
       
   690 	TInt r = KErrNone;
       
   691 	do
       
   692 		{
       
   693 		r = ReadUsb();
       
   694 		if ((r == KErrCompletion) && (iSCReadSize == KCbwLength))  
       
   695 			{
       
   696 			iCurrentState = EWaitForCBW;
       
   697 			iStatus = KErrNone;
       
   698 			DecodeCBW();
       
   699 			iSCReadSize = 0;
       
   700 			}
       
   701 		else if (r == KErrNone)
       
   702 			{
       
   703 			iCurrentState = EWaitForCBW;
       
   704 			SetActive();
       
   705 			}
       
   706 		else if ((r == KErrCompletion) && (iSCReadSize != KCbwLength))
       
   707 			{
       
   708 			ExpireData(iSCReadData);
       
   709 			}
       
   710 		}while ((r == KErrCompletion) && (!IsActive()));
       
   711 	}
       
   712 
       
   713 void CBulkOnlyTransportUsbcScLdd::ExpireData(TAny* aAddress)
       
   714 	{
       
   715 	if (aAddress)
       
   716 		{
       
   717 		iSCReadEndpointBuf.Expire(aAddress);
       
   718 		}
       
   719 	else
       
   720 		{
       
   721 		iSCReadEndpointBuf.Expire();
       
   722 		}
       
   723 	}
       
   724 
       
   725 void CBulkOnlyTransportUsbcScLdd::ProcessCbwEvent()
       
   726 	{
       
   727 	ReadCBW();
       
   728 	}
       
   729 
       
   730 /**
       
   731 Request data form the host for the protocol
       
   732 
       
   733 @param aLength amount of data (in bytes) to be received from the host
       
   734 */
       
   735 void CBulkOnlyTransportUsbcScLdd::ReadData(TUint /*aLength*/)
       
   736 	{
       
   737 	__FNLOG("CBulkOnlyTransportUsbcScLdd::ReadData");
       
   738 	if (IsActive())
       
   739 		{
       
   740 		__PRINT(_L("Still active\n"));
       
   741 		__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
       
   742 		return;
       
   743 		}
       
   744 	TInt r = KErrNone;
       
   745 	do
       
   746 		{
       
   747 		r = ReadUsb();
       
   748 		iCurrentState = EReadingData;
       
   749 		if (r == KErrCompletion)
       
   750 			{
       
   751 			iReadBufPtr.Set((TUint8*) iSCReadData, iSCReadSize, iSCReadSize);
       
   752 			iStatus = KErrNone;
       
   753 			ProcessDataFromHost();
       
   754 			iSCReadSize = 0;
       
   755 			}
       
   756 		else if (r == KErrNone)
       
   757 			{
       
   758 			iSCReadSize = 0;
       
   759 			SetActive();
       
   760 			}
       
   761 
       
   762 		}while ((r == KErrCompletion) && (!IsActive()));
       
   763 	}
       
   764 
       
   765 void CBulkOnlyTransportUsbcScLdd::ProcessDataFromHost()
       
   766 	{
       
   767 	TInt ret = KErrNone;
       
   768 		{
       
   769 		if (iReadSetUp)
       
   770 			{
       
   771 			ret = iProtocol->ReadComplete(KErrNone);
       
   772 			}
       
   773 #ifndef MSDC_MULTITHREADED
       
   774 		ExpireData(iSCReadData);
       
   775 #endif
       
   776 		TUint deviceDataLength = iSCReadSize; // What was written to the disk // static_cast<TUint>(iReadBuf.Length());
       
   777 		if(ret == KErrCompletion)
       
   778 			{
       
   779 			// The protocol has indicated with KErrCompletion that sufficient
       
   780 			// data is available in the buffer to process the transfer immediately.
       
   781 
       
   782 			//iDataResidue is initially set to host data length as we do not know how much data is there in the 'LDD transfer'. 
       
   783 			//After a TakeBuffer call, iSCReadSize in updated and set to deviceDataLength
       
   784 			iDataResidue -= deviceDataLength;
       
   785 			}
       
   786 		else
       
   787 			{
       
   788 			iDataResidue -= deviceDataLength;
       
   789 
       
   790 			// The protocol has indicated that transfer is
       
   791 			// complete, so send the CSW response to the host.
       
   792 			iReadSetUp = EFalse;
       
   793 
       
   794 			if (ret != KErrNone)
       
   795 				{
       
   796 				iCmdStatus = ECommandFailed;
       
   797 				}
       
   798 
       
   799 			if (iDataResidue)
       
   800 				{
       
   801 				__PRINT(_L("Discarding residue"));
       
   802 				// we have to read as much data as available that host PC sends;
       
   803 				// otherwise, bulk-out endpoint will need to keep sending NAK back.
       
   804 				ReadAndDiscardData(iDataResidue); 
       
   805 				}
       
   806 
       
   807 			SendCSW(iCbwTag, iDataResidue, iCmdStatus);
       
   808 			}
       
   809 		}
       
   810 	}
       
   811 
       
   812 void CBulkOnlyTransportUsbcScLdd::WriteUsb(TRequestStatus& aStatus, TPtrC8& aDes, TUint aLength, TBool aZlpRequired)
       
   813 	{
       
   814 	TUint aOffset = (TUint) aDes.Ptr() - (TUint) iChunk->Base();
       
   815 	iSCWriteEndpointBuf.WriteBuffer(aOffset, aLength, aZlpRequired, aStatus);
       
   816 	}
       
   817 
       
   818 void CBulkOnlyTransportUsbcScLdd::SetCbwPtr()
       
   819 	{
       
   820 	iCbwBufPtr.Set((TUint8*)iSCReadData, iSCReadSize);
       
   821 	}
       
   822 
       
   823 TPtr8& CBulkOnlyTransportUsbcScLdd::SetCommandBufPtr(TUint aLength)
       
   824 	{
       
   825 	TPtr8 writeBuf((TUint8*) iDataPtr, aLength);
       
   826 	iCommandBufPtr.Set(writeBuf);
       
   827 	return iCommandBufPtr;
       
   828 	}
       
   829 
       
   830 void CBulkOnlyTransportUsbcScLdd::SetReadDataBufPtr(TUint /*aLength*/)
       
   831 	{
       
   832 	// Do nothing for now 
       
   833 	}
       
   834 
       
   835 TPtr8& CBulkOnlyTransportUsbcScLdd::SetDataBufPtr()
       
   836 	{
       
   837 	TPtr8 writeBuf((TUint8*) iDataPtr, iInBufferLength);
       
   838 	iDataBufPtr.Set(writeBuf);
       
   839 	return iDataBufPtr;
       
   840 	}
       
   841 
       
   842 void CBulkOnlyTransportUsbcScLdd::SetPaddingBufPtr(TUint aLength)
       
   843 	{
       
   844 	TPtr8 writeBuf((TUint8*) iDataPtr, aLength, aLength);
       
   845 	iPaddingBufPtr.Set(writeBuf);
       
   846 	}
       
   847 
       
   848 void CBulkOnlyTransportUsbcScLdd::SetCswBufPtr(TUint aLength)
       
   849 	{
       
   850 	TPtr8 writeBuf((TUint8*) iDataPtr, aLength, aLength);
       
   851 	iCswBufPtr.Set(writeBuf);
       
   852 	}
       
   853 
       
   854 void CBulkOnlyTransportUsbcScLdd::ProcessReadingDataEvent()
       
   855 	{
       
   856 	ReadData();
       
   857 	}
       
   858 
       
   859 TInt CBulkOnlyTransportUsbcScLdd::ReadUsb(TUint /*aLength*/)
       
   860 	{
       
   861 	__FNLOG("CBulkOnlyTransportUsbcScLdd::ReadUSB");
       
   862 	return iSCReadEndpointBuf.TakeBuffer(iSCReadData,iSCReadSize,iReadZlp,iStatus);
       
   863 	}
       
   864 
       
   865 void CBulkOnlyTransportUsbcScLdd::DiscardData(TUint aLength)
       
   866 	{
       
   867 	TUint c = 0;
       
   868 	TRequestStatus status;
       
   869 	TInt r = KErrNone;
       
   870 	while (c < aLength)
       
   871 		{
       
   872 		iSCReadSize = 0;
       
   873 		status = KErrNone;
       
   874 		r = iSCReadEndpointBuf.TakeBuffer(iSCReadData,iSCReadSize,iReadZlp,status);
       
   875 		c += iSCReadSize;
       
   876 		if (r == KErrNone)
       
   877 			User::WaitForRequest(status);
       
   878 		if (r == KErrCompletion)
       
   879 			{
       
   880 			iSCReadEndpointBuf.Expire();
       
   881 			}
       
   882 		iSCReadSize = 0;
       
   883 		}
       
   884 	}
       
   885 
       
   886 void CBulkOnlyTransportUsbcScLdd::WriteToClient(TUint aLength)
       
   887 	{
       
   888 	TUint c = 0;
       
   889 	TRequestStatus status;
       
   890 	TInt r = KErrNone;
       
   891 	while (c < aLength)
       
   892 		{
       
   893 		iSCReadSize = 0;
       
   894 		status = KErrNone;
       
   895 		r = iSCReadEndpointBuf.TakeBuffer(iSCReadData,iSCReadSize,iReadZlp,status);
       
   896 		c += iSCReadSize;
       
   897 		iProtocol->ReadComplete(KErrGeneral);
       
   898 		if (r == KErrNone)
       
   899 			User::WaitForRequest(status);
       
   900 		if (r == KErrCompletion)
       
   901 			{
       
   902 			iSCReadEndpointBuf.Expire();
       
   903 			}
       
   904 		iSCReadSize = 0;
       
   905 		}
       
   906 	}
       
   907 
       
   908 #ifdef MSDC_MULTITHREADED
       
   909 void CBulkOnlyTransportUsbcScLdd::GetBufferPointers(TPtr8& aDes1, TPtr8& aDes2)
       
   910 	{
       
   911 	//for DB
       
   912 	TUint length = (TUint) (iInBufferLength - KCswBufferSize) / 2;
       
   913 
       
   914 	TUint8* start = (TUint8*) (iDataPtr) + KCswBufferSize ; // 'first' buffer
       
   915 	aDes1.Set(start, length, length);
       
   916 
       
   917 	start = (TUint8*) (iDataPtr) + KCswBufferSize + length; // 'second' buffer
       
   918 	aDes2.Set(start, length, length);
       
   919 	}
       
   920 #endif
       
   921 
       
   922 void CBulkOnlyTransportUsbcScLdd::Activate(TRequestStatus& aStatus, TUint& aDeviceState)
       
   923     {
       
   924 	iLdd.AlternateDeviceStatusNotify(aStatus, aDeviceState);
       
   925     }
       
   926 
       
   927 
       
   928 void CBulkOnlyTransportUsbcScLdd::Cancel()
       
   929     {
       
   930 	iLdd.AlternateDeviceStatusNotifyCancel();
       
   931     }
       
   932 
       
   933 
       
   934 
       
   935