usbclasses/usbphoneasmodem/classimplementation/mscfileserver/src/bulkonlytransport.cpp
changeset 34 7858bc6ead78
parent 31 dfdd8240f7c8
child 35 9d8b04ca6939
equal deleted inserted replaced
31:dfdd8240f7c8 34:7858bc6ead78
     1 // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // 
       
    15 // 
       
    16 
       
    17 #include "bulkonlytransport.h"
       
    18 #include "mscfileserver.h"
       
    19 #include "usbmscfileshared.h"
       
    20 #include "debug.h"
       
    21 #define InEndpoint EEndpoint1
       
    22 #define OutEndpoint EEndpoint2
       
    23 //This value defined in USB Mass Storage Bulk Only Transrt spec and not supposed to be changed
       
    24 LOCAL_D const TInt KRequiredNumberOfEndpoints = 2; // in addition to endpoint 0. 
       
    25 
       
    26 
       
    27 //CBW offsets
       
    28 LOCAL_D const TInt KCbwSignatureOffset = 0;
       
    29 LOCAL_D const TInt KCbwTagOffset = 4;
       
    30 LOCAL_D const TInt KCbwDataTransferLengthOffset = 8;
       
    31 LOCAL_D const TInt KCbwFlagOffset = 12;
       
    32 LOCAL_D const TInt KCbwLunOffset = 13;
       
    33 LOCAL_D const TInt KCbwCbLengthOffset = 14;
       
    34 LOCAL_D const TInt KMaxCbwcbLength = 16;
       
    35 // CSW offsets
       
    36 LOCAL_D const TInt KCswSingnatureOffset = 0;
       
    37 LOCAL_D const TInt KCswTagOffset = 4;
       
    38 LOCAL_D const TInt KCswDataResidueOffset = 8;
       
    39 LOCAL_D const TInt KCswStatusOffset = 12;
       
    40 LOCAL_D const TInt KCswLength = 13;
       
    41 LOCAL_D const TInt KUsbNumInterfacesOffset = 4;
       
    42 
       
    43 /**
       
    44  This function unpacks into the TUsbRequestHdr class from a descriptor with 
       
    45  the alignment that would be introduced on the USB bus.
       
    46  
       
    47  @param aBuffer Input buffer
       
    48  @param aTarget Unpacked header.
       
    49  @return Error.
       
    50  */
       
    51 TInt TUsbRequestHdr::Decode(const TDesC8& aBuffer)
       
    52 
       
    53     {
       
    54     if (aBuffer.Length() < static_cast<TInt> (KRequestHdrSize))
       
    55         {
       
    56         TRACE_ERROR((_L("TUsbRequestHdr::Decode buffer invalid length %d"),aBuffer.Length()))
       
    57         return KErrGeneral;
       
    58         }
       
    59 
       
    60     // Decode as SPEC 1.3.3
       
    61     iRequestType = aBuffer[0];
       
    62     iRequest = static_cast<TEp0Request>(aBuffer[1]);
       
    63     iValue = static_cast<TUint16>(aBuffer[2] + (aBuffer[3] << 8));
       
    64     iIndex = static_cast<TUint16>(aBuffer[4] + (aBuffer[5] << 8));
       
    65     iLength = static_cast<TUint16>(aBuffer[6] + (aBuffer[7] << 8));
       
    66     TRACE_INFO((_L("type=%d request=%d value=%d index=%d length=%d"), iRequestType,iRequest,iValue,iIndex,iLength))
       
    67 
       
    68     return KErrNone;
       
    69     }
       
    70 
       
    71 /**
       
    72  This function determines whether data is required by the host in response 
       
    73  to a message header.
       
    74 
       
    75  @return TBool	Flag indicating whether a data response required.
       
    76  */
       
    77 TBool TUsbRequestHdr::IsDataResponseRequired() const
       
    78 
       
    79     {
       
    80     return (iRequestType & 0x80) ? ETrue : EFalse;
       
    81     }
       
    82 
       
    83 //
       
    84 /**
       
    85  Called by CBulkOnlyTransport to create an instance of CControlInterface
       
    86 
       
    87  @param aParent reference to the CBulkOnlyTransport
       
    88  */
       
    89 CControlInterface* CControlInterface::NewL(CBulkOnlyTransport& aParent)
       
    90     {
       
    91     CControlInterface* self = new (ELeave) CControlInterface(aParent);
       
    92     CleanupStack::PushL(self);
       
    93     self->ConstructL();
       
    94     CActiveScheduler::Add(self);
       
    95     CleanupStack::Pop();
       
    96     return self;
       
    97     }
       
    98 
       
    99 void CControlInterface::ConstructL()
       
   100     {
       
   101     }
       
   102 
       
   103 /**
       
   104  c'tor
       
   105 
       
   106  @param aParent reference to the CBulkOnlyTransport
       
   107  */
       
   108 CControlInterface::CControlInterface(CBulkOnlyTransport& aParent) :
       
   109 	CActive(EPriorityStandard),
       
   110 	iParent(aParent),
       
   111 	iCurrentState(ENone)
       
   112     {
       
   113     }
       
   114 
       
   115 /**
       
   116  d'tor
       
   117  */
       
   118 CControlInterface::~CControlInterface()
       
   119     {
       
   120     TRACE_FUNC
       
   121 	Cancel();
       
   122     }
       
   123 
       
   124 /**
       
   125  Called by  CBulkOnlyTransportStart to start control interface
       
   126  */
       
   127 TInt CControlInterface::Start()
       
   128     {
       
   129     TRACE_FUNC
       
   130     TInt res = ReadEp0Data();
       
   131     return (res);
       
   132     }
       
   133 
       
   134 /**
       
   135  Called by CBulkOnlyTransportStart to stop control interface
       
   136  */
       
   137 void CControlInterface::Stop()
       
   138     {
       
   139     TRACE_FUNC
       
   140     // Don't need to be any thing if we're not in active state
       
   141     if (!IsActive())
       
   142         {
       
   143         TRACE_INFO((_L("Not active")))
       
   144         return;
       
   145         }
       
   146 
       
   147     TRACE_INFO((_L("Stopping...")))
       
   148 
       
   149     // Stop by cancel
       
   150     Cancel();
       
   151     iCurrentState = ENone;
       
   152     }
       
   153 
       
   154 /**
       
   155  Cancel outstanding request (if any)
       
   156  */
       
   157 void CControlInterface::DoCancel()
       
   158     {
       
   159     TRACE_FUNC
       
   160     switch(iCurrentState)
       
   161         {
       
   162         case EReadEp0Data:
       
   163         iParent.Ldd().ReadCancel(EEndpoint0);
       
   164         break;
       
   165         case ESendMaxLun:
       
   166         iParent.Ldd().WriteCancel(EEndpoint0);
       
   167         break;
       
   168         default:
       
   169         TRACE_ERROR((_L("\nWrong state !")))
       
   170         __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceBadState));
       
   171         }
       
   172     }
       
   173 
       
   174 /**
       
   175  Implement CControlInterface state machine
       
   176  */
       
   177 void CControlInterface::RunL()
       
   178     {
       
   179     TRACE_FUNC
       
   180     if (iStatus != KErrNone)
       
   181         {
       
   182         TRACE_ERROR(( _L( "Error %d in RunL" ), iStatus.Int() ))
       
   183 
       
   184         //read EP0  again 
       
   185         ReadEp0Data();
       
   186         return;
       
   187         }
       
   188 
       
   189     switch (iCurrentState)
       
   190         {
       
   191         case ESendMaxLun:
       
   192             ReadEp0Data();
       
   193             break;
       
   194 
       
   195         case EReadEp0Data:
       
   196             DecodeEp0Data();
       
   197             break;
       
   198 
       
   199         default:
       
   200             TRACE_ERROR(( _L( "error: (Shouldn't end up here...)" ) ))
       
   201             __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceBadState));
       
   202             break;
       
   203         }
       
   204     return;
       
   205     }
       
   206 
       
   207 /**
       
   208  Post a read request to EEndpoint0 to read request header
       
   209  */
       
   210 TInt CControlInterface::ReadEp0Data()
       
   211     {
       
   212     TRACE_FUNC
       
   213     if ( IsActive() )
       
   214         {
       
   215         TRACE_ERROR(( _L( "Still active" ) ))
       
   216         return KErrServerBusy;
       
   217         }
       
   218 
       
   219     iParent.Ldd().Read(iStatus, EEndpoint0, iData, KRequestHdrSize);
       
   220 
       
   221     iCurrentState = EReadEp0Data;
       
   222 
       
   223     SetActive();
       
   224     return KErrNone;
       
   225     }
       
   226 
       
   227 /**
       
   228  Decode request header and do appropriate action - get max LUN info or post a reset request
       
   229  */
       
   230 void CControlInterface::DecodeEp0Data()
       
   231     {
       
   232     TRACE_FUNC
       
   233     if ( IsActive() )
       
   234         {
       
   235         TRACE_ERROR(( _L( "Still active" ) ))
       
   236         __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceStillActive));
       
   237         return;
       
   238         }
       
   239 
       
   240     TInt err = iRequestHeader.Decode(iData);
       
   241 
       
   242     if (err != KErrNone)
       
   243         {
       
   244         TRACE_WARNING((_L("Decode header error : err=%d"), err))
       
   245         return;
       
   246         }
       
   247 
       
   248     switch(iRequestHeader.iRequest)
       
   249         {
       
   250         // GET MAX LUN (0xFE)
       
   251         case TUsbRequestHdr::EReqGetMaxLun:
       
   252             {
       
   253             TRACE_INFO((_L("DecodeEp0Data : 'Get Max LUN' Request MaxLun = %d" ),
       
   254                             iParent.MaxLun() ))
       
   255 
       
   256             if ( iRequestHeader.iRequestType != 0xA1 //value from USB MS BOT spec
       
   257                     || iRequestHeader.iIndex> 15 || iRequestHeader.iValue != 0 || iRequestHeader.iLength != 1)
       
   258                 {
       
   259                 TRACE_ERROR((_L("GetMaxLun command packet check error")))
       
   260                 iParent.Ldd().EndpointZeroRequestError();
       
   261                 break;
       
   262                 }
       
   263 
       
   264             iData.FillZ(1); //Return only 1 byte to host 
       
   265             iData[0] = static_cast<TUint8>(iParent.MaxLun()); // Supported Units
       
   266             iParent.Ldd().Write(iStatus, EEndpoint0, iData, 1);
       
   267 
       
   268             iCurrentState = ESendMaxLun;
       
   269             SetActive();
       
   270 
       
   271             return;
       
   272             }
       
   273 
       
   274         // RESET (0xFF)
       
   275         case TUsbRequestHdr::EReqReset:
       
   276             {
       
   277             TRACE_INFO((_L("DecodeEp0Data : 'Mass Storage Reset' Request")))
       
   278 
       
   279             if ( iRequestHeader.iRequestType != 0x21 //value from USB MS BOT spec
       
   280                     || iRequestHeader.iIndex> 15 || iRequestHeader.iValue != 0 || iRequestHeader.iLength != 0)
       
   281                 {
       
   282                 TRACE_ERROR((_L("MSC Reset command packet check error")))
       
   283                 iParent.Ldd().EndpointZeroRequestError();
       
   284                 break;
       
   285                 }
       
   286 
       
   287             iParent.HwStop();
       
   288             iParent.Controller().Reset();
       
   289             iParent.HwStart(ETrue);
       
   290 
       
   291             err = iParent.Ldd().SendEp0StatusPacket();
       
   292             TRACE_INFO((_L("SendEp0StatusPacket: err=%d"), err))
       
   293 
       
   294             return;
       
   295             }
       
   296         // Unknown?
       
   297         default:
       
   298             {
       
   299             TRACE_ERROR((_L("DecodeEp0Data : Unknown Request")))
       
   300             }
       
   301         }
       
   302     ReadEp0Data(); //try to get another request 
       
   303     }
       
   304 
       
   305 //-------------------------------------
       
   306 /**
       
   307  Create CBulkOnlyTransport object
       
   308  @param aNumDrives - The number of drives available for MS
       
   309  @param aController - reference to the parent
       
   310  @return pointer to newly created object
       
   311  */
       
   312 CBulkOnlyTransport* CBulkOnlyTransport::NewL(TInt aNumDrives,CMscFileController& aController)
       
   313     {
       
   314 	CBulkOnlyTransport* self = new(ELeave) CBulkOnlyTransport(aNumDrives, aController);
       
   315     CleanupStack::PushL(self);
       
   316     self->ConstructL();
       
   317     CleanupStack::Pop(self);
       
   318     return self;
       
   319     }
       
   320 
       
   321 /**
       
   322  c'tor 
       
   323  @param aNumDrives - The number of drives available for MS
       
   324  @param aController - reference to the parent
       
   325  */
       
   326 CBulkOnlyTransport::CBulkOnlyTransport(TInt aNumDrives,CMscFileController& aController):
       
   327 	CActive(EPriorityStandard),
       
   328 	iMaxLun(aNumDrives-1),
       
   329 	iController(aController),
       
   330 	iReadBuf(NULL,0),
       
   331 	iWriteBuf(NULL,0),
       
   332 	iStallAllowed(ETrue)
       
   333     {
       
   334     }
       
   335 
       
   336 /**
       
   337  Constructs the CBulkOnlyTranspor object
       
   338  */
       
   339 void CBulkOnlyTransport::ConstructL()
       
   340     {
       
   341     TRACE_FUNC
       
   342     iControlInterface = CControlInterface::NewL(*this);
       
   343     iDeviceStateNotifier = CActiveDeviceStateNotifier::NewL(*this);
       
   344     CActiveScheduler::Add(this);
       
   345     }
       
   346 
       
   347 /**
       
   348  Destructor
       
   349  */
       
   350 CBulkOnlyTransport::~CBulkOnlyTransport()
       
   351     {
       
   352     TRACE_FUNC
       
   353     if (iInterfaceConfigured)
       
   354         {
       
   355         Stop();
       
   356         }
       
   357     delete iControlInterface;
       
   358     delete iDeviceStateNotifier;
       
   359     }
       
   360 
       
   361 /**
       
   362  Set or unset configuration descriptor for USB MassStorage Bulk Only transport
       
   363 
       
   364  @param aUnset indicate whether set or unset descriptor
       
   365  @return KErrNone if operation was completed successfully, errorcode otherwise
       
   366  */
       
   367 TInt CBulkOnlyTransport::SetupConfigurationDescriptor(TBool aUnset)
       
   368     {
       
   369     TRACE_FUNC
       
   370     TInt ret(KErrNone);
       
   371     TInt configDescriptorSize(0);
       
   372 
       
   373     iLdd.GetConfigurationDescriptorSize(configDescriptorSize);
       
   374     if (static_cast<TUint> (configDescriptorSize) != KUsbDescSize_Config)
       
   375         {
       
   376         return KErrCorrupt;
       
   377         }
       
   378 
       
   379     TBuf8<KUsbDescSize_Config> configDescriptor;
       
   380     ret = iLdd.GetConfigurationDescriptor(configDescriptor);
       
   381     if (ret != KErrNone)
       
   382         {
       
   383         return ret;
       
   384         }
       
   385 
       
   386     // I beleive that other fields setted up during LDD initialisation
       
   387     if (aUnset)
       
   388         {
       
   389         --configDescriptor[KUsbNumInterfacesOffset];
       
   390         }
       
   391     else
       
   392         {
       
   393         ++configDescriptor[KUsbNumInterfacesOffset];
       
   394         }
       
   395     ret = iLdd.SetConfigurationDescriptor(configDescriptor);
       
   396 
       
   397     return ret;
       
   398     }
       
   399 
       
   400 /**
       
   401  Set up interface descriptor
       
   402 
       
   403  @return KErrNone if operation was completed successfully, errorcode otherwise
       
   404  */
       
   405 TInt CBulkOnlyTransport::SetupInterfaceDescriptors()
       
   406     {
       
   407     TRACE_FUNC
       
   408     // Device caps
       
   409     TUsbDeviceCaps d_caps;
       
   410     TInt ret = iLdd.DeviceCaps(d_caps);
       
   411     if (ret != KErrNone)
       
   412         {
       
   413         return ret;
       
   414         }
       
   415     TInt totalEndpoints = d_caps().iTotalEndpoints;
       
   416     if (totalEndpoints < KRequiredNumberOfEndpoints)
       
   417         {
       
   418         return KErrHardwareNotAvailable;
       
   419         }
       
   420 
       
   421     // Endpoint caps
       
   422     TUsbcEndpointData data[KUsbcMaxEndpoints];
       
   423 	TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data));
       
   424     ret = iLdd.EndpointCaps(dataptr);
       
   425     if (ret != KErrNone)
       
   426         {
       
   427         return ret;
       
   428         }
       
   429 
       
   430     // Set the active interface
       
   431     TUsbcInterfaceInfoBuf ifc;
       
   432     TInt ep_found = 0;
       
   433     TBool foundBulkIN = EFalse;
       
   434     TBool foundBulkOUT = EFalse;
       
   435 
       
   436     for (TInt i = 0; i < totalEndpoints; i++)
       
   437         {
       
   438         const TUsbcEndpointCaps* caps = &data[i].iCaps;
       
   439         const TInt maxPacketSize = caps->MaxPacketSize();
       
   440 		if (!foundBulkIN &&
       
   441 			(caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirIn)) == (KUsbEpTypeBulk | KUsbEpDirIn))
       
   442             {
       
   443             // InEndpoint is going to be our TX (IN, write) endpoint
       
   444             ifc().iEndpointData[0].iType = KUsbEpTypeBulk;
       
   445             ifc().iEndpointData[0].iDir = KUsbEpDirIn;
       
   446             ifc().iEndpointData[0].iSize = maxPacketSize;
       
   447             ifc().iEndpointData[0].iInterval_Hs = 0;
       
   448 			ifc().iEndpointData[0].iFeatureWord1 = KUsbcEndpointInfoFeatureWord1_DMA;
       
   449             foundBulkIN = ETrue;
       
   450             if (++ep_found == KRequiredNumberOfEndpoints)
       
   451                 {
       
   452                 break;
       
   453                 }
       
   454             continue;
       
   455             }
       
   456 		if (!foundBulkOUT &&
       
   457 			(caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirOut)) == (KUsbEpTypeBulk | KUsbEpDirOut))
       
   458             {
       
   459             // OutEndpoint is going to be our RX (OUT, read) endpoint
       
   460             ifc().iEndpointData[1].iType = KUsbEpTypeBulk;
       
   461             ifc().iEndpointData[1].iDir = KUsbEpDirOut;
       
   462             ifc().iEndpointData[1].iSize = maxPacketSize;
       
   463             ifc().iEndpointData[1].iInterval_Hs = 0;
       
   464 			ifc().iEndpointData[1].iFeatureWord1 = KUsbcEndpointInfoFeatureWord1_DMA;
       
   465             foundBulkOUT = ETrue;
       
   466             if (++ep_found == KRequiredNumberOfEndpoints)
       
   467                 {
       
   468                 break;
       
   469                 }
       
   470             continue;
       
   471             }
       
   472         }
       
   473     if (ep_found != KRequiredNumberOfEndpoints)
       
   474         {
       
   475         return KErrHardwareNotAvailable;
       
   476         }
       
   477     _LIT16(string, "USB Mass Storage Interface");
       
   478     ifc().iString = const_cast<TDesC16*> (&string);
       
   479     ifc().iTotalEndpointsUsed = KRequiredNumberOfEndpoints;
       
   480     ifc().iClass.iClassNum = 0x08; // Mass Storage
       
   481     ifc().iClass.iSubClassNum = 0x06; // SCSI Transparent Command Set
       
   482     ifc().iClass.iProtocolNum = 0x50; // Bulk Only Transport
       
   483 
       
   484 	TUint bandwidth_priority = (EUsbcBandwidthOUTDefault | EUsbcBandwidthINDefault);
       
   485     if (d_caps().iHighSpeed)
       
   486         {
       
   487         // If this device supports USB High-speed, then we request 64KB buffers
       
   488         // (otherwise the default 4KB ones will do).
       
   489         bandwidth_priority = (EUsbcBandwidthOUTPlus2 | EUsbcBandwidthINPlus2);
       
   490         // Also, tell the Protocol about it, because it might want to do some
       
   491         // optimizing too.
       
   492         iProtocol->ReportHighSpeedDevice();
       
   493         }
       
   494     ret = iLdd.SetInterface(0, ifc, bandwidth_priority);
       
   495     return ret;
       
   496     }
       
   497 
       
   498 /**
       
   499  Called by the protocol after processing the packet to indicate that more data is required.  
       
   500 
       
   501  @param aData reference to the data buffer. 
       
   502  */
       
   503 void CBulkOnlyTransport::SetupReadData(TPtr8& aData)
       
   504     {
       
   505     TRACE_FUNC
       
   506     TRACE_INFO((_L("Length = %d  (bytes)"), aData.Length()))
       
   507     iReadBuf.Set(aData);
       
   508     iReadSetUp = ETrue;
       
   509     }
       
   510 
       
   511 /**
       
   512  Called by the protocol after processing the packet to indicate that data should be written to the host.  
       
   513 
       
   514  @param aData reference to the data buffer. 
       
   515  */
       
   516 void CBulkOnlyTransport::SetupWriteData(TPtrC8& aData)
       
   517     {
       
   518     TRACE_FUNC
       
   519     TRACE_INFO((_L("Length = %d  (bytes)"), aData.Length()))
       
   520     iWriteBuf.Set(aData);
       
   521     iWriteSetUp = ETrue;
       
   522     }
       
   523 
       
   524 TInt CBulkOnlyTransport::Start()
       
   525     {
       
   526     TRACE_FUNC_ENTRY
       
   527 
       
   528     TInt err = KErrNone;
       
   529 
       
   530     if (!iProtocol)
       
   531         {
       
   532         return KErrBadHandle; //protocol should be set up before start
       
   533         }
       
   534 
       
   535     if (IsActive())
       
   536         {
       
   537         TRACE_ERROR((_L("Active before start!")))
       
   538         return KErrInUse;
       
   539         }
       
   540 
       
   541     if ((err = iLdd.Open(0)) != KErrNone )
       
   542         {
       
   543         TRACE_ERROR((_L("Error during open ldd!")))
       
   544         return err;
       
   545         }
       
   546 
       
   547     if ((err = SetupConfigurationDescriptor()) != KErrNone ||
       
   548             (err = SetupInterfaceDescriptors()) != KErrNone )
       
   549         {
       
   550         iLdd.Close();
       
   551         TRACE_ERROR((_L("Error during descriptors setup!")))
       
   552         return err;
       
   553         }
       
   554 
       
   555     iDeviceStateNotifier->Activate(); // activate notifier wich will wait until USB became configured
       
   556     TUsbcDeviceState deviceStatus = EUsbcDeviceStateDefault;
       
   557     err = iLdd.DeviceStatus(deviceStatus);
       
   558     TRACE_INFO((_L("Device status = %d"), deviceStatus))
       
   559     if (err == KErrNone && deviceStatus == EUsbcDeviceStateConfigured)
       
   560         {
       
   561         TRACE_INFO(_L("Starting bulk only transport\n"));
       
   562         err = HwStart();
       
   563         }
       
   564     iInterfaceConfigured = ETrue;
       
   565     TRACE_FUNC_EXIT
       
   566     return err;
       
   567     }
       
   568 
       
   569 TInt CBulkOnlyTransport::HwStart(TBool aDiscard)
       
   570     {
       
   571     TRACE_FUNC_ENTRY
       
   572 
       
   573     TInt res = iControlInterface->Start();
       
   574 
       
   575     iCurrentState = ENone;
       
   576     iWriteSetUp = EFalse;
       
   577     iReadSetUp = EFalse;
       
   578     iStarted = ETrue;
       
   579 
       
   580     if (aDiscard)
       
   581         {
       
   582         TInt bytes;
       
   583         const TInt err = iLdd.QueryReceiveBuffer(OutEndpoint, bytes);
       
   584         if (err != KErrNone || bytes <= 0)
       
   585             {
       
   586             TRACE_ERROR((_L("Error: err=%d bytes=%d"), bytes))
       
   587             }
       
   588         else
       
   589             {
       
   590             TRACE_ERROR((_L("RxBuffer has %d bytes"), bytes))
       
   591             ReadAndDiscardData(bytes);
       
   592             }
       
   593         }
       
   594 
       
   595     ReadCBW();
       
   596     TRACE_FUNC_EXIT
       
   597     return res;
       
   598     }
       
   599 
       
   600 TInt CBulkOnlyTransport::HwStop()
       
   601     {
       
   602     TRACE_FUNC
       
   603 
       
   604     if (iStarted)
       
   605         {
       
   606         Cancel();
       
   607         iControlInterface->Cancel();
       
   608         iProtocol->Cancel();
       
   609         iStarted = EFalse;
       
   610         }
       
   611     return KErrNone;
       
   612     }
       
   613 
       
   614 TInt CBulkOnlyTransport::HwSuspend()
       
   615     {
       
   616     TRACE_FUNC
       
   617     return KErrNone;
       
   618     }
       
   619 
       
   620 TInt CBulkOnlyTransport::HwResume()
       
   621     {
       
   622     TRACE_FUNC
       
   623     return KErrNone;
       
   624     }
       
   625 
       
   626 /**
       
   627  Stops the Bulk Only Transport
       
   628  */
       
   629 TInt CBulkOnlyTransport::Stop()
       
   630     {
       
   631     TRACE_FUNC
       
   632     iControlInterface->Cancel();
       
   633     iDeviceStateNotifier->Cancel();
       
   634     Cancel();
       
   635     if (iInterfaceConfigured)
       
   636         {
       
   637         iLdd.ReleaseInterface(0);
       
   638         SetupConfigurationDescriptor(ETrue);
       
   639         iLdd.Close();
       
   640         }
       
   641     iCurrentState = ENone;
       
   642     iInterfaceConfigured = EFalse;
       
   643 
       
   644     return KErrNone;
       
   645     }
       
   646 
       
   647 /**
       
   648  Read aLength bytes of data from the host into the read buffer.
       
   649  @param aLength The number of bytes to read from the host.
       
   650  */
       
   651 void CBulkOnlyTransport::ReadCBW()
       
   652     {
       
   653     TRACE_FUNC
       
   654     if (IsActive())
       
   655         {
       
   656         TRACE_ERROR(( _L( "Still active" ) ))
       
   657         __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
       
   658         return;
       
   659         }
       
   660 
       
   661     iCbwBuf.SetMax();
       
   662     iLdd.ReadUntilShort(iStatus, OutEndpoint, iCbwBuf, iCbwBuf.Length());
       
   663 
       
   664     iCurrentState = EWaitForCBW;
       
   665     SetActive();
       
   666     }
       
   667 
       
   668 void CBulkOnlyTransport::DoCancel()
       
   669     {
       
   670     TRACE_FUNC
       
   671     iLdd.WriteCancel(InEndpoint);
       
   672     iLdd.ReadCancel(OutEndpoint);
       
   673     }
       
   674 
       
   675 void CBulkOnlyTransport::Activate(TInt aReason)
       
   676     {
       
   677     SetActive();
       
   678     TRequestStatus* r = &iStatus;
       
   679     User::RequestComplete(r, aReason);
       
   680     }
       
   681 
       
   682 void CBulkOnlyTransport::RunL()
       
   683     {
       
   684     TRACE_FUNC
       
   685     if (iStatus != KErrNone)
       
   686         {
       
   687         TRACE_ERROR((_L("Error %d in RunL, halt endpoints \n"), iStatus.Int()))
       
   688         SetPermError(); //halt endpoints for reset recovery
       
   689         return;
       
   690         }
       
   691 
       
   692     switch (iCurrentState)
       
   693         {
       
   694         case EWaitForCBW:
       
   695             TRACE_INFO((_L("EWaitForCBW")))
       
   696             DecodeCBW();
       
   697             break;
       
   698 
       
   699         case EWritingData:
       
   700             TRACE_INFO((_L("EWritingData")))
       
   701             iWriteSetUp = EFalse; //the buffer was used
       
   702 
       
   703             if (iDataResidue && iStallAllowed)
       
   704                 {
       
   705                 StallEndpointAndWaitForClear(InEndpoint);
       
   706                 }
       
   707 
       
   708             SendCSW(iCbwTag, iDataResidue, iCmdStatus);
       
   709             break;
       
   710 
       
   711         case EReadingData:
       
   712             {
       
   713             TRACE_INFO((_L("EReadingData")))
       
   714 
       
   715             TInt ret = KErrNone;
       
   716             FOREVER
       
   717                 {
       
   718                 if (iReadSetUp)
       
   719                     {
       
   720                     ret = iProtocol->ReadComplete(KErrNone);
       
   721                     }
       
   722 
       
   723                 TUint deviceDataLength = static_cast<TUint>(iReadBuf.Length());
       
   724                 if(ret == KErrCompletion)
       
   725                     {
       
   726                     // The protocol has indicated with KErrCompletion that sufficient
       
   727                     // data is available in the buffer to process the transfer immediately.
       
   728                     iDataResidue -= deviceDataLength;
       
   729                     iLdd.Read(iStatus, OutEndpoint, iReadBuf, deviceDataLength);
       
   730                     User::WaitForRequest(iStatus);
       
   731                     if (iStatus != KErrNone)
       
   732                         {
       
   733                         // An error occurred - halt endpoints for reset recovery
       
   734                         TRACE_ERROR((_L("Error %d in EReadingData, halt endpoints"),
       
   735                                         iStatus.Int()))
       
   736                         SetPermError();
       
   737                         return;
       
   738                         }
       
   739                     }
       
   740                 else if(ret == KErrNotReady)
       
   741                     {
       
   742                     // The protocol has indicated with KErrNotReady that insufficient
       
   743                     // data is available in the buffer, so should wait for it to arrive
       
   744                     ReadData(deviceDataLength);
       
   745                     break;
       
   746                     }
       
   747                 else
       
   748                     {
       
   749                     // The protocol has indicated that transfer is 
       
   750                     // complete, so send the CSW response to the host.
       
   751                     iReadSetUp = EFalse;
       
   752 
       
   753                     if (ret != KErrNone)
       
   754                         {
       
   755                         iCmdStatus = ECommandFailed;
       
   756                         }
       
   757 
       
   758                     if (iDataResidue)
       
   759                         {
       
   760                         TRACE_INFO((_L("Discarding residue")))
       
   761                         // we have to read as much data as available that host PC sends;
       
   762                         // otherwise, bulk-out endpoint will need to keep sending NAK back.
       
   763                         ReadAndDiscardData(iDataResidue);
       
   764                         }
       
   765                     SendCSW(iCbwTag, iDataResidue, iCmdStatus);
       
   766                     break;
       
   767                     }
       
   768                 }
       
   769             }
       
   770         break;
       
   771 
       
   772         case ESendingCSW:
       
   773         TRACE_INFO((_L("ESendingCSW")))
       
   774         ReadCBW();
       
   775         break;
       
   776 
       
   777         case EPermErr:
       
   778         TRACE_INFO((_L("EPermErr")))
       
   779         StallEndpointAndWaitForClear(InEndpoint);
       
   780         break;
       
   781 
       
   782         default:
       
   783         SetPermError(); // unexpected state
       
   784         }
       
   785     }
       
   786 
       
   787 /**
       
   788  Prepare incase we need to read data from host
       
   789  Called in DecodeCBW(...)
       
   790  @param aHostDataLength The number of bytes to read from the host.
       
   791  */
       
   792 void CBulkOnlyTransport::PrepareReadFromHost(TUint aHostDataLength)
       
   793     {
       
   794     if (!iReadSetUp)
       
   795         {
       
   796 			iDataResidue =aHostDataLength;
       
   797 			TRACE_INFO((_L("Read buffer was not setup\n")))
       
   798             //Use next block instead of StallEndpointAndWaitForClear(OutEndpoint); 
       
   799             {
       
   800             iBuf.SetLength(KBOTMaxBufSize);
       
   801             TUint c =0;
       
   802             TRequestStatus status;
       
   803             while (c<aHostDataLength)
       
   804                 {
       
   805                 TInt len;
       
   806                 if (aHostDataLength - c> KBOTMaxBufSize)
       
   807                     {
       
   808                     len = KBOTMaxBufSize;
       
   809                     }
       
   810                 else
       
   811                     {
       
   812                     len = aHostDataLength - c;
       
   813                     }
       
   814 
       
   815                 iLdd.Read(status, OutEndpoint, iBuf, len);
       
   816                 User::WaitForRequest(status);
       
   817                 c += KBOTMaxBufSize;
       
   818                 }
       
   819             }
       
   820 
       
   821         if (iWriteSetUp) //case (10)
       
   822             {
       
   823             TRACE_INFO((_L("case 10\n")))
       
   824             SendCSW(iCbwTag, aHostDataLength, EPhaseError);
       
   825             }
       
   826         else // case (9)
       
   827 
       
   828             {
       
   829             TRACE_INFO((_L("Case 9\n")))
       
   830             SendCSW(iCbwTag, aHostDataLength, iCmdStatus);
       
   831             }
       
   832 
       
   833         return;
       
   834         }
       
   835     else
       
   836         {
       
   837         TUint deviceDataLength = static_cast<TUint>(iReadBuf.Length());
       
   838         iDataResidue =aHostDataLength - deviceDataLength;
       
   839         TRACE_INFO((_L("deviceDataLength=%d, DataResidue (read from host) =%d\n"),
       
   840                         deviceDataLength,iDataResidue))
       
   841 
       
   842         if (deviceDataLength <= aHostDataLength) // case (11) and (12)
       
   843 
       
   844             {
       
   845             TRACE_INFO((_L("Case 11 or 12\n")))
       
   846             ReadData(deviceDataLength);
       
   847             return;
       
   848             }
       
   849 
       
   850         if (deviceDataLength> aHostDataLength) // case  (13)
       
   851 
       
   852             {
       
   853             TRACE_INFO((_L("Case 13\n")))
       
   854             /**
       
   855              * Comment following line in order to pass compliant test.
       
   856              * As spec said in case 13:"The device may receive data up to a
       
   857              * total of dCBWDataTransferLength."
       
   858              * Here we choose to ignore incoming data.
       
   859              */
       
   860             //StallEndpointAndWaitForClear(OutEndpoint); //Stall Out endpoint
       
   861             if (iReadSetUp)
       
   862                 {
       
   863                 iLdd.Read(iStatus, OutEndpoint, iReadBuf, aHostDataLength);
       
   864                 User::WaitForRequest(iStatus);
       
   865                 iProtocol->ReadComplete(KErrGeneral);
       
   866                 iReadSetUp = EFalse;
       
   867                 }
       
   868             SendCSW(iCbwTag, aHostDataLength, EPhaseError);
       
   869             return;
       
   870             }
       
   871         }
       
   872     }
       
   873 
       
   874 /**
       
   875  Prepare incase we need to read data from host
       
   876  Called in DecodeCBW(...)
       
   877  @param aHostDataLength The number of bytes to write to the host.
       
   878  */
       
   879 void CBulkOnlyTransport::PrepareWriteToHost(TUint aHostDataLength)
       
   880     {
       
   881     if (!iWriteSetUp) //write buffer was not set up 
       
   882         {
       
   883         TRACE_INFO((_L("Write buffer was not setup")))
       
   884         iDataResidue =aHostDataLength;
       
   885         TRACE_INFO((_L("DataResidue (write to host)=%d"),iDataResidue))
       
   886 
       
   887         //------------------------------------
       
   888         if (aHostDataLength <= KBOTMaxBufSize)
       
   889             {
       
   890             TRACE_INFO((_L("Case 4 or 8\n")))
       
   891             iBuf.FillZ(aHostDataLength);
       
   892             iLdd.Write(iStatus, InEndpoint, iBuf, aHostDataLength);
       
   893             SetActive();
       
   894             iCurrentState = EWritingData;
       
   895             iStallAllowed = EFalse;
       
   896             if (iReadSetUp) //read buffer WAS set up - case (8)
       
   897 
       
   898                 {
       
   899                 TRACE_INFO((_L("It is Case 8")))
       
   900                 iCmdStatus = EPhaseError;
       
   901                 }
       
   902             return;
       
   903             }
       
   904         else
       
   905         //------------------------------------
       
   906         //					Use next block instead of StallEndpointAndWaitForClear(InEndpoint);
       
   907 
       
   908             {
       
   909             iBuf.FillZ(KBOTMaxBufSize);
       
   910             TUint c =0;
       
   911             TRequestStatus status;
       
   912             while (c<aHostDataLength)
       
   913                 {
       
   914                 TInt len;
       
   915                 if (aHostDataLength - c> KBOTMaxBufSize)
       
   916                     {
       
   917                     len = KBOTMaxBufSize;
       
   918                     }
       
   919                 else
       
   920                     {
       
   921                     len = aHostDataLength - c;
       
   922                     }
       
   923 
       
   924                 iLdd.Write(status, InEndpoint, iBuf, len);
       
   925                 User::WaitForRequest(status);
       
   926                 c += KBOTMaxBufSize;
       
   927                 }
       
   928             }
       
   929 
       
   930         if (iReadSetUp) //read buffer WAS set up - case (8)
       
   931             {
       
   932             TRACE_INFO(_L("Case 8"));
       
   933             SendCSW(iCbwTag, aHostDataLength, EPhaseError);
       
   934             //don't care to reset any flag - should get reset recovery
       
   935             }
       
   936         else // case (4)
       
   937             {
       
   938             TRACE_INFO((_L("Case 4")))
       
   939             SendCSW(iCbwTag, aHostDataLength, iCmdStatus);
       
   940             }
       
   941         return;
       
   942         }
       
   943     else
       
   944         {
       
   945         //================== 
       
   946         TUint deviceDataLength = static_cast<TUint>(iWriteBuf.Length());
       
   947         iDataResidue =aHostDataLength - deviceDataLength;
       
   948         TRACE_INFO((_L("Device data length = %d, DataResidue (write to host)=%d"),
       
   949                         deviceDataLength, iDataResidue))
       
   950 
       
   951         if (deviceDataLength < aHostDataLength &&
       
   952                 aHostDataLength < KBOTMaxBufSize )
       
   953             {
       
   954             TRACE_INFO((_L("Case 5 (padding)\n")))
       
   955             iBuf.Zero();
       
   956             iBuf.Append(iWriteBuf);
       
   957             iBuf.SetLength(aHostDataLength);
       
   958             iStallAllowed = EFalse;
       
   959             TRACE_INFO((_L("iBuf.Length=%d\n"),iBuf.Length()))
       
   960             iLdd.Write(iStatus, InEndpoint, iBuf, aHostDataLength);
       
   961             SetActive();
       
   962             iCurrentState = EWritingData;
       
   963             return;
       
   964             }
       
   965 
       
   966         //===================
       
   967 
       
   968         if (deviceDataLength == aHostDataLength) //case (6)[==]
       
   969 
       
   970             {
       
   971             TRACE_INFO((_L("Case 6\n")))
       
   972             WriteData(deviceDataLength);
       
   973             return;
       
   974             }
       
   975         else if (deviceDataLength < aHostDataLength) //case (5)[<]
       
   976 
       
   977             {
       
   978             TRACE_INFO((_L("Case 5\n")))
       
   979             WriteData(deviceDataLength, ETrue); // Send ZLP
       
   980             return;
       
   981             }
       
   982         else // deviceDataLength > aHostDataLength - case (7)
       
   983 
       
   984             {
       
   985             TRACE_INFO((_L("Case 7\n")))
       
   986             iCmdStatus = EPhaseError;
       
   987             iDataResidue = 0;
       
   988             WriteData(aHostDataLength);
       
   989             return;
       
   990             }
       
   991         }
       
   992     }
       
   993 
       
   994 /**
       
   995  Decode the CBW received from the host via OutEndpoint
       
   996 
       
   997  - If the header is valid, the data content is passed to the parser.
       
   998  - Depending on the command, more data may be transmitted/received.
       
   999  - ...or the CSW is sent (if not a data command).
       
  1000 
       
  1001  */
       
  1002 void CBulkOnlyTransport::DecodeCBW()
       
  1003     {
       
  1004     TRACE_FUNC
       
  1005     if (!CheckCBW()) //check if CBW valid and meaningful
       
  1006 
       
  1007         {
       
  1008         // CBW not valid or meaningful
       
  1009         // Specification says: "If the CBW is not valid, the device shall STALL
       
  1010         // the Bulk-In pipe. Also, the device shall either STALL the Bulk-Out pipe,
       
  1011         // or the device shall accept and discard any Bulk-Out data. The device
       
  1012         // shall maintain this state until a Reset Recovery."
       
  1013         // Here we keep bulk-in ep stalled and ignore bulk-out ep.
       
  1014         SetPermError();
       
  1015         return;
       
  1016         }
       
  1017 
       
  1018     TPtrC8 aData;
       
  1019     aData.Set(&iCbwBuf[KCbwCbLengthOffset], KMaxCbwcbLength + 1); //prepare data for protocol starting form Length 
       
  1020     TUint8 lun = static_cast<TUint8> (iCbwBuf[13] & 0x0f);
       
  1021 
       
  1022 	iCbwTag  =	static_cast<TUint32>(iCbwBuf[KCbwTagOffset])		| 
       
  1023 				static_cast<TUint32>(iCbwBuf[KCbwTagOffset+1])	<<8 | 
       
  1024 				static_cast<TUint32>(iCbwBuf[KCbwTagOffset+2])	<<16| 
       
  1025 				static_cast<TUint32>(iCbwBuf[KCbwTagOffset+3])	<<24;
       
  1026 
       
  1027     TInt i = KCbwDataTransferLengthOffset;
       
  1028 	TUint hostDataLength = 	static_cast<TUint32>(iCbwBuf[i  ])		| 
       
  1029 							static_cast<TUint32>(iCbwBuf[i+1]) <<8 	| 
       
  1030 							static_cast<TUint32>(iCbwBuf[i+2]) <<16	| 
       
  1031 							static_cast<TUint32>(iCbwBuf[i+3]) <<24;
       
  1032 
       
  1033     TBool dataToHost = iCbwBuf[KCbwFlagOffset] & 0x80;
       
  1034 
       
  1035     TRACE_INFO((_L("lun =%d, hostDataLength=%d, CBWtag = 0x%X\n, dataToHost=%d"),
       
  1036                     lun, hostDataLength, iCbwTag, dataToHost))
       
  1037     //
       
  1038     TBool ret = iProtocol->DecodePacket(aData, lun);
       
  1039     //
       
  1040 
       
  1041     iStallAllowed = ETrue;
       
  1042 
       
  1043     if (!ret)
       
  1044         {
       
  1045         TRACE_INFO((_L("Command Failed")))
       
  1046         iCmdStatus = ECommandFailed;
       
  1047         }
       
  1048     else
       
  1049         {
       
  1050         TRACE_INFO((_L("Command Passed")))
       
  1051         iCmdStatus = ECommandPassed;
       
  1052         }
       
  1053 
       
  1054     if (hostDataLength == 0)
       
  1055         {
       
  1056         TRACE_INFO((_L("No data transfer expected\n")))
       
  1057         iDataResidue = 0;
       
  1058         if (iWriteSetUp || iReadSetUp) // case (2) and (3)
       
  1059 
       
  1060             {
       
  1061             TRACE_INFO((_L("Case 2 or 3\n")))
       
  1062             SendCSW(iCbwTag, 0, EPhaseError);
       
  1063             }
       
  1064         else
       
  1065             {
       
  1066             TRACE_INFO((_L("Case 1\n")))
       
  1067             SendCSW(iCbwTag, 0, iCmdStatus); //case (1)
       
  1068             }
       
  1069 
       
  1070         return;
       
  1071         }
       
  1072     else
       
  1073         {
       
  1074         // Data Direction, To or From Host
       
  1075         if (dataToHost)
       
  1076             {
       
  1077             PrepareWriteToHost(hostDataLength);
       
  1078             }
       
  1079         else
       
  1080             {
       
  1081             PrepareReadFromHost(hostDataLength);
       
  1082             }
       
  1083         }
       
  1084     }
       
  1085 
       
  1086 /**
       
  1087  Check if CBW Valid and Meaningful.  
       
  1088 
       
  1089  @return ETrue if CBW is Valid and Meaningful, EFalse otherwise
       
  1090  */
       
  1091 TBool CBulkOnlyTransport::CheckCBW()
       
  1092     {
       
  1093     TRACE_FUNC
       
  1094 
       
  1095     // Check valid
       
  1096 
       
  1097     // Check length
       
  1098     if (iCbwBuf.Length() != KCbwLength)
       
  1099         {
       
  1100         TRACE_INFO((_L("Bad length: %d"), iCbwBuf.Length()))
       
  1101         return EFalse;
       
  1102         }
       
  1103 
       
  1104     // Check signature
       
  1105     TInt i = KCbwSignatureOffset;
       
  1106 	if (iCbwBuf[i  ] != 0x55 ||         // CBW Singature from USB Bulk-Only Transport spec
       
  1107 		iCbwBuf[i+1] != 0x53 ||
       
  1108 		iCbwBuf[i+2] != 0x42 ||
       
  1109 		iCbwBuf[i+3] != 0x43)
       
  1110         {
       
  1111         TRACE_INFO((_L("Bad signature")))
       
  1112         TRACE_INFO((_L(" 0x%x, 0x%x, 0x%x, 0x%x"),
       
  1113                         iCbwBuf[i], iCbwBuf[i+1], iCbwBuf[i+2],iCbwBuf[i+3]))
       
  1114         return EFalse;
       
  1115         }
       
  1116 
       
  1117     // Check meaningful
       
  1118 
       
  1119     // Check reserved bits ( must be zero )
       
  1120     if ((iCbwBuf[KCbwLunOffset] & 0xF0) || (iCbwBuf[KCbwCbLengthOffset] & 0xE0))
       
  1121         {
       
  1122         TRACE_INFO((_L("Reserved bits not zero\n")))
       
  1123         return EFalse;
       
  1124         }
       
  1125 
       
  1126     // check command block length
       
  1127     TInt cbwcbLength = iCbwBuf[KCbwCbLengthOffset] & 0x1F;
       
  1128     if (cbwcbLength>KMaxCbwcbLength)
       
  1129         {
       
  1130         TRACE_INFO((_L("Incorrect block length\n")))
       
  1131         return EFalse;
       
  1132         }
       
  1133 
       
  1134     //check LUN
       
  1135     TInt8 lun = static_cast<TUint8>(iCbwBuf[KCbwLunOffset] & 0x0f);
       
  1136     if (iMaxLun < lun)
       
  1137         {
       
  1138         TRACE_INFO((_L("bad lun: %d"), lun))
       
  1139         return EFalse;
       
  1140         }
       
  1141 
       
  1142     return ETrue;
       
  1143     }
       
  1144 
       
  1145 /**
       
  1146  Initiate stalling of bulk IN endpoint.
       
  1147  Used when protocol wants to force host to initiate a reset recovery.
       
  1148  */
       
  1149 void CBulkOnlyTransport::SetPermError()
       
  1150     {
       
  1151     TRACE_FUNC
       
  1152     iCurrentState = EPermErr;
       
  1153     Activate(KErrNone);
       
  1154     }
       
  1155 
       
  1156 /**
       
  1157  Send data provided by protocol to the host
       
  1158 
       
  1159  @param aLength amount of data (in bytes) to be send to host
       
  1160  */
       
  1161 void CBulkOnlyTransport::WriteData(TUint aLength, TBool aZlpRequired)
       
  1162     {
       
  1163     TRACE_FUNC
       
  1164 
       
  1165     if (IsActive())
       
  1166         {
       
  1167         TRACE_INFO((_L("Still active")))
       
  1168         __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
       
  1169         return;
       
  1170         }
       
  1171     iLdd.Write(iStatus, InEndpoint, iWriteBuf, aLength, aZlpRequired);
       
  1172     iCurrentState = EWritingData;
       
  1173     SetActive();
       
  1174     }
       
  1175 
       
  1176 /**
       
  1177  Request data form the host for the protocol
       
  1178 
       
  1179  @param aLength amount of data (in bytes) to be received from the host
       
  1180  */
       
  1181 void CBulkOnlyTransport::ReadData(TUint aLength)
       
  1182     {
       
  1183     TRACE_FUNC
       
  1184     if (IsActive())
       
  1185         {
       
  1186         TRACE_INFO((_L("Still active")))
       
  1187         __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
       
  1188         return;
       
  1189         }
       
  1190     iLdd.Read(iStatus, OutEndpoint, iReadBuf, aLength);
       
  1191     SetActive();
       
  1192     iCurrentState = EReadingData;
       
  1193     }
       
  1194 
       
  1195 /**
       
  1196  Send Command Status Wrapper to the host
       
  1197 
       
  1198  @param aTag Echo of Command Block Tag sent by the host.
       
  1199  @param aDataResidue the difference between the amount of data expected by the
       
  1200  host, and the actual amount of data processed by the device.
       
  1201  @param aStatus indicates the success or failure of the command.
       
  1202  */
       
  1203 void CBulkOnlyTransport::SendCSW(TUint aTag, TUint aDataResidue, TCswStatus aStatus)
       
  1204     {
       
  1205     TRACE_FUNC
       
  1206     TRACE_INFO((_L("DataResidue = %d, Status = %d \n"), aDataResidue, aStatus))
       
  1207 
       
  1208     if (IsActive())
       
  1209         {
       
  1210         TRACE_INFO((_L("Still active")))
       
  1211         __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
       
  1212         return;
       
  1213         }
       
  1214     TBuf8<KCswLength> csw(KCswLength);
       
  1215 
       
  1216     TInt i = KCswSingnatureOffset;
       
  1217     csw[i] = 0x55; // CSW Singature from USB Bulk-Only Transport spec
       
  1218     csw[i + 1] = 0x53;
       
  1219     csw[i + 2] = 0x42;
       
  1220     csw[i + 3] = 0x53;
       
  1221 
       
  1222     i = KCswTagOffset;
       
  1223 
       
  1224     csw[i] = static_cast<TUint8> ((aTag & 0x000000FF));
       
  1225     csw[i + 1] = static_cast<TUint8> ((aTag & 0x0000FF00) >> 8);
       
  1226     csw[i + 2] = static_cast<TUint8> ((aTag & 0x00FF0000) >> 16);
       
  1227     csw[i + 3] = static_cast<TUint8> ((aTag & 0xFF000000) >> 24);
       
  1228 
       
  1229     i = KCswDataResidueOffset;
       
  1230     csw[i] = static_cast<TUint8> ((aDataResidue & 0x000000FF));
       
  1231     csw[i + 1] = static_cast<TUint8> ((aDataResidue & 0x0000FF00) >> 8);
       
  1232     csw[i + 2] = static_cast<TUint8> ((aDataResidue & 0x00FF0000) >> 16);
       
  1233     csw[i + 3] = static_cast<TUint8> ((aDataResidue & 0xFF000000) >> 24);
       
  1234 
       
  1235     csw[KCswStatusOffset] = static_cast<TUint8> (aStatus);
       
  1236 
       
  1237     iLdd.Write(iStatus, InEndpoint, csw, KCswLength);
       
  1238 
       
  1239     iCurrentState = ESendingCSW;
       
  1240 
       
  1241     SetActive();
       
  1242     }
       
  1243 
       
  1244 /**
       
  1245  Associates the transport with the protocol.  Called during initialization of the controller.
       
  1246 
       
  1247  @param aProtocol reference to the protocol
       
  1248  */
       
  1249 void CBulkOnlyTransport::RegisterProtocol(MProtocolBase& aProtocol)
       
  1250     {
       
  1251     TRACE_FUNC
       
  1252     iProtocol = &aProtocol;
       
  1253     }
       
  1254 
       
  1255 /**
       
  1256  Used by CControlInterface
       
  1257 
       
  1258  @return reference to the controller which instantiate the CBulkOnlyTransport
       
  1259  */
       
  1260 CMscFileController& CBulkOnlyTransport::Controller()
       
  1261     {
       
  1262     return iController;
       
  1263     }
       
  1264 
       
  1265 /**
       
  1266  @return the number of logical units supported by the device. 
       
  1267  Logical Unit Numbers on the device shall be numbered contiguously starting from LUN
       
  1268  0 to a maximum LUN of 15 (Fh).
       
  1269  */
       
  1270 TInt CBulkOnlyTransport::MaxLun()
       
  1271     {
       
  1272     return iMaxLun;
       
  1273     }
       
  1274 
       
  1275 /**
       
  1276  Used by CControlInterface
       
  1277  @return reference to USB logical driver
       
  1278  */
       
  1279 RDevUsbcClient& CBulkOnlyTransport::Ldd()
       
  1280     {
       
  1281     return iLdd;
       
  1282     }
       
  1283 
       
  1284 
       
  1285 void CBulkOnlyTransport::StallEndpointAndWaitForClear(TEndpointNumber aEndpoint)
       
  1286     {
       
  1287     TRACE_FUNC
       
  1288     __ASSERT_DEBUG(aEndpoint != EEndpoint0, User::Panic(KUsbMsSvrPncCat, EMsWrongEndpoint));
       
  1289 
       
  1290     // Now stall this endpoint
       
  1291     TRACE_INFO((_L("Stalling endpoint %d"), aEndpoint))
       
  1292     TInt r = iLdd.HaltEndpoint(aEndpoint);
       
  1293     if (r != KErrNone)
       
  1294         {
       
  1295         TRACE_ERROR((_L("Error: stalling ep %d failed: %d"), aEndpoint, r))
       
  1296         }
       
  1297     TEndpointState ep_state;
       
  1298     TInt i = 0;
       
  1299     do
       
  1300         {
       
  1301         // Wait for 10ms before checking the ep status
       
  1302         User::After(10000);
       
  1303         iLdd.EndpointStatus(aEndpoint, ep_state);
       
  1304         if (++i >= 1000)
       
  1305             {
       
  1306             // 10 secs should be enough
       
  1307             TRACE_ERROR((_L("Error: Checked for ep %d de-stall %d seconds - giving up now..."),
       
  1308                             aEndpoint, i / 100))
       
  1309             // We can only hope for a Reset Recovery
       
  1310             return;
       
  1311             }
       
  1312         }while ((ep_state == EEndpointStateStalled) && iStarted);
       
  1313     TRACE_INFO((_L("Checked for ep %d de-stall: %d time(s)"), aEndpoint, i))
       
  1314     }
       
  1315 
       
  1316 /**
       
  1317  * Read out rest data from OutEndpoint and discard them
       
  1318  */
       
  1319 void CBulkOnlyTransport::ReadAndDiscardData(TInt aBytes)
       
  1320     {
       
  1321     TRACE_FUNC
       
  1322     const TUint bufsize = static_cast<TUint>(iReadBuf.Length());
       
  1323     __ASSERT_ALWAYS(bufsize> 0, User::Panic(_L("Buffer size is zero"), bufsize));
       
  1324     TRequestStatus status;
       
  1325     while (aBytes> 0)
       
  1326         {
       
  1327         TRACE_INFO((_L("Bytes still to be read: %d\n"), aBytes))
       
  1328         iLdd.ReadOneOrMore(status, OutEndpoint, iReadBuf, bufsize);
       
  1329         User::WaitForRequest(status);
       
  1330         TInt err = status.Int();
       
  1331         if (err != KErrNone)
       
  1332             {
       
  1333             // Bad.
       
  1334             break;
       
  1335             }
       
  1336         aBytes -= iReadBuf.Length();
       
  1337         }
       
  1338     iReadBuf.SetLength(bufsize);
       
  1339     }
       
  1340 
       
  1341 /**
       
  1342  Called by the protocol to determine how many bytes of data are available in the read buffer. 
       
  1343 
       
  1344  @return The number of bytes available in the read buffer
       
  1345  */
       
  1346 TInt CBulkOnlyTransport::BytesAvailable()
       
  1347     {
       
  1348     TInt bytes = 0;
       
  1349     TInt err = iLdd.QueryReceiveBuffer(OutEndpoint, bytes);
       
  1350     if (err != KErrNone)
       
  1351         bytes = 0;
       
  1352     return bytes;
       
  1353     }
       
  1354 
       
  1355 //
       
  1356 // --- class CActiveDeviceStateNotifier ---------------------------------------------------------
       
  1357 //
       
  1358 CActiveDeviceStateNotifier::CActiveDeviceStateNotifier(CBulkOnlyTransport& aParent)
       
  1359 /**
       
  1360  *
       
  1361  */
       
  1362 	: CActive(EPriorityStandard),
       
  1363 	  iParent(aParent),
       
  1364 	  iDeviceState(EUsbcNoState),
       
  1365             iOldDeviceState(EUsbcNoState)
       
  1366     {
       
  1367 
       
  1368     }
       
  1369 
       
  1370 
       
  1371 CActiveDeviceStateNotifier* CActiveDeviceStateNotifier::NewL(CBulkOnlyTransport& aParent)
       
  1372 /**
       
  1373  *
       
  1374  */
       
  1375     {
       
  1376 	CActiveDeviceStateNotifier* self = new (ELeave) CActiveDeviceStateNotifier(aParent);
       
  1377     CleanupStack::PushL(self);
       
  1378     self->ConstructL();
       
  1379     CActiveScheduler::Add(self);
       
  1380     CleanupStack::Pop(); // self
       
  1381     return (self);
       
  1382     }
       
  1383 
       
  1384 void CActiveDeviceStateNotifier::ConstructL()
       
  1385 /**
       
  1386  *
       
  1387  */
       
  1388     {
       
  1389     TRACE_FUNC
       
  1390 	}
       
  1391 
       
  1392 CActiveDeviceStateNotifier::~CActiveDeviceStateNotifier()
       
  1393 /**
       
  1394  *
       
  1395  */
       
  1396     {
       
  1397     TRACE_FUNC
       
  1398     Cancel();												// base class
       
  1399     }
       
  1400 
       
  1401 void CActiveDeviceStateNotifier::DoCancel()
       
  1402 /**
       
  1403  *
       
  1404  */
       
  1405     {
       
  1406     TRACE_FUNC
       
  1407     iParent.Ldd().AlternateDeviceStatusNotifyCancel();
       
  1408     }
       
  1409 
       
  1410 void CActiveDeviceStateNotifier::RunL()
       
  1411 /**
       
  1412  *
       
  1413  */
       
  1414     {
       
  1415     TRACE_FUNC
       
  1416     // This displays the device state.
       
  1417     // In a real world program, the user could take here appropriate action (cancel a
       
  1418     // transfer request or whatever).
       
  1419     if (!(iDeviceState & KUsbAlternateSetting))
       
  1420         {
       
  1421 
       
  1422         switch (iDeviceState)
       
  1423             {
       
  1424             case EUsbcDeviceStateUndefined:
       
  1425             TRACE_INFO((_L("Device State notifier: Undefined\n")))
       
  1426             iParent.HwStop();
       
  1427             break;
       
  1428             case EUsbcDeviceStateAttached:
       
  1429             TRACE_INFO((_L("Device State notifier: Attached\n")))
       
  1430             iParent.HwStop();
       
  1431             break;
       
  1432             case EUsbcDeviceStatePowered:
       
  1433             TRACE_INFO((_L("Device State notifier: Powered\n")))
       
  1434             iParent.HwStop();
       
  1435             break;
       
  1436             case EUsbcDeviceStateDefault:
       
  1437             TRACE_INFO((_L("Device State notifier: Default\n")))
       
  1438             iParent.HwStop();
       
  1439             break;
       
  1440             case EUsbcDeviceStateAddress:
       
  1441             TRACE_INFO((_L("Device State notifier: Address\n")))
       
  1442             iParent.HwStop();
       
  1443             break;
       
  1444             case EUsbcDeviceStateConfigured:
       
  1445             TRACE_INFO((_L("Device State notifier: Configured\n")))
       
  1446             if (iOldDeviceState == EUsbcDeviceStateSuspended)
       
  1447                 {
       
  1448                 iParent.HwResume();
       
  1449                 }
       
  1450             else
       
  1451                 {
       
  1452                 iParent.HwStart();
       
  1453                 }
       
  1454             break;
       
  1455             case EUsbcDeviceStateSuspended:
       
  1456             TRACE_INFO((_L("Device State notifier: Suspended\n")))
       
  1457             if (iOldDeviceState == EUsbcDeviceStateConfigured)
       
  1458                 {
       
  1459                 iParent.HwSuspend();
       
  1460                 }
       
  1461             break;
       
  1462             default:
       
  1463             TRACE_INFO((_L("Device State notifier: ***BAD***\n")))
       
  1464             iParent.HwStop();
       
  1465             break;
       
  1466             }
       
  1467         iOldDeviceState = iDeviceState;
       
  1468         }
       
  1469     else if (iDeviceState & KUsbAlternateSetting)
       
  1470         {
       
  1471         TRACE_INFO((_L("Device State notifier: Alternate interface setting has changed: now %d\n"),
       
  1472                         iDeviceState & ~KUsbAlternateSetting))
       
  1473         }
       
  1474     Activate();
       
  1475     }
       
  1476 
       
  1477 void CActiveDeviceStateNotifier::Activate()
       
  1478 /**
       
  1479  *
       
  1480  */
       
  1481     {
       
  1482     TRACE_FUNC
       
  1483     if (IsActive())
       
  1484         {
       
  1485         TRACE_INFO((_L("Still active")))
       
  1486         return;
       
  1487         }
       
  1488     iParent.Ldd().AlternateDeviceStatusNotify(iStatus, iDeviceState);
       
  1489     SetActive();
       
  1490     }
       
  1491