userlibandfileserver/fileserver/smassstorage/cbulkonlytransportusbcldd.cpp
changeset 286 48e57fb1237e
parent 271 dc268b18d709
equal deleted inserted replaced
285:ff5437e4337c 286:48e57fb1237e
    19 /**
    19 /**
    20  @file
    20  @file
    21  @internalTechnology
    21  @internalTechnology
    22 */
    22 */
    23 
    23 
       
    24 #include <e32std.h>
       
    25 #include "mtransport.h"
       
    26 #include "mprotocol.h"
       
    27 #include "mldddevicestatenotification.h"
       
    28 #include "tbulkmm.h"
       
    29 
       
    30 #include "drivemanager.h"
       
    31 #include "cusbmassstoragecontroller.h"
       
    32 
    24 #include "cbulkonlytransport.h"
    33 #include "cbulkonlytransport.h"
    25 #include "cbulkonlytransportusbcldd.h"
    34 #include "cbulkonlytransportusbcldd.h"
    26 #include "usbmsshared.h"
    35 #include "smassstorage.h"
    27 #include "massstoragedebug.h"
    36 
    28 #include "cusbmassstorageserver.h"
    37 #include "OstTraceDefinitions.h"
       
    38 #ifdef OST_TRACE_COMPILER_IN_USE
       
    39 #include "cbulkonlytransportusbclddTraces.h"
       
    40 #endif
       
    41 
       
    42 
    29 
    43 
    30 #define InEndpoint EEndpoint1
    44 #define InEndpoint EEndpoint1
    31 #define OutEndpoint EEndpoint2
    45 #define OutEndpoint EEndpoint2
    32 
    46 
    33 //This value defined in USB Mass Storage Bulk Only Transrt spec and not supposed to be changed
    47 //This value defined in USB Mass Storage Bulk Only Transrt spec and not supposed to be changed
    34 LOCAL_D const TInt KRequiredNumberOfEndpoints = 2; // in addition to endpoint 0.
    48 static const TInt KRequiredNumberOfEndpoints = 2; // in addition to endpoint 0.
    35 
    49 
    36 LOCAL_D const TInt KUsbNumInterfacesOffset = 4;
    50 static const TInt KUsbNumInterfacesOffset = 4;
    37 
    51 
    38 ////////////////////////////////////
    52 ////////////////////////////////////
    39 /**
    53 /**
    40 Called by CBulkOnlyTransportUsbcLdd to create an instance of CControlInterfaceUsbcLdd
    54 Called by CBulkOnlyTransportUsbcLdd to create an instance of CControlInterfaceUsbcLdd
    41 
    55 
    42 @param aParent reference to the CBulkOnlyTransportUsbcLdd
    56 @param aParent reference to the CBulkOnlyTransportUsbcLdd
    43 */
    57 */
    44 
    58 
    45 
    59 
    46 CControlInterfaceUsbcLdd* CControlInterfaceUsbcLdd::NewL(CBulkOnlyTransportUsbcLdd& aParent)
    60 CControlInterfaceUsbcLdd* CControlInterfaceUsbcLdd::NewL(CBulkOnlyTransportUsbcLdd& aParent)
    47 	{
    61     {
    48 	CControlInterfaceUsbcLdd* self = new(ELeave) CControlInterfaceUsbcLdd(aParent);
    62     CControlInterfaceUsbcLdd* self = new(ELeave) CControlInterfaceUsbcLdd(aParent);
    49 	CleanupStack::PushL(self);
    63     CleanupStack::PushL(self);
    50 	self->ConstructL();
    64     self->ConstructL();
    51 	CActiveScheduler::Add(self);
    65     CActiveScheduler::Add(self);
    52 	CleanupStack::Pop();
    66     CleanupStack::Pop();
    53 	return self;
    67     return self;
    54 	}
    68     }
    55 
    69 
    56 
    70 
    57 void CControlInterfaceUsbcLdd::ConstructL()
    71 void CControlInterfaceUsbcLdd::ConstructL()
    58 	{
    72     {
    59 	}
    73     }
    60 
    74 
    61 
    75 
    62 /**
    76 /**
    63 c'tor
    77 c'tor
    64 
    78 
    65 @param aParent reference to the CBulkOnlyTransportUsbcLdd
    79 @param aParent reference to the CBulkOnlyTransportUsbcLdd
    66 */
    80 */
    67 CControlInterfaceUsbcLdd::CControlInterfaceUsbcLdd(CBulkOnlyTransportUsbcLdd& aParent)
    81 CControlInterfaceUsbcLdd::CControlInterfaceUsbcLdd(CBulkOnlyTransportUsbcLdd& aParent)
    68 	:CActive(EPriorityStandard),
    82     :CActive(EPriorityStandard),
    69 	 iParent(aParent),
    83      iParent(aParent),
    70 	 iCurrentState(ENone)
    84      iCurrentState(ENone)
    71 	{
    85     {
    72 	}
    86     }
    73 
    87 
    74 
    88 
    75 /**
    89 /**
    76 d'tor
    90 d'tor
    77 */
    91 */
    78 CControlInterfaceUsbcLdd::~CControlInterfaceUsbcLdd()
    92 CControlInterfaceUsbcLdd::~CControlInterfaceUsbcLdd()
    79 	{
    93     {
    80 	__FNLOG("CControlInterfaceUsbcLdd::~CControlInterfaceUsbcLdd ");
    94     Cancel();
    81 	Cancel();
    95     }
    82 	}
       
    83 
    96 
    84 
    97 
    85 /**
    98 /**
    86 Called by CBulkOnlyTransport HwStart to start control interface
    99 Called by CBulkOnlyTransport HwStart to start control interface
    87 */
   100 */
    88 TInt CControlInterfaceUsbcLdd::Start()
   101 TInt CControlInterfaceUsbcLdd::Start()
    89 	{
   102     {
    90 	__FNLOG("CControlInterfaceUsbcLdd::Start ");
   103     TInt res = ReadEp0Data();
    91 	TInt res = ReadEp0Data();
   104     return (res);
    92 	return (res);
   105     }
    93 	}
       
    94 
   106 
    95 
   107 
    96 /**
   108 /**
    97 Called by desctructor of CBulkOnlyTransportUsbcLdd to stop control interface
   109 Called by desctructor of CBulkOnlyTransportUsbcLdd to stop control interface
    98 */
   110 */
    99 void CControlInterfaceUsbcLdd::Stop()
   111 void CControlInterfaceUsbcLdd::Stop()
   100 	{
   112     {
   101 	__FNLOG("CControlInterfaceUsbcLdd::Stop ");
   113     if (!IsActive())
   102 	if (!IsActive())
   114         {
   103 		{
   115         return;
   104 		__PRINT(_L("Not active\n"));
   116         }
   105 		return;
   117     iCurrentState = ENone;
   106 		}
   118     Cancel();
   107 
   119     }
   108 	__PRINT(_L("\nStopping...\n"));
       
   109 
       
   110 
       
   111 	iCurrentState = ENone;
       
   112 
       
   113 	Cancel();
       
   114 	}
       
   115 
   120 
   116 
   121 
   117 /**
   122 /**
   118 Cancel outstanding request (if any)
   123 Cancel outstanding request (if any)
   119 */
   124 */
   120 void CControlInterfaceUsbcLdd::DoCancel()
   125 void CControlInterfaceUsbcLdd::DoCancel()
   121 	{
   126     {
   122 	__FNLOG("CControlInterfaceUsbcLdd::DoCancel ");
   127     switch(iCurrentState)
   123 	switch(iCurrentState)
   128         {
   124 		{
   129         case EReadEp0Data:
   125 		case EReadEp0Data:
   130             iParent.Ldd().ReadCancel(EEndpoint0);
   126 			iParent.Ldd().ReadCancel(EEndpoint0);
   131             break;
   127 			break;
   132         case ESendMaxLun:
   128 		case ESendMaxLun:
   133             iParent.Ldd().WriteCancel(EEndpoint0);
   129 			iParent.Ldd().WriteCancel(EEndpoint0);
   134             break;
   130 			break;
   135         default:
   131 		default:
   136             __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceBadState));
   132 			__PRINT(_L("\nWrong state !\n"));
   137             break;
   133 			__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceBadState));
   138         }
   134 		}
   139     }
   135 	}
       
   136 
   140 
   137 
   141 
   138 /**
   142 /**
   139 Implement CControlInterfaceUsbcLdd state machine
   143 Implement CControlInterfaceUsbcLdd state machine
   140 */
   144 */
   141 void CControlInterfaceUsbcLdd::RunL()
   145 void CControlInterfaceUsbcLdd::RunL()
   142 	{
   146     {
   143 	__FNLOG("CControlInterfaceUsbcLdd::RunL ");
   147     if (iStatus != KErrNone)
   144 	if (iStatus != KErrNone)
   148         {
   145 		{
   149         OstTrace1(TRACE_SMASSSTORAGE_BOT, CCONTROLINTERFACEUSBCLDD,
   146 		__PRINT1(_L("Error %d in RunL\n"), iStatus.Int());
   150                   "ERROR %d in RunL", iStatus.Int());
   147 
   151 
   148 		//read EP0  again
   152         //read EP0  again
   149 		ReadEp0Data();
   153         ReadEp0Data();
   150 		return;
   154         return;
   151 		}
   155         }
   152 
   156 
   153 	switch (iCurrentState)
   157     switch (iCurrentState)
   154 		{
   158         {
   155 		case ESendMaxLun:
   159         case ESendMaxLun:
   156 			ReadEp0Data();
   160             ReadEp0Data();
   157 			break;
   161             break;
   158 
   162 
   159 		case EReadEp0Data:
   163         case EReadEp0Data:
   160 			DecodeEp0Data();
   164             DecodeEp0Data();
   161 			break;
   165             break;
   162 
   166 
   163 		default:
   167         default:
   164 			__PRINT(_L("  error: (Shouldn't end up here...)\n"));
   168             __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceBadState));
   165 			__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceBadState));
   169             break;
   166 			break;
   170         }
   167 		}
   171     return;
   168 	return;
   172     }
   169 	}
       
   170 
   173 
   171 
   174 
   172 /**
   175 /**
   173 Post a read request to EEndpoint0 to read request header
   176 Post a read request to EEndpoint0 to read request header
   174 */
   177 */
   175 TInt CControlInterfaceUsbcLdd::ReadEp0Data()
   178 TInt CControlInterfaceUsbcLdd::ReadEp0Data()
   176 	{
   179     {
   177 	__FNLOG("CControlInterfaceUsbcLdd::ReadEp0Data ");
   180     if (IsActive())
   178 	if (IsActive())
   181         {
   179 		{
   182         OstTrace0(TRACE_SMASSSTORAGE_BOT, READEP0DATA, "Still active");
   180 		__PRINT(_L("Still active\n"));
   183         return KErrServerBusy;
   181 		return KErrServerBusy;
   184         }
   182 		}
   185     iParent.Ldd().Read(iStatus, EEndpoint0, iData, KRequestHdrSize);
   183 	iParent.Ldd().Read(iStatus, EEndpoint0, iData, KRequestHdrSize);
   186 
   184 
   187     iCurrentState = EReadEp0Data;
   185 	iCurrentState = EReadEp0Data;
   188 
   186 
   189     SetActive();
   187 	SetActive();
   190     return KErrNone;
   188 	return KErrNone;
   191     }
   189 	}
       
   190 
   192 
   191 
   193 
   192 /**
   194 /**
   193 Decode request header and do appropriate action - get max LUN info or post a reset request
   195 Decode request header and do appropriate action - get max LUN info or post a reset request
   194 */
   196 */
   195 void CControlInterfaceUsbcLdd::DecodeEp0Data()
   197 void CControlInterfaceUsbcLdd::DecodeEp0Data()
   196 	{
   198     {
   197 	__FNLOG("CControlInterfaceUsbcLdd::DecodeEp0Data ");
   199     if (IsActive())
   198 	if (IsActive())
   200         {
   199 		{
   201         __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceStillActive));
   200 		__PRINT(_L("Still active\n"));
   202         return;
   201 		__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceStillActive));
   203         }
   202 		return;
   204 
   203 		}
   205     TInt err = iRequestHeader.Decode(iData);
   204 
   206 
   205 	TInt err = iRequestHeader.Decode(iData);
   207     if(err != KErrNone)
   206 
   208         return;
   207 	if(err != KErrNone)
       
   208 		return;
       
   209 
   209 
   210     switch(iRequestHeader.iRequest)
   210     switch(iRequestHeader.iRequest)
   211 		{
   211         {
   212 		//
   212         //
   213 		// GET MAX LUN (0xFE)
   213         // GET MAX LUN (0xFE)
   214 		//
   214         //
   215 		case TUsbRequestHdr::EReqGetMaxLun:
   215         case TUsbRequestHdr::EReqGetMaxLun:
   216 			{
   216             {
   217 			__PRINT1(_L("DecodeEp0Data : 'Get Max LUN' Request MaxLun = %d"),iParent.MaxLun() );
   217             OstTrace1(TRACE_SMASSSTORAGE_BOT, DECODEEP0DATA, ">>> EP0 GetMaxLun = %d", iParent.MaxLun());
   218 
       
   219             if (   iRequestHeader.iRequestType != 0xA1 //value from USB MS BOT spec
   218             if (   iRequestHeader.iRequestType != 0xA1 //value from USB MS BOT spec
   220                 || iRequestHeader.iIndex > 15
   219                 || iRequestHeader.iIndex > 15
   221                 || iRequestHeader.iValue != 0
   220                 || iRequestHeader.iValue != 0
   222                 || iRequestHeader.iLength != 1)
   221                 || iRequestHeader.iLength != 1)
   223                 {
   222                 {
   224     		    __PRINT(_L("GetMaxLun command packet check error"));
   223                 OstTrace0(TRACE_SMASSSTORAGE_BOT, DECODEEP0DATA1, "ERROR: GetMaxLun command packet check error");
   225                 iParent.Ldd().EndpointZeroRequestError();
   224                 iParent.Ldd().EndpointZeroRequestError();
   226                 break;
   225                 break;
   227                 }
   226                 }
   228 			iData.FillZ(1);  //Return only 1 byte to host
   227             iData.FillZ(1);  //Return only 1 byte to host
   229 			iData[0] = static_cast<TUint8>(iParent.MaxLun());	// Supported Units
   228             iData[0] = static_cast<TUint8>(iParent.MaxLun());   // Supported Units
   230 			iParent.Ldd().Write(iStatus, EEndpoint0, iData, 1);
   229             iParent.Ldd().Write(iStatus, EEndpoint0, iData, 1);
   231 
   230 
   232 			iCurrentState = ESendMaxLun;
   231             iCurrentState = ESendMaxLun;
   233 			SetActive();
   232             SetActive();
   234 
   233 
   235 			return;
   234             return;
   236 			}
   235             }
   237 		//
   236         //
   238 		// RESET (0xFF)
   237         // RESET (0xFF)
   239 		//
   238         //
   240 		case TUsbRequestHdr::EReqReset:
   239         case TUsbRequestHdr::EReqReset:
   241 			{
   240             {
   242 			__PRINT(_L("DecodeEp0Data : 'Mass Storage Reset' Request"));
   241             OstTrace0(TRACE_SMASSSTORAGE_BOT, DECODEEP0DATA2, ">>> EP0 BulkOnlyMassStorageReset");
   243 
   242 
   244             if (   iRequestHeader.iRequestType != 0x21 //value from USB MS BOT spec
   243             if (   iRequestHeader.iRequestType != 0x21 //value from USB MS BOT spec
   245                 || iRequestHeader.iIndex > 15
   244                 || iRequestHeader.iIndex > 15
   246                 || iRequestHeader.iValue != 0
   245                 || iRequestHeader.iValue != 0
   247                 || iRequestHeader.iLength != 0)
   246                 || iRequestHeader.iLength != 0)
   248                 {
   247                 {
   249 			    __PRINT(_L("MSC Reset command packet check error"));
   248                 OstTrace0(TRACE_SMASSSTORAGE_BOT, DECODEEP0DATA3, "BulkOnlyMassStorageReset command packet check error");
   250                 iParent.Ldd().EndpointZeroRequestError();
   249                 iParent.Ldd().EndpointZeroRequestError();
   251                 break;
   250                 break;
   252                 }
   251                 }
   253 			iParent.HwStop();
   252             iParent.HwStop();
   254 			iParent.Controller().Reset();
   253             iParent.Controller().Reset();
   255 			iParent.HwStart(ETrue);
   254             iParent.HwStart(ETrue);
   256 
   255 
   257             err = iParent.Ldd().SendEp0StatusPacket();
   256             err = iParent.Ldd().SendEp0StatusPacket();
   258 
   257 
   259 			return;
   258             return;
   260 			}
   259             }
   261 		//
   260         //
   262 		// Unknown?
   261         // Unknown?
   263 		//
   262         //
   264 		default:
   263         default:
   265 			{
   264             {
   266 			__PRINT(_L("DecodeEp0Data : Unknown Request"));
   265             OstTrace0(TRACE_SMASSSTORAGE_BOT, DECODEEP0DATA4, ">>> EP0 DecodeEp0Data : Unknown Request");
   267 
   266             }
   268 			}
   267         }
   269 		}
   268         ReadEp0Data();  //try to get another request
   270 		ReadEp0Data();  //try to get another request
   269     }
   271 	}
       
   272 
   270 
   273 
   271 
   274 //
   272 //
   275 // --- class CBulkOnlyTransportUsbcLdd ---------------------------------------------------------
   273 // --- class CBulkOnlyTransportUsbcLdd ---------------------------------------------------------
   276 //
   274 //
   277 
   275 
   278 CBulkOnlyTransportUsbcLdd::CBulkOnlyTransportUsbcLdd(TInt aNumDrives,CUsbMassStorageController& aController)
   276 CBulkOnlyTransportUsbcLdd::CBulkOnlyTransportUsbcLdd(TInt aNumDrives,CUsbMassStorageController& aController)
   279 	:CBulkOnlyTransport(aNumDrives, aController),
   277     :CBulkOnlyTransport(aNumDrives, aController)
   280 	 iSwap(ETrue)
   278     {
   281 	{
   279     }
   282 	__FNLOG("CBulkOnlyTransportUsbcLdd::CBulkOnlyTransportUsbcLdd");
       
   283 	}
       
   284 
   280 
   285 /**
   281 /**
   286 Constructs the CBulkOnlyTransportUsbcLdd object
   282 Constructs the CBulkOnlyTransportUsbcLdd object
   287 */
   283 */
   288 void CBulkOnlyTransportUsbcLdd::ConstructL()
   284 void CBulkOnlyTransportUsbcLdd::ConstructL()
   289 	{
   285     {
   290 	__FNLOG("CBulkOnlyTransportUsbcLdd::ConstructL()");
   286     iControlInterface = CControlInterfaceUsbcLdd::NewL(*this);
   291 	iControlInterface = CControlInterfaceUsbcLdd::NewL(*this);
   287     iDeviceStateNotifier = CActiveDeviceStateNotifierBase::NewL(*this, *this);
   292 	iDeviceStateNotifier = CActiveDeviceStateNotifierBase::NewL(*this, *this);
   288     CActiveScheduler::Add(this);
   293 	CActiveScheduler::Add(this);
   289     }
   294 	}
       
   295 
   290 
   296 CBulkOnlyTransportUsbcLdd::~CBulkOnlyTransportUsbcLdd()
   291 CBulkOnlyTransportUsbcLdd::~CBulkOnlyTransportUsbcLdd()
   297 	{
   292     {
   298 	__FNLOG("CBulkOnlyTransportUsbcLdd::~CBulkOnlyTransportUsbcLdd");
   293     if (iInterfaceConfigured)
   299 	if (iInterfaceConfigured)
   294         {
   300 		{
   295         Stop();
   301 		Stop();
   296         delete iControlInterface ;
   302 		delete iControlInterface ;
   297         delete iDeviceStateNotifier;
   303 		delete iDeviceStateNotifier;
   298         }
   304 		}
   299     }
   305 	}	
       
   306 
   300 
   307 RDevUsbcClient& CBulkOnlyTransportUsbcLdd::Ldd()
   301 RDevUsbcClient& CBulkOnlyTransportUsbcLdd::Ldd()
   308 	{
   302     {
   309 	return iLdd;
   303     return iLdd;
   310 	}
   304     }
   311 
   305 
   312 
   306 
   313 /**
   307 /**
   314 Set or unset configuration descriptor for USB MassStorage Bulk Only transport
   308 Set or unset configuration descriptor for USB MassStorage Bulk Only transport
   315 
   309 
   316 @param aUnset indicate whether set or unset descriptor
   310 @param aUnset indicate whether set or unset descriptor
   317 @return KErrNone if operation was completed successfully, errorcode otherwise
   311 @return KErrNone if operation was completed successfully, errorcode otherwise
   318 */
   312 */
   319 TInt CBulkOnlyTransportUsbcLdd::SetupConfigurationDescriptor(TBool aUnset)
   313 TInt CBulkOnlyTransportUsbcLdd::SetupConfigurationDescriptor(TBool aUnset)
   320 	{
   314     {
   321 	__FNLOG("CBulkOnlyTransportUsbcLdd::SetupConfigurationDescriptor");
   315     TInt ret(KErrNone);
   322 	TInt ret(KErrNone);
   316 
   323 	
   317         if ((ret = iLdd.Open(0)) != KErrNone)
   324 		if ((ret = iLdd.Open(0)) != KErrNone)
   318             return ret;
   325 			return ret;
   319 
   326 
   320     TInt configDescriptorSize(0);
   327 	TInt configDescriptorSize(0);
   321     iLdd.GetConfigurationDescriptorSize(configDescriptorSize);
   328 	iLdd.GetConfigurationDescriptorSize(configDescriptorSize);
   322     if (static_cast<TUint>(configDescriptorSize) != KUsbDescSize_Config)
   329 	if (static_cast<TUint>(configDescriptorSize) != KUsbDescSize_Config)
   323         {
   330 		{
   324         return KErrCorrupt;
   331 		return KErrCorrupt;
   325         }
   332 		}
   326 
   333 
   327     TBuf8<KUsbDescSize_Config> configDescriptor;
   334 	TBuf8<KUsbDescSize_Config> configDescriptor;
   328     ret = iLdd.GetConfigurationDescriptor(configDescriptor);
   335 	ret = iLdd.GetConfigurationDescriptor(configDescriptor);
   329     if (ret != KErrNone)
   336 	if (ret != KErrNone)
   330         {
   337 		{
   331         return ret;
   338 		return ret;
   332         }
   339 		}
   333 
   340 
   334     // I beleive that other fields setted up during LDD initialisation
   341 	// I beleive that other fields setted up during LDD initialisation
   335     if (aUnset)
   342 	if (aUnset)
   336         {
   343 		{
   337         --configDescriptor[KUsbNumInterfacesOffset];
   344 		--configDescriptor[KUsbNumInterfacesOffset];
   338         }
   345 		}
   339     else
   346 	else
   340         {
   347 		{
   341         ++configDescriptor[KUsbNumInterfacesOffset];
   348 		++configDescriptor[KUsbNumInterfacesOffset];
   342         }
   349 		}
   343     ret = iLdd.SetConfigurationDescriptor(configDescriptor);
   350 	ret = iLdd.SetConfigurationDescriptor(configDescriptor);
   344 
   351 
   345     if (aUnset)
   352 	if (aUnset)
   346         {
   353 		{
   347         iLdd.Close();
   354 		iLdd.Close();
   348         }
   355 		}
   349     return ret;
   356 	return ret;
   350     }
   357 	}
       
   358 
   351 
   359 /**
   352 /**
   360 Set up interface descriptor
   353 Set up interface descriptor
   361 
   354 
   362 @return KErrNone if operation was completed successfully, errorcode otherwise
   355 @return KErrNone if operation was completed successfully, errorcode otherwise
   363 */
   356 */
   364 TInt CBulkOnlyTransportUsbcLdd::SetupInterfaceDescriptors()
   357 TInt CBulkOnlyTransportUsbcLdd::SetupInterfaceDescriptors()
   365 	{
   358     {
   366 	__FNLOG("CBulkOnlyTransportUsbcLdd::SetupInterfaceDescriptors");
   359     // Device caps
   367 	// Device caps
   360     TUsbDeviceCaps d_caps;
   368 	TUsbDeviceCaps d_caps;
   361     TInt ret = iLdd.DeviceCaps(d_caps);
   369 	TInt ret = iLdd.DeviceCaps(d_caps);
   362     if (ret != KErrNone)
   370 	if (ret != KErrNone)
   363         {
   371 		{
   364         return ret;
   372 		return ret;
   365         }
   373 		}
   366     TInt totalEndpoints = d_caps().iTotalEndpoints;
   374 	TInt totalEndpoints = d_caps().iTotalEndpoints;
   367     if (totalEndpoints  < KRequiredNumberOfEndpoints)
   375 	if (totalEndpoints  < KRequiredNumberOfEndpoints)
   368         {
   376 		{
   369         return KErrHardwareNotAvailable;
   377 		return KErrHardwareNotAvailable;
   370         }
   378 		}
   371 
   379 
   372     // Endpoint caps
   380 	// Endpoint caps
   373     TUsbcEndpointData data[KUsbcMaxEndpoints];
   381 	TUsbcEndpointData data[KUsbcMaxEndpoints];
   374     TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data));
   382 	TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data));
   375     ret = iLdd.EndpointCaps(dataptr);
   383 	ret = iLdd.EndpointCaps(dataptr);
   376     if (ret != KErrNone)
   384 	if (ret != KErrNone)
   377         {
   385 		{
   378         return ret;
   386 		return ret;
   379         }
   387 		}
   380 
   388 
   381     // Set the active interface
   389 	// Set the active interface
   382     TUsbcInterfaceInfoBuf ifc;
   390 	TUsbcInterfaceInfoBuf ifc;
   383     TInt ep_found = 0;
   391 	TInt ep_found = 0;
   384     TBool foundBulkIN = EFalse;
   392 	TBool foundBulkIN = EFalse;
   385     TBool foundBulkOUT = EFalse;
   393 	TBool foundBulkOUT = EFalse;
   386 
   394 
   387     for (TInt i = 0; i < totalEndpoints ; i++)
   395 	for (TInt i = 0; i < totalEndpoints ; i++)
   388         {
   396 		{
   389         const TUsbcEndpointCaps* caps = &data[i].iCaps;
   397 		const TUsbcEndpointCaps* caps = &data[i].iCaps;
   390         const TInt maxPacketSize = caps->MaxPacketSize();
   398 		const TInt maxPacketSize = caps->MaxPacketSize();
   391         if (!foundBulkIN &&
   399 		if (!foundBulkIN &&
   392             (caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirIn)) == (KUsbEpTypeBulk | KUsbEpDirIn))
   400 			(caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirIn)) == (KUsbEpTypeBulk | KUsbEpDirIn))
   393             {
   401 			{
   394             // InEndpoint is going to be our TX (IN, write) endpoint
   402 			// InEndpoint is going to be our TX (IN, write) endpoint
   395             ifc().iEndpointData[0].iType = KUsbEpTypeBulk;
   403 			ifc().iEndpointData[0].iType = KUsbEpTypeBulk;
   396             if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) == KUsbDevCapsFeatureWord1_EndpointResourceAllocV2)
   404 			if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) == KUsbDevCapsFeatureWord1_EndpointResourceAllocV2)
   397                 ifc().iEndpointData[0].iFeatureWord1  = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering;
   405 				ifc().iEndpointData[0].iFeatureWord1  = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering;
   398             ifc().iEndpointData[0].iDir  = KUsbEpDirIn;
   406 			ifc().iEndpointData[0].iDir  = KUsbEpDirIn;
   399             ifc().iEndpointData[0].iSize = maxPacketSize;
   407 			ifc().iEndpointData[0].iSize = maxPacketSize;
   400             ifc().iEndpointData[0].iInterval_Hs = 0;
   408 			ifc().iEndpointData[0].iInterval_Hs = 0;
   401             foundBulkIN = ETrue;
   409 			foundBulkIN = ETrue;
   402             if (++ep_found == KRequiredNumberOfEndpoints)
   410 			if (++ep_found == KRequiredNumberOfEndpoints)
   403                 {
   411 				{
   404                 break;
   412 				break;
   405                 }
   413 				}
   406             continue;
   414 			continue;
   407             }
   415 			}
   408         if (!foundBulkOUT &&
   416 		if (!foundBulkOUT &&
   409             (caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirOut)) == (KUsbEpTypeBulk | KUsbEpDirOut))
   417 			(caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirOut)) == (KUsbEpTypeBulk | KUsbEpDirOut))
   410             {
   418 			{
   411             // OutEndpoint is going to be our RX (OUT, read) endpoint
   419 			// OutEndpoint is going to be our RX (OUT, read) endpoint
   412             ifc().iEndpointData[1].iType = KUsbEpTypeBulk;
   420 			ifc().iEndpointData[1].iType = KUsbEpTypeBulk;
   413             if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) == KUsbDevCapsFeatureWord1_EndpointResourceAllocV2)
   421 			if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) == KUsbDevCapsFeatureWord1_EndpointResourceAllocV2)
   414                 ifc().iEndpointData[1].iFeatureWord1  = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering;
   422 				ifc().iEndpointData[1].iFeatureWord1  = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering;
   415             ifc().iEndpointData[1].iDir  = KUsbEpDirOut;
   423 			ifc().iEndpointData[1].iDir  = KUsbEpDirOut;
   416             ifc().iEndpointData[1].iSize = maxPacketSize;
   424 			ifc().iEndpointData[1].iSize = maxPacketSize;
   417             ifc().iEndpointData[1].iInterval_Hs = 0;
   425 			ifc().iEndpointData[1].iInterval_Hs = 0;
   418             foundBulkOUT = ETrue;
   426 			foundBulkOUT = ETrue;
   419             if (++ep_found == KRequiredNumberOfEndpoints)
   427 			if (++ep_found == KRequiredNumberOfEndpoints)
   420                 {
   428 				{
   421                 break;
   429 				break;
   422                 }
   430 				}
   423             continue;
   431 			continue;
   424             }
   432 			}
   425         }
   433 		}
   426     if (ep_found != KRequiredNumberOfEndpoints)
   434 	if (ep_found != KRequiredNumberOfEndpoints)
   427         {
   435 		{
   428         return KErrHardwareNotAvailable;
   436 		return KErrHardwareNotAvailable;
   429         }
   437 		}
   430 
   438 
   431     _LIT16(string, "USB Mass Storage Interface");
   439 	_LIT16(string, "USB Mass Storage Interface");
   432     ifc().iString = const_cast<TDesC16*>(&string);
   440 	ifc().iString = const_cast<TDesC16*>(&string);
   433     ifc().iTotalEndpointsUsed = KRequiredNumberOfEndpoints;
   441 	ifc().iTotalEndpointsUsed = KRequiredNumberOfEndpoints;
   434     ifc().iClass.iClassNum    = 0x08;   // Mass Storage
   442 	ifc().iClass.iClassNum    = 0x08;	// Mass Storage
   435     ifc().iClass.iSubClassNum = 0x06;   // SCSI Transparent Command Set
   443 	ifc().iClass.iSubClassNum = 0x06;	// SCSI Transparent Command Set
   436     ifc().iClass.iProtocolNum = 0x50;   // Bulk Only Transport
   444 	ifc().iClass.iProtocolNum = 0x50;	// Bulk Only Transport
   437 
   445 
   438     TUint bandwidth_priority = (EUsbcBandwidthOUTDefault | EUsbcBandwidthINDefault);
   446 	TUint bandwidth_priority = (EUsbcBandwidthOUTDefault | EUsbcBandwidthINDefault);
   439     if (d_caps().iHighSpeed)
   447 	if (d_caps().iHighSpeed)
   440         {
   448 		{
   441         // If this device supports USB High-speed, then we request 64KB buffers
   449 		// If this device supports USB High-speed, then we request 64KB buffers
   442         // (otherwise the default 4KB ones will do).
   450 		// (otherwise the default 4KB ones will do).
   443         bandwidth_priority = (EUsbcBandwidthOUTPlus2 | EUsbcBandwidthINPlus2);
   451 		bandwidth_priority = (EUsbcBandwidthOUTPlus2 | EUsbcBandwidthINPlus2);
   444         // Also, tell the Protocol about it, because it might want to do some
   452 		// Also, tell the Protocol about it, because it might want to do some
   445         // optimizing too.
   453 		// optimizing too.
   446         iProtocol->ReportHighSpeedDevice();
   454 		iProtocol->ReportHighSpeedDevice();
   447         }
   455 		}
   448     ret = iLdd.SetInterface(0, ifc, bandwidth_priority);
   456 	ret = iLdd.SetInterface(0, ifc, bandwidth_priority);
   449     return ret;
   457 	return ret;
   450     }
   458 	}
       
   459 
   451 
   460 void CBulkOnlyTransportUsbcLdd::ReleaseInterface()
   452 void CBulkOnlyTransportUsbcLdd::ReleaseInterface()
   461 	{
   453     {
   462 	iLdd.ReleaseInterface(0);
   454     iLdd.ReleaseInterface(0);
   463 	}
   455     }
   464 
   456 
   465 TInt CBulkOnlyTransportUsbcLdd::StartControlInterface()
   457 TInt CBulkOnlyTransportUsbcLdd::StartControlInterface()
   466 	{
   458     {
   467 	return iControlInterface->Start();
   459     return iControlInterface->Start();
   468 	}
   460     }
   469 
   461 
   470 void CBulkOnlyTransportUsbcLdd::CancelControlInterface()
   462 void CBulkOnlyTransportUsbcLdd::CancelControlInterface()
   471 	{
   463     {
   472 	iControlInterface->Cancel();
   464     iControlInterface->Cancel();
   473 	}
   465     }
   474 
   466 
   475 void CBulkOnlyTransportUsbcLdd::ActivateDeviceStateNotifier()
   467 void CBulkOnlyTransportUsbcLdd::ActivateDeviceStateNotifier()
   476 	{
   468     {
   477     __ASSERT_DEBUG(iDeviceStateNotifier, User::Panic(KUsbMsSvrPncCat, EMsCDeviceStateNotifierNull));
   469     __ASSERT_DEBUG(iDeviceStateNotifier, User::Panic(KUsbMsSvrPncCat, EMsCDeviceStateNotifierNull));
   478 	iDeviceStateNotifier->Activate();
   470     iDeviceStateNotifier->Activate();
   479 	}
   471     }
   480 
   472 
   481 void CBulkOnlyTransportUsbcLdd::CancelDeviceStateNotifier()
   473 void CBulkOnlyTransportUsbcLdd::CancelDeviceStateNotifier()
   482 	{
   474     {
   483 	iDeviceStateNotifier->Cancel();
   475     iDeviceStateNotifier->Cancel();
   484 	}
   476     }
   485 
   477 
   486 void CBulkOnlyTransportUsbcLdd::CancelReadWriteRequests()
   478 void CBulkOnlyTransportUsbcLdd::CancelReadWriteRequests()
   487 	{
   479     {
   488 	__FNLOG("CBulkOnlyTransportUsbcLdd::CancelReadWriteRequests");
   480     iLdd.WriteCancel(InEndpoint);
   489 	iLdd.WriteCancel(InEndpoint);
   481     iLdd.ReadCancel(OutEndpoint);
   490 	iLdd.ReadCancel(OutEndpoint);
   482     }
   491 	}
       
   492 
   483 
   493 void CBulkOnlyTransportUsbcLdd::AllocateEndpointResources()
   484 void CBulkOnlyTransportUsbcLdd::AllocateEndpointResources()
   494 	{
   485     {
   495 	TUsbDeviceCaps d_caps;
   486     TUsbDeviceCaps d_caps;
   496 	TInt ret = iLdd.DeviceCaps(d_caps);
   487     TInt ret = iLdd.DeviceCaps(d_caps);
   497 	if (ret == KErrNone)
   488     if (ret == KErrNone)
   498 		{
   489         {
   499 		if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != KUsbDevCapsFeatureWord1_EndpointResourceAllocV2)
   490         if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != KUsbDevCapsFeatureWord1_EndpointResourceAllocV2)
   500 			{
   491             {
   501 				// Set up DMA if possible (errors are non-critical)
   492             // Set up DMA if possible (errors are non-critical)
   502 			TInt err = iLdd.AllocateEndpointResource(OutEndpoint, EUsbcEndpointResourceDMA);
   493             TInt err = iLdd.AllocateEndpointResource(OutEndpoint, EUsbcEndpointResourceDMA);
   503 			if (err != KErrNone)
   494             if (err != KErrNone)
   504 				{
   495                 {
   505 				__PRINT1(_L("Set DMA on OUT endpoint failed with error code: %d"), err);
   496                 OstTrace1(TRACE_SMASSSTORAGE_BOT, A1, "Set DMA on OUT endpoint failed with error code: %d", err);
   506 				}
   497                 }
   507 			err = iLdd.AllocateEndpointResource(InEndpoint, EUsbcEndpointResourceDMA);
   498             err = iLdd.AllocateEndpointResource(InEndpoint, EUsbcEndpointResourceDMA);
   508 			if (err != KErrNone)
   499             if (err != KErrNone)
   509 				{
   500                 {
   510 				__PRINT1(_L("Set DMA on IN endpoint failed with error code: %d"), err);
   501                 OstTrace1(TRACE_SMASSSTORAGE_BOT, A2, "Set DMA on IN endpoint failed with error code: %d", err);
   511 				}
   502                 }
   512 
   503 
   513 				// Set up Double Buffering if possible (errors are non-critical)
   504                 // Set up Double Buffering if possible (errors are non-critical)
   514 			err = iLdd.AllocateEndpointResource(OutEndpoint, EUsbcEndpointResourceDoubleBuffering);
   505             err = iLdd.AllocateEndpointResource(OutEndpoint, EUsbcEndpointResourceDoubleBuffering);
   515 			if (err != KErrNone)
   506             if (err != KErrNone)
   516 				{
   507                 {
   517 				__PRINT1(_L("Set Double Buffering on OUT endpoint failed with error code: %d"), err);
   508                 OstTrace1(TRACE_SMASSSTORAGE_BOT, A3, "Set Double Buffering on OUT endpoint failed with error code: %d", err);
   518 				}
   509                 }
   519 			err = iLdd.AllocateEndpointResource(InEndpoint, EUsbcEndpointResourceDoubleBuffering);
   510             err = iLdd.AllocateEndpointResource(InEndpoint, EUsbcEndpointResourceDoubleBuffering);
   520 			if (err != KErrNone)
   511             if (err != KErrNone)
   521 				{
   512                 {
   522 				__PRINT1(_L("Set Double Buffering on IN endpoint failed with error code: %d"), err);
   513                 OstTrace1(TRACE_SMASSSTORAGE_BOT, A4, "Set Double Buffering on IN endpoint failed with error code: %d", err);
   523 				}
   514                 }
   524 			}
   515             }
   525 		}
   516         }
   526 	}
   517     }
   527 
   518 
   528 TInt CBulkOnlyTransportUsbcLdd::GetDeviceStatus(TUsbcDeviceState& deviceStatus)
   519 TInt CBulkOnlyTransportUsbcLdd::GetDeviceStatus(TUsbcDeviceState& deviceStatus)
   529 	{
   520     {
   530 	return iLdd.DeviceStatus(deviceStatus);
   521     return iLdd.DeviceStatus(deviceStatus);
   531 	}
   522     }
   532 
   523 
   533 void CBulkOnlyTransportUsbcLdd::FlushData()
   524 void CBulkOnlyTransportUsbcLdd::FlushData()
   534 	{
   525     {
   535 	TInt bytes;
   526     TInt bytes;
   536 	const TInt err = iLdd.QueryReceiveBuffer(OutEndpoint, bytes);
   527     const TInt err = iLdd.QueryReceiveBuffer(OutEndpoint, bytes);
   537 	if (err != KErrNone || bytes <= 0)
   528     if (err != KErrNone || bytes <= 0)
   538 		{
   529         {
   539 		__PRINT1(_L("Error: err=%d bytes=%d"), bytes);
   530         OstTraceExt2(TRACE_SMASSSTORAGE_BOT, B1, "ERROR: err=%d bytes=0x%x", err, bytes);
   540 		}
   531         }
   541 	else
   532     else
   542 		{
   533         {
   543 		__PRINT1(_L("RxBuffer has %d bytes"), bytes);
   534         OstTrace1(TRACE_SMASSSTORAGE_BOT1, B2, "RxBuffer has %d bytes", bytes);
   544 		ReadAndDiscardData(bytes);
   535         ReadAndDiscardData(bytes);
   545 		}
   536         }
   546 	}
   537     }
   547 /**
   538 /**
   548  * Read out rest data from OutEndpoint and discard them
   539  * Read out rest data from OutEndpoint and discard them
   549  */
   540  */
   550 void CBulkOnlyTransportUsbcLdd::ReadAndDiscardData(TInt aBytes)
   541 void CBulkOnlyTransportUsbcLdd::ReadAndDiscardData(TInt aBytes)
   551 	{
   542     {
   552 	__FNLOG("CBulkOnlyTransportUsbcLdd::ReadAndDiscardData");
   543     iDiscardBuf.SetMax();
   553 	iDiscardBuf.SetMax();
   544     const TUint bufsize = static_cast<TUint>(iDiscardBuf.Length());
   554 	const TUint bufsize = static_cast<TUint>(iDiscardBuf.Length());
   545     TRequestStatus status;
   555 	TRequestStatus status;
   546     while (aBytes > 0)
   556 	while (aBytes > 0)
   547         {
   557 		{
   548         OstTrace1(TRACE_SMASSSTORAGE_BOT1, C1, "Bytes still to be read: 0x%x", aBytes);
   558 		__PRINT1(_L("Bytes still to be read: %d\n"), aBytes);
   549         iLdd.ReadOneOrMore(status, OutEndpoint, iDiscardBuf, bufsize);
   559 		iLdd.ReadOneOrMore(status, OutEndpoint, iDiscardBuf, bufsize);
   550         User::WaitForRequest(status);
   560 		User::WaitForRequest(status);
   551         TInt err = status.Int();
   561 		TInt err = status.Int();
   552         if (err != KErrNone)
   562 		if (err != KErrNone)
   553             {
   563 			{
   554             // Bad.
   564 			// Bad.
   555             break;
   565 			break;
   556             }
   566 			}
   557         aBytes -= iDiscardBuf.Length();
   567 		aBytes -= iDiscardBuf.Length();
   558         }
   568 		}
   559     }
   569 	}
       
   570 
   560 
   571 /**
   561 /**
   572 Called by the protocol to determine how many bytes of data are available in the read buffer.
   562 Called by the protocol to determine how many bytes of data are available in the read buffer.
   573 
   563 
   574 @return The number of bytes available in the read buffer
   564 @return The number of bytes available in the read buffer
   575 */
   565 */
   576 TInt CBulkOnlyTransportUsbcLdd::BytesAvailable()
   566 TInt CBulkOnlyTransportUsbcLdd::BytesAvailable()
   577 	{
   567     {
   578 	TInt bytes = 0;
   568     TInt bytes = 0;
   579 	TInt err = iLdd.QueryReceiveBuffer(OutEndpoint, bytes);
   569     TInt err = iLdd.QueryReceiveBuffer(OutEndpoint, bytes);
   580 	if (err != KErrNone)
   570     if (err != KErrNone)
   581 		bytes = 0;
   571         bytes = 0;
   582 	return bytes;
   572     return bytes;
   583 	}
   573     }
   584 
   574 
   585 
   575 
   586 void CBulkOnlyTransportUsbcLdd::StallEndpointAndWaitForClear()
   576 void CBulkOnlyTransportUsbcLdd::StallEndpointAndWaitForClear()
   587 	{
   577     {
   588 	__FNLOG("CBulkOnlyTransportUsbcLdd::StallEndpointAndWaitForClear");
   578     // Now stall this endpoint
   589 
   579     OstTrace1(TRACE_SMASSSTORAGE_BOT, D1, "Stalling endpoint %d", InEndpoint);
   590 	// Now stall this endpoint
   580     TInt r = iLdd.HaltEndpoint(InEndpoint);
   591 	__PRINT1(_L("Stalling endpoint %d"), InEndpoint);
   581     if (r != KErrNone)
   592 	TInt r = iLdd.HaltEndpoint(InEndpoint);
   582         {
   593 	if (r != KErrNone)
   583         OstTraceExt2(TRACE_SMASSSTORAGE_BOT, D2, "Error: stalling ep %d failed: %d", InEndpoint, r);
   594 		{
   584         }
   595 		__PRINT2(_L("Error: stalling ep %d failed: %d"), InEndpoint, r);
   585     TEndpointState ep_state;
   596 		}
   586     TInt i = 0;
   597 	TEndpointState ep_state;
   587     do
   598 	TInt i = 0;
   588         {
   599 	do
   589         // Wait for 10ms before checking the ep status
   600 		{
   590         User::After(10000);
   601 		// Wait for 10ms before checking the ep status
   591         iLdd.EndpointStatus(InEndpoint, ep_state);
   602 		User::After(10000);
   592         if (++i >= 550)
   603 		iLdd.EndpointStatus(InEndpoint, ep_state);
   593             {
   604 		if (++i >= 550)
   594             // 5.5 secs should be enough (see 9.2.6.1 Request Processing Timing)
   605 			{
   595             OstTrace1(TRACE_SMASSSTORAGE_BOT, D3, "Error: Checked for ep %d de-stall for 5.5s - giving up now", InEndpoint);
   606 			// 5.5 secs should be enough (see 9.2.6.1 Request Processing Timing)
   596             // We can now only hope for a Reset Recovery
   607 			__PRINT1(_L("Error: Checked for ep %d de-stall for 5.5s - giving up now"), InEndpoint);
   597             return;
   608 			// We can now only hope for a Reset Recovery
   598             }
   609 			return;
   599         } while ((ep_state == EEndpointStateStalled) && iStarted);
   610 			}
   600     OstTraceExt2(TRACE_SMASSSTORAGE_BOT, D4, "Checked for ep %d de-stall: %d time(s)", InEndpoint, i);
   611 		} while ((ep_state == EEndpointStateStalled) && iStarted);
   601     }
   612 	__PRINT2(_L("Checked for ep %d de-stall: %d time(s)"), InEndpoint, i);
       
   613 	}
       
   614 
   602 
   615 
   603 
   616 /**
   604 /**
   617 Read CBW data (KCbwLength) from the host into the read buffer.
   605 Read CBW data (KCbwLength) from the host into the read buffer.
   618 */
   606 */
   619 void CBulkOnlyTransportUsbcLdd::ReadCBW()
   607 void CBulkOnlyTransportUsbcLdd::ReadCBW()
   620 	{
   608     {
   621 	__FNLOG("CBulkOnlyTransportUsbcLdd::ReadCBW");
   609     if (IsActive())
   622 	if (IsActive())
   610         {
   623 		{
   611         __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
   624 		__PRINT(_L("Still active\n"));
   612         return;
   625 		__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
   613         }
   626 		return;
   614 
   627 		}
   615     iCbwBuf.SetMax();
   628 
   616     iLdd.ReadUntilShort(iStatus, OutEndpoint, iCbwBuf, KCbwLength);
   629 	iCbwBuf.SetMax();
   617 
   630 	iLdd.ReadUntilShort(iStatus, OutEndpoint, iCbwBuf, KCbwLength);
   618     iCurrentState = EWaitForCBW;
   631 
   619     SetActive();
   632 	iCurrentState = EWaitForCBW;
   620     }
   633 	SetActive();
       
   634 	}
       
   635 
   621 
   636 void CBulkOnlyTransportUsbcLdd::ExpireData(TAny* /*aAddress*/)
   622 void CBulkOnlyTransportUsbcLdd::ExpireData(TAny* /*aAddress*/)
   637 	{
   623     {
   638 	// Intentionally left blank
   624     // Intentionally left blank
   639 	}
   625     }
   640 
   626 
   641 void CBulkOnlyTransportUsbcLdd::ProcessCbwEvent()
   627 void CBulkOnlyTransportUsbcLdd::ProcessCbwEvent()
   642 	{
   628     {
   643 	DecodeCBW();
   629     DecodeCBW();
   644 	}
   630     }
   645 
   631 
   646 
   632 
   647 /**
   633 /**
   648 Request data form the host for the protocol
   634 Request data form the host for the protocol
   649 
   635 
   650 @param aLength amount of data (in bytes) to be received from the host
   636 @param aLength amount of data (in bytes) to be received from the host
   651 */
   637 */
   652 void CBulkOnlyTransportUsbcLdd::ReadData(TUint aLength)
   638 void CBulkOnlyTransportUsbcLdd::ReadData(TUint aLength)
   653 	{
   639     {
   654 	__FNLOG("CBulkOnlyTransportUsbcLdd::ReadData");
   640     if (IsActive())
   655 	if (IsActive())
   641         {
   656 		{
   642         __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
   657 		__PRINT(_L("Still active\n"));
   643         return;
   658 		__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
   644         }
   659 		return;
   645 
   660 		}
   646     SetReadDataBufPtr(aLength);
   661 	
   647     iLdd.Read(iStatus, OutEndpoint, iReadBufPtr, aLength);
   662 	SetReadDataBufPtr(aLength);
   648 
   663 	iLdd.Read(iStatus, OutEndpoint, iReadBufPtr, aLength);
   649     iCurrentState = EReadingData;
   664 
   650     SetActive();
   665 	iCurrentState = EReadingData;
   651     }
   666 	SetActive();
       
   667 	}
       
   668 
   652 
   669 void CBulkOnlyTransportUsbcLdd::WriteUsb(TRequestStatus& aStatus, TPtrC8& aDes, TUint aLength, TBool aZlpRequired)
   653 void CBulkOnlyTransportUsbcLdd::WriteUsb(TRequestStatus& aStatus, TPtrC8& aDes, TUint aLength, TBool aZlpRequired)
   670 	{
   654     {
   671 	iLdd.Write(aStatus, InEndpoint, aDes, aLength, aZlpRequired);
   655     iLdd.Write(aStatus, InEndpoint, aDes, aLength, aZlpRequired);
   672 	}
   656     }
   673 
   657 
   674 void CBulkOnlyTransportUsbcLdd::SetCbwPtr()
   658 void CBulkOnlyTransportUsbcLdd::SetCbwPtr()
   675 	{
   659     {
   676 	iCbwBufPtr.Set(iCbwBuf.Ptr(), iCbwBuf.Length());
   660     iCbwBufPtr.Set(iCbwBuf.Ptr(), iCbwBuf.Length());
   677 	}
   661     }
   678 
   662 
   679 TPtr8& CBulkOnlyTransportUsbcLdd::SetCommandBufPtr(TUint aLength)
   663 TPtr8& CBulkOnlyTransportUsbcLdd::SetCommandBufPtr(TUint aLength)
   680 	{
   664     {
   681 	iCommandBufPtr.Set((TUint8*) iCommandBuf.Ptr(), aLength, aLength );
   665     iCommandBufPtr.Set((TUint8*) iCommandBuf.Ptr(), aLength, aLength );
   682 	return iCommandBufPtr;
   666     return iCommandBufPtr;
   683 	}
   667     }
   684 
   668 
   685 void CBulkOnlyTransportUsbcLdd::SetReadDataBufPtr(TUint aLength) //Write10(Host->Device
   669 void CBulkOnlyTransportUsbcLdd::SetReadDataBufPtr(TUint aLength) //Write10(Host->Device
   686 	{
   670     {
   687 	if (iSwap)
   671     iBulkMm.GetNextTransferBuffer(aLength, iReadBufPtr);
   688 		{
   672         }
   689 		iDataBuf1.SetLength(aLength);
   673 
   690 		iReadBufPtr.Set(iDataBuf1.LeftTPtr(iDataBuf1.Length()));
       
   691 		iSwap = EFalse;
       
   692 		}
       
   693 	else
       
   694 		{
       
   695 		iDataBuf2.SetLength(aLength);
       
   696 		iReadBufPtr.Set(iDataBuf2.LeftTPtr(iDataBuf2.Length()));
       
   697 		iSwap = ETrue;
       
   698 		}
       
   699 	}
       
   700 
   674 
   701 TPtr8& CBulkOnlyTransportUsbcLdd::SetDataBufPtr() //Read10(Device->Host)
   675 TPtr8& CBulkOnlyTransportUsbcLdd::SetDataBufPtr() //Read10(Device->Host)
   702 	{
   676     {
   703 	if (iSwap)
   677     iBulkMm.GetNextTransferBuffer(iDataBufPtr);
   704 		{
   678     return iDataBufPtr;
   705 		iDataBufPtr.Set((TUint8*) iDataBuf1.Ptr(), KMaxBufSize, KMaxBufSize);
   679     }
   706 		iSwap = EFalse;
       
   707 		}
       
   708 	else
       
   709 		{
       
   710 		iDataBufPtr.Set((TUint8*) iDataBuf2.Ptr(), KMaxBufSize, KMaxBufSize);
       
   711 		iSwap = ETrue;
       
   712 		}
       
   713 	return iDataBufPtr;
       
   714 	}
       
   715 
   680 
   716 void CBulkOnlyTransportUsbcLdd::SetPaddingBufPtr(TUint aLength)
   681 void CBulkOnlyTransportUsbcLdd::SetPaddingBufPtr(TUint aLength)
   717 	{
   682     {
   718 	iPaddingBufPtr.Set((TUint8*) iBuf.Ptr(), aLength, aLength );
   683     iPaddingBufPtr.Set((TUint8*) iBuf.Ptr(), aLength, aLength );
   719 	}
   684     }
   720 
   685 
   721 
   686 
   722 void CBulkOnlyTransportUsbcLdd::SetCswBufPtr(TUint aLength)
   687 void CBulkOnlyTransportUsbcLdd::SetCswBufPtr(TUint aLength)
   723 	{
   688     {
   724 	iCswBufPtr.Set((TUint8*) iCswBuf.Ptr(), aLength, aLength );
   689     iCswBufPtr.Set((TUint8*) iCswBuf.Ptr(), aLength, aLength );
   725 	}
   690     }
   726 
   691 
   727 void CBulkOnlyTransportUsbcLdd::ProcessReadingDataEvent()
   692 void CBulkOnlyTransportUsbcLdd::ProcessReadingDataEvent()
   728 	{
   693     {
   729 	TInt ret = KErrNone;
   694     TInt ret = KErrNone;
   730     FOREVER
   695     FOREVER
   731 		{
   696         {
   732 		if (iReadSetUp)
   697         if (iReadSetUp)
   733 			{
   698             {
   734 			ret = iProtocol->ReadComplete(KErrNone);
   699             ret = iProtocol->ReadComplete(KErrNone);
   735 			}
   700             }
   736 
   701 
   737 		TUint deviceDataLength = iBufSize; // This is the amount (maximum in case of SC Ldd) to be read next.
   702         TUint deviceDataLength = iBufSize; // This is the amount (maximum in case of SC Ldd) to be read next.
   738 
   703 
   739 		if(ret == KErrCompletion)
   704         if(ret == KErrCompletion)
   740 			{
   705             {
   741 			// The protocol has indicated with KErrCompletion that sufficient
   706             // The protocol has indicated with KErrCompletion that sufficient
   742 			// data is available in the buffer to process the transfer immediately.
   707             // data is available in the buffer to process the transfer immediately.
   743 
       
   744 			iDataResidue -= iReadBufPtr.Length();
       
   745 			SetReadDataBufPtr(deviceDataLength);
       
   746 
       
   747 			iLdd.Read(iStatus, OutEndpoint, iReadBufPtr, deviceDataLength);
       
   748 			User::WaitForRequest(iStatus);
       
   749 			if (iStatus != KErrNone)
       
   750 				{
       
   751 				// An error occurred - halt endpoints for reset recovery
       
   752 				__PRINT1(_L("Error %d in EReadingData, halt endpoints \n"), iStatus.Int());
       
   753 				SetPermError();
       
   754 				return;
       
   755 				}
       
   756 			}
       
   757 		else if(ret == KErrNotReady)
       
   758 			{
       
   759 			// The protocol has indicated with KErrNotReady that insufficient
       
   760 			// data is available in the buffer, so should wait for it to arrive
       
   761 
   708 
   762             iDataResidue -= iReadBufPtr.Length();
   709             iDataResidue -= iReadBufPtr.Length();
   763 			ReadData(deviceDataLength);
   710             SetReadDataBufPtr(deviceDataLength);
   764 			break;
   711 
   765 			}
   712             iLdd.Read(iStatus, OutEndpoint, iReadBufPtr, deviceDataLength);
   766 		else
   713             User::WaitForRequest(iStatus);
   767 			{
   714             if (iStatus != KErrNone)
   768 			// The protocol has indicated that transfer is
   715                 {
   769 			// complete, so send the CSW response to the host.
   716                 // An error occurred - halt endpoints for reset recovery
   770 			iDataResidue -= iReadBufPtr.Length();
   717                 OstTrace1(TRACE_SMASSSTORAGE_BOT, E1, "Error %d in EReadingData, halt endpoints", iStatus.Int());
   771 			iReadSetUp = EFalse;
   718                 SetPermError();
   772 
   719                 return;
   773 			if (ret != KErrNone)
   720                 }
   774 				{
   721             }
   775 				iCmdStatus = ECommandFailed;
   722         else if(ret == KErrNotReady)
   776 				}
   723             {
   777 
   724             // The protocol has indicated with KErrNotReady that insufficient
   778 			if (iDataResidue)
   725             // data is available in the buffer, so should wait for it to arrive
   779 				{
   726 
   780 				__PRINT(_L("Discarding residue"));
   727             iDataResidue -= iReadBufPtr.Length();
   781 				// we have to read as much data as available that host PC sends;
   728             ReadData(deviceDataLength);
   782 				// otherwise, bulk-out endpoint will need to keep sending NAK back.
   729             break;
   783 				ReadAndDiscardData(iDataResidue);
   730             }
   784 				}
   731         else
   785 			SendCSW(iCbwTag, iDataResidue, iCmdStatus);
   732             {
   786 			break;
   733             // The protocol has indicated that transfer is
   787 			}
   734             // complete, so send the CSW response to the host.
   788 		}
   735             iDataResidue -= iReadBufPtr.Length();
   789 
   736             iReadSetUp = EFalse;
   790 	}
   737 
       
   738             if (ret != KErrNone)
       
   739                 {
       
   740                 iCmdStatus = ECommandFailed;
       
   741                 }
       
   742 
       
   743             if (iDataResidue)
       
   744                 {
       
   745                 OstTrace0(TRACE_SMASSSTORAGE_BOT, E2, "Discarding residue");
       
   746                 // we have to read as much data as available that host PC sends;
       
   747                 // otherwise, bulk-out endpoint will need to keep sending NAK back.
       
   748                 ReadAndDiscardData(iDataResidue);
       
   749                 }
       
   750             SendCSW(iCbwTag, iDataResidue, iCmdStatus);
       
   751             break;
       
   752             }
       
   753         }
       
   754 
       
   755     }
   791 
   756 
   792 void CBulkOnlyTransportUsbcLdd::DiscardData(TUint aLength)
   757 void CBulkOnlyTransportUsbcLdd::DiscardData(TUint aLength)
   793 	{
   758     {
   794 	iBuf.SetLength(KBOTMaxBufSize);
   759     iBuf.SetLength(KBOTMaxBufSize);
   795 	TUint c = 0;
   760     TUint c = 0;
   796 	TRequestStatus status;
   761     TRequestStatus status;
   797 	while (c < aLength)
   762     while (c < aLength)
   798 		{
   763         {
   799 		TInt len;
   764         TInt len;
   800 		if (aLength - c >  KBOTMaxBufSize)
   765         if (aLength - c >  KBOTMaxBufSize)
   801 			{
   766             {
   802 			len = KBOTMaxBufSize;
   767             len = KBOTMaxBufSize;
   803 			}
   768             }
   804 		else
   769         else
   805 			{
   770             {
   806 			len = aLength - c;
   771             len = aLength - c;
   807 			}
   772             }
   808 
   773 
   809 		iLdd.Read(status, OutEndpoint, iBuf, len);
   774         iLdd.Read(status, OutEndpoint, iBuf, len);
   810 		User::WaitForRequest(status);
   775         User::WaitForRequest(status);
   811 		c +=  KBOTMaxBufSize;
   776         c +=  KBOTMaxBufSize;
   812 		}
   777         }
   813 	}
   778     }
   814 
   779 
   815 void CBulkOnlyTransportUsbcLdd::WriteToClient(TUint aLength)
   780 void CBulkOnlyTransportUsbcLdd::WriteToClient(TUint aLength)
   816 	{
   781     {
   817 	SetDataBufPtr();
   782     SetDataBufPtr();
   818 	iLdd.Read(iStatus, OutEndpoint, iDataBufPtr, aLength);
   783     iLdd.Read(iStatus, OutEndpoint, iDataBufPtr, aLength);
   819     User::WaitForRequest(iStatus);
   784     User::WaitForRequest(iStatus);
   820     iProtocol->ReadComplete(KErrGeneral);
   785     iProtocol->ReadComplete(KErrGeneral);
   821 	}
   786     }
   822 
   787 
   823 #ifdef MSDC_MULTITHREADED
   788 #ifdef MSDC_MULTITHREADED
   824 void CBulkOnlyTransportUsbcLdd::GetBufferPointers(TPtr8& aDes1, TPtr8& aDes2)
   789 void CBulkOnlyTransportUsbcLdd::GetBufferPointers(TPtr8& aDes1, TPtr8& aDes2)
   825 	{
   790     {
   826 	aDes1.Set((TUint8*) iDataBuf1.Ptr(), KMaxBufSize, KMaxBufSize);
   791     aDes1.Set(iBulkMm.Buf1(), KMaxBufSize, KMaxBufSize);
   827 	aDes2.Set((TUint8*) iDataBuf2.Ptr(), KMaxBufSize, KMaxBufSize);
   792     aDes2.Set(iBulkMm.Buf2(), KMaxBufSize, KMaxBufSize);
   828 	}
   793     }
   829 #endif
   794 #endif
   830 
   795 
   831 void CBulkOnlyTransportUsbcLdd::Activate(TRequestStatus& aStatus, TUint& aDeviceState)
   796 void CBulkOnlyTransportUsbcLdd::Activate(TRequestStatus& aStatus, TUint& aDeviceState)
   832     {
   797     {
   833 	iLdd.AlternateDeviceStatusNotify(aStatus, aDeviceState);
   798     iLdd.AlternateDeviceStatusNotify(aStatus, aDeviceState);
   834     }
   799     }
   835 
   800 
   836 
   801 
   837 void CBulkOnlyTransportUsbcLdd::Cancel()
   802 void CBulkOnlyTransportUsbcLdd::Cancel()
   838     {
   803     {
   839 	iLdd.AlternateDeviceStatusNotifyCancel();
   804     iLdd.AlternateDeviceStatusNotifyCancel();
   840     }
   805     }
   841 
   806 
   842 
   807 
   843 
   808 
   844 
   809