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