userlibandfileserver/fileserver/smassstorage/cbulkonlytransportusbcldd.cpp
changeset 0 a41df078684a
child 39 5d2844f35677
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 "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 			ifc().iEndpointData[0].iDir  = KUsbEpDirIn;
       
   404 			ifc().iEndpointData[0].iSize = maxPacketSize;
       
   405 			ifc().iEndpointData[0].iInterval_Hs = 0;
       
   406 			foundBulkIN = ETrue;
       
   407 			if (++ep_found == KRequiredNumberOfEndpoints)
       
   408 				{
       
   409 				break;
       
   410 				}
       
   411 			continue;
       
   412 			}
       
   413 		if (!foundBulkOUT &&
       
   414 			(caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirOut)) == (KUsbEpTypeBulk | KUsbEpDirOut))
       
   415 			{
       
   416 			// OutEndpoint is going to be our RX (OUT, read) endpoint
       
   417 			ifc().iEndpointData[1].iType = KUsbEpTypeBulk;
       
   418 			ifc().iEndpointData[1].iDir  = KUsbEpDirOut;
       
   419 			ifc().iEndpointData[1].iSize = maxPacketSize;
       
   420 			ifc().iEndpointData[1].iInterval_Hs = 0;
       
   421 			foundBulkOUT = ETrue;
       
   422 			if (++ep_found == KRequiredNumberOfEndpoints)
       
   423 				{
       
   424 				break;
       
   425 				}
       
   426 			continue;
       
   427 			}
       
   428 		}
       
   429 	if (ep_found != KRequiredNumberOfEndpoints)
       
   430 		{
       
   431 		return KErrHardwareNotAvailable;
       
   432 		}
       
   433 
       
   434 	_LIT16(string, "USB Mass Storage Interface");
       
   435 	ifc().iString = const_cast<TDesC16*>(&string);
       
   436 	ifc().iTotalEndpointsUsed = KRequiredNumberOfEndpoints;
       
   437 	ifc().iClass.iClassNum    = 0x08;	// Mass Storage
       
   438 	ifc().iClass.iSubClassNum = 0x06;	// SCSI Transparent Command Set
       
   439 	ifc().iClass.iProtocolNum = 0x50;	// Bulk Only Transport
       
   440 
       
   441 	TUint bandwidth_priority = (EUsbcBandwidthOUTDefault | EUsbcBandwidthINDefault);
       
   442 	if (d_caps().iHighSpeed)
       
   443 		{
       
   444 		// If this device supports USB High-speed, then we request 64KB buffers
       
   445 		// (otherwise the default 4KB ones will do).
       
   446 		bandwidth_priority = (EUsbcBandwidthOUTPlus2 | EUsbcBandwidthINPlus2);
       
   447 		// Also, tell the Protocol about it, because it might want to do some
       
   448 		// optimizing too.
       
   449 		iProtocol->ReportHighSpeedDevice();
       
   450 		}
       
   451 	ret = iLdd.SetInterface(0, ifc, bandwidth_priority);
       
   452 	return ret;
       
   453 	}
       
   454 
       
   455 void CBulkOnlyTransportUsbcLdd::ReleaseInterface()
       
   456 	{
       
   457 	iLdd.ReleaseInterface(0);
       
   458 	}
       
   459 
       
   460 TInt CBulkOnlyTransportUsbcLdd::StartControlInterface()
       
   461 	{
       
   462 	return iControlInterface->Start();
       
   463 	}
       
   464 
       
   465 void CBulkOnlyTransportUsbcLdd::CancelControlInterface()
       
   466 	{
       
   467 	iControlInterface->Cancel();
       
   468 	}
       
   469 
       
   470 void CBulkOnlyTransportUsbcLdd::ActivateDeviceStateNotifier()
       
   471 	{
       
   472 	iDeviceStateNotifier->Activate();
       
   473 	}
       
   474 
       
   475 void CBulkOnlyTransportUsbcLdd::CancelDeviceStateNotifier()
       
   476 	{
       
   477 	iDeviceStateNotifier->Cancel();
       
   478 	}
       
   479 
       
   480 void CBulkOnlyTransportUsbcLdd::CancelReadWriteRequests()
       
   481 	{
       
   482 	__FNLOG("CBulkOnlyTransportUsbcLdd::CancelReadWriteRequests");
       
   483 	iLdd.WriteCancel(InEndpoint);
       
   484 	iLdd.ReadCancel(OutEndpoint);
       
   485 	}
       
   486 
       
   487 void CBulkOnlyTransportUsbcLdd::AllocateEndpointResources()
       
   488 	{
       
   489 		// Set up DMA if possible (errors are non-critical)
       
   490 	TInt err = iLdd.AllocateEndpointResource(OutEndpoint, EUsbcEndpointResourceDMA);
       
   491 	if (err != KErrNone)
       
   492 		{
       
   493 		__PRINT1(_L("Set DMA on OUT endpoint failed with error code: %d"), err);
       
   494 		}
       
   495 	err = iLdd.AllocateEndpointResource(InEndpoint, EUsbcEndpointResourceDMA);
       
   496 	if (err != KErrNone)
       
   497 		{
       
   498 		__PRINT1(_L("Set DMA on IN endpoint failed with error code: %d"), err);
       
   499 		}
       
   500 
       
   501 	// Set up Double Buffering if possible (errors are non-critical)
       
   502 	err = iLdd.AllocateEndpointResource(OutEndpoint, EUsbcEndpointResourceDoubleBuffering);
       
   503 	if (err != KErrNone)
       
   504 		{
       
   505 		__PRINT1(_L("Set Double Buffering on OUT endpoint failed with error code: %d"), err);
       
   506 		}
       
   507 	err = iLdd.AllocateEndpointResource(InEndpoint, EUsbcEndpointResourceDoubleBuffering);
       
   508 	if (err != KErrNone)
       
   509 		{
       
   510 		__PRINT1(_L("Set Double Buffering on IN endpoint failed with error code: %d"), err);
       
   511 		}
       
   512 	}
       
   513 
       
   514 TInt CBulkOnlyTransportUsbcLdd::GetDeviceStatus(TUsbcDeviceState& deviceStatus)
       
   515 	{
       
   516 	return iLdd.DeviceStatus(deviceStatus);
       
   517 	}
       
   518 
       
   519 void CBulkOnlyTransportUsbcLdd::FlushData()
       
   520 	{
       
   521 	TInt bytes;
       
   522 	const TInt err = iLdd.QueryReceiveBuffer(OutEndpoint, bytes);
       
   523 	if (err != KErrNone || bytes <= 0)
       
   524 		{
       
   525 		__PRINT1(_L("Error: err=%d bytes=%d"), bytes);
       
   526 		}
       
   527 	else
       
   528 		{
       
   529 		__PRINT1(_L("RxBuffer has %d bytes"), bytes);
       
   530 		ReadAndDiscardData(bytes);
       
   531 		}
       
   532 	}
       
   533 /**
       
   534  * Read out rest data from OutEndpoint and discard them
       
   535  */
       
   536 void CBulkOnlyTransportUsbcLdd::ReadAndDiscardData(TInt aBytes)
       
   537 	{
       
   538 	__FNLOG("CBulkOnlyTransportUsbcLdd::ReadAndDiscardData");
       
   539 	iDiscardBuf.SetMax();
       
   540 	const TUint bufsize = static_cast<TUint>(iDiscardBuf.Length());
       
   541 	TRequestStatus status;
       
   542 	while (aBytes > 0)
       
   543 		{
       
   544 		__PRINT1(_L("Bytes still to be read: %d\n"), aBytes);
       
   545 		iLdd.ReadOneOrMore(status, OutEndpoint, iDiscardBuf, bufsize);
       
   546 		User::WaitForRequest(status);
       
   547 		TInt err = status.Int();
       
   548 		if (err != KErrNone)
       
   549 			{
       
   550 			// Bad.
       
   551 			break;
       
   552 			}
       
   553 		aBytes -= iDiscardBuf.Length();
       
   554 		}
       
   555 	}
       
   556 
       
   557 /**
       
   558 Called by the protocol to determine how many bytes of data are available in the read buffer.
       
   559 
       
   560 @return The number of bytes available in the read buffer
       
   561 */
       
   562 TInt CBulkOnlyTransportUsbcLdd::BytesAvailable()
       
   563 	{
       
   564 	TInt bytes = 0;
       
   565 	TInt err = iLdd.QueryReceiveBuffer(OutEndpoint, bytes);
       
   566 	if (err != KErrNone)
       
   567 		bytes = 0;
       
   568 	return bytes;
       
   569 	}
       
   570 
       
   571 
       
   572 void CBulkOnlyTransportUsbcLdd::StallEndpointAndWaitForClear()
       
   573 	{
       
   574 	__FNLOG("CBulkOnlyTransportUsbcLdd::StallEndpointAndWaitForClear");
       
   575 
       
   576 	// Now stall this endpoint
       
   577 	__PRINT1(_L("Stalling endpoint %d"), InEndpoint);
       
   578 	TInt r = iLdd.HaltEndpoint(InEndpoint);
       
   579 	if (r != KErrNone)
       
   580 		{
       
   581 		__PRINT2(_L("Error: stalling ep %d failed: %d"), InEndpoint, r);
       
   582 		}
       
   583 	TEndpointState ep_state;
       
   584 	TInt i = 0;
       
   585 	do
       
   586 		{
       
   587 		// Wait for 10ms before checking the ep status
       
   588 		User::After(10000);
       
   589 		iLdd.EndpointStatus(InEndpoint, ep_state);
       
   590 		if (++i >= 550)
       
   591 			{
       
   592 			// 5.5 secs should be enough (see 9.2.6.1 Request Processing Timing)
       
   593 			__PRINT1(_L("Error: Checked for ep %d de-stall for 5.5s - giving up now"), InEndpoint);
       
   594 			// We can now only hope for a Reset Recovery
       
   595 			return;
       
   596 			}
       
   597 		} while ((ep_state == EEndpointStateStalled) && iStarted);
       
   598 	__PRINT2(_L("Checked for ep %d de-stall: %d time(s)"), InEndpoint, i);
       
   599 	}
       
   600 
       
   601 
       
   602 /**
       
   603 Read CBW data (KCbwLength) from the host into the read buffer.
       
   604 */
       
   605 void CBulkOnlyTransportUsbcLdd::ReadCBW()
       
   606 	{
       
   607 	__FNLOG("CBulkOnlyTransportUsbcLdd::ReadCBW");
       
   608 	if (IsActive())
       
   609 		{
       
   610 		__PRINT(_L("Still active\n"));
       
   611 		__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
       
   612 		return;
       
   613 		}
       
   614 
       
   615 	iCbwBuf.SetMax();
       
   616 	iLdd.ReadUntilShort(iStatus, OutEndpoint, iCbwBuf, KCbwLength);
       
   617 
       
   618 	iCurrentState = EWaitForCBW;
       
   619 	SetActive();
       
   620 	}
       
   621 
       
   622 void CBulkOnlyTransportUsbcLdd::ExpireData(TAny* /*aAddress*/)
       
   623 	{
       
   624 	// Intentionally left blank
       
   625 	}
       
   626 
       
   627 void CBulkOnlyTransportUsbcLdd::ProcessCbwEvent()
       
   628 	{
       
   629 	DecodeCBW();
       
   630 	}
       
   631 
       
   632 
       
   633 /**
       
   634 Request data form the host for the protocol
       
   635 
       
   636 @param aLength amount of data (in bytes) to be received from the host
       
   637 */
       
   638 void CBulkOnlyTransportUsbcLdd::ReadData(TUint aLength)
       
   639 	{
       
   640 	__FNLOG("CBulkOnlyTransportUsbcLdd::ReadData");
       
   641 	if (IsActive())
       
   642 		{
       
   643 		__PRINT(_L("Still active\n"));
       
   644 		__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
       
   645 		return;
       
   646 		}
       
   647 	
       
   648 	SetReadDataBufPtr(aLength);
       
   649 	iLdd.Read(iStatus, OutEndpoint, iReadBufPtr, aLength);
       
   650 
       
   651 	iCurrentState = EReadingData;
       
   652 	SetActive();
       
   653 	}
       
   654 
       
   655 void CBulkOnlyTransportUsbcLdd::WriteUsb(TRequestStatus& aStatus, TPtrC8& aDes, TUint aLength, TBool aZlpRequired)
       
   656 	{
       
   657 	iLdd.Write(aStatus, InEndpoint, aDes, aLength, aZlpRequired);
       
   658 	}
       
   659 
       
   660 void CBulkOnlyTransportUsbcLdd::SetCbwPtr()
       
   661 	{
       
   662 	iCbwBufPtr.Set(iCbwBuf.Ptr(), iCbwBuf.Length());
       
   663 	}
       
   664 
       
   665 TPtr8& CBulkOnlyTransportUsbcLdd::SetCommandBufPtr(TUint aLength)
       
   666 	{
       
   667 	iCommandBufPtr.Set((TUint8*) iCommandBuf.Ptr(), aLength, aLength );
       
   668 	return iCommandBufPtr;
       
   669 	}
       
   670 
       
   671 void CBulkOnlyTransportUsbcLdd::SetReadDataBufPtr(TUint aLength) //Write10(Host->Device
       
   672 	{
       
   673 	if (iSwap)
       
   674 		{
       
   675 		iDataBuf1.SetLength(aLength);
       
   676 		iReadBufPtr.Set(iDataBuf1.LeftTPtr(iDataBuf1.Length()));
       
   677 		iSwap = EFalse;
       
   678 		}
       
   679 	else
       
   680 		{
       
   681 		iDataBuf2.SetLength(aLength);
       
   682 		iReadBufPtr.Set(iDataBuf2.LeftTPtr(iDataBuf2.Length()));
       
   683 		iSwap = ETrue;
       
   684 		}
       
   685 	}
       
   686 
       
   687 TPtr8& CBulkOnlyTransportUsbcLdd::SetDataBufPtr() //Read10(Device->Host)
       
   688 	{
       
   689 	if (iSwap)
       
   690 		{
       
   691 		iDataBufPtr.Set((TUint8*) iDataBuf1.Ptr(), KMaxBufSize, KMaxBufSize);
       
   692 		iSwap = EFalse;
       
   693 		}
       
   694 	else
       
   695 		{
       
   696 		iDataBufPtr.Set((TUint8*) iDataBuf2.Ptr(), KMaxBufSize, KMaxBufSize);
       
   697 		iSwap = ETrue;
       
   698 		}
       
   699 	return iDataBufPtr;
       
   700 	}
       
   701 
       
   702 void CBulkOnlyTransportUsbcLdd::SetPaddingBufPtr(TUint aLength)
       
   703 	{
       
   704 	iPaddingBufPtr.Set((TUint8*) iBuf.Ptr(), aLength, aLength );
       
   705 	}
       
   706 
       
   707 
       
   708 void CBulkOnlyTransportUsbcLdd::SetCswBufPtr(TUint aLength)
       
   709 	{
       
   710 	iCswBufPtr.Set((TUint8*) iCswBuf.Ptr(), aLength, aLength );
       
   711 	}
       
   712 
       
   713 void CBulkOnlyTransportUsbcLdd::ProcessReadingDataEvent()
       
   714 	{
       
   715 	TInt ret = KErrNone;
       
   716     FOREVER
       
   717 		{
       
   718 		if (iReadSetUp)
       
   719 			{
       
   720 			ret = iProtocol->ReadComplete(KErrNone);
       
   721 			}
       
   722 
       
   723 		TUint deviceDataLength = iBufSize; // This is the amount (maximum in case of SC Ldd) to be read next.
       
   724 
       
   725 		if(ret == KErrCompletion)
       
   726 			{
       
   727 			// The protocol has indicated with KErrCompletion that sufficient
       
   728 			// data is available in the buffer to process the transfer immediately.
       
   729 
       
   730 			iDataResidue -= iReadBufPtr.Length();
       
   731 			SetReadDataBufPtr(deviceDataLength);
       
   732 
       
   733 			iLdd.Read(iStatus, OutEndpoint, iReadBufPtr, deviceDataLength);
       
   734 			User::WaitForRequest(iStatus);
       
   735 			if (iStatus != KErrNone)
       
   736 				{
       
   737 				// An error occurred - halt endpoints for reset recovery
       
   738 				__PRINT1(_L("Error %d in EReadingData, halt endpoints \n"), iStatus.Int());
       
   739 				SetPermError();
       
   740 				return;
       
   741 				}
       
   742 			}
       
   743 		else if(ret == KErrNotReady)
       
   744 			{
       
   745 			// The protocol has indicated with KErrNotReady that insufficient
       
   746 			// data is available in the buffer, so should wait for it to arrive
       
   747 
       
   748             iDataResidue -= iReadBufPtr.Length();
       
   749 			ReadData(deviceDataLength);
       
   750 			break;
       
   751 			}
       
   752 		else
       
   753 			{
       
   754 			// The protocol has indicated that transfer is
       
   755 			// complete, so send the CSW response to the host.
       
   756 			iDataResidue -= iReadBufPtr.Length();
       
   757 			iReadSetUp = EFalse;
       
   758 
       
   759 			if (ret != KErrNone)
       
   760 				{
       
   761 				iCmdStatus = ECommandFailed;
       
   762 				}
       
   763 
       
   764 			if (iDataResidue)
       
   765 				{
       
   766 				__PRINT(_L("Discarding residue"));
       
   767 				// we have to read as much data as available that host PC sends;
       
   768 				// otherwise, bulk-out endpoint will need to keep sending NAK back.
       
   769 				ReadAndDiscardData(iDataResidue);
       
   770 				}
       
   771 			SendCSW(iCbwTag, iDataResidue, iCmdStatus);
       
   772 			break;
       
   773 			}
       
   774 		}
       
   775 
       
   776 	}
       
   777 
       
   778 void CBulkOnlyTransportUsbcLdd::DiscardData(TUint aLength)
       
   779 	{
       
   780 	iBuf.SetLength(KBOTMaxBufSize);
       
   781 	TUint c = 0;
       
   782 	TRequestStatus status;
       
   783 	while (c < aLength)
       
   784 		{
       
   785 		TInt len;
       
   786 		if (aLength - c >  KBOTMaxBufSize)
       
   787 			{
       
   788 			len = KBOTMaxBufSize;
       
   789 			}
       
   790 		else
       
   791 			{
       
   792 			len = aLength - c;
       
   793 			}
       
   794 
       
   795 		iLdd.Read(status, OutEndpoint, iBuf, len);
       
   796 		User::WaitForRequest(status);
       
   797 		c +=  KBOTMaxBufSize;
       
   798 		}
       
   799 	}
       
   800 
       
   801 void CBulkOnlyTransportUsbcLdd::WriteToClient(TUint aLength)
       
   802 	{
       
   803 	SetDataBufPtr();
       
   804 	iLdd.Read(iStatus, OutEndpoint, iDataBufPtr, aLength);
       
   805     User::WaitForRequest(iStatus);
       
   806     iProtocol->ReadComplete(KErrGeneral);
       
   807 	}
       
   808 
       
   809 #ifdef MSDC_MULTITHREADED
       
   810 void CBulkOnlyTransportUsbcLdd::GetBufferPointers(TPtr8& aDes1, TPtr8& aDes2)
       
   811 	{
       
   812 	aDes1.Set((TUint8*) iDataBuf1.Ptr(), KMaxBufSize, KMaxBufSize);
       
   813 	aDes2.Set((TUint8*) iDataBuf2.Ptr(), KMaxBufSize, KMaxBufSize);
       
   814 	}
       
   815 #endif
       
   816 
       
   817 void CBulkOnlyTransportUsbcLdd::Activate(TRequestStatus& aStatus, TUint& aDeviceState)
       
   818     {
       
   819 	iLdd.AlternateDeviceStatusNotify(aStatus, aDeviceState);
       
   820     }
       
   821 
       
   822 
       
   823 void CBulkOnlyTransportUsbcLdd::Cancel()
       
   824     {
       
   825 	iLdd.AlternateDeviceStatusNotifyCancel();
       
   826     }
       
   827 
       
   828 
       
   829 
       
   830