userlibandfileserver/fileserver/shostmassstorage/server/transport/cbulkonlytransport.cpp
changeset 0 a41df078684a
child 31 56f325a607ea
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2008-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 the License "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  @internalTechnology
       
    19 */
       
    20 
       
    21 #include <e32base.h>
       
    22 #include <e32base_private.h>
       
    23 #include <d32usbdi_hubdriver.h>
       
    24 #include <d32usbdi.h>
       
    25 #include <d32otgdi.h>
       
    26 #include <d32usbdescriptors.h>
       
    27 #include <d32usbtransfers.h>
       
    28 #ifdef MASSSTORAGE_PUBLISHER
       
    29 #include <e32property.h>
       
    30 #endif
       
    31 #include "botmsctypes.h"
       
    32 #include "msctypes.h"
       
    33 #include "mscutils.h"
       
    34 #include "mtransport.h"
       
    35 #include "mprotocol.h"
       
    36 #include "cusbifacehandler.h"
       
    37 #include "cbulkonlytransport.h"
       
    38 #include "debug.h"
       
    39 #include "msdebug.h"
       
    40 
       
    41 CBulkOnlyTransport::CBulkOnlyTransport()
       
    42 :	iBulkOutCbwTd(KCbwPacketSize),
       
    43 	iBulkDataTd(KResponsePacketSize),
       
    44 	iBulkInCswTd(KCswPacketSize)
       
    45 	{
       
    46     __MSFNLOG
       
    47 	}
       
    48 
       
    49 CBulkOnlyTransport::~CBulkOnlyTransport()
       
    50 	{
       
    51     __MSFNLOG
       
    52 	delete iUsbInterfaceHandler;
       
    53 	UnInitialiseTransport();
       
    54 	iInterface.Close();
       
    55 	}
       
    56 
       
    57 /**
       
    58 Create CBulkOnlyTransport object.
       
    59 
       
    60 @param aInterfaceId The interface ID of the device
       
    61 
       
    62 @return CBulkOnlyTransport* Pointer to the created object
       
    63 */
       
    64 CBulkOnlyTransport* CBulkOnlyTransport::NewL(TUint aInterfaceId)
       
    65 	{
       
    66     __MSFNSLOG
       
    67 	CBulkOnlyTransport* transport = new (ELeave) CBulkOnlyTransport();
       
    68 	CleanupStack::PushL(transport);
       
    69     transport->ConstructL(aInterfaceId);
       
    70     CleanupStack::Pop(transport);
       
    71 	return transport;
       
    72 	}
       
    73 
       
    74 
       
    75 void CBulkOnlyTransport::ConstructL(TUint aInterfaceId)
       
    76     {
       
    77     __MSFNSLOG
       
    78 	User::LeaveIfError(iInterface.Open(aInterfaceId));
       
    79 	iUsbInterfaceHandler = CUsbInterfaceHandler::NewL(iInterface);
       
    80 	InitialiseTransport();
       
    81     }
       
    82 
       
    83 
       
    84 void CBulkOnlyTransport::Resume()
       
    85 	{
       
    86     __MSFNSLOG
       
    87 	__BOTPRINT(_L("BOT RESUME"));
       
    88 	User::AfterHighRes(1000 * 1000); 	//	DEF126984 - we need delay here in order for the usb to resume properly in the case of cancelling a suspend
       
    89 	iInterface.CancelPermitSuspend();
       
    90 	User::AfterHighRes(1000 * 1000); 	//	DEF126984 - we need delay here in order for the usb to resume properly in the case of cancelling a suspend
       
    91 	}
       
    92 
       
    93 void CBulkOnlyTransport::Suspend(TRequestStatus &aStatus)
       
    94 	{
       
    95     __MSFNSLOG
       
    96 	__BOTPRINT(_L("BOT SUSPEND"));
       
    97 //	iInterface.PermitRemoteWakeup(ETrue);
       
    98 	iInterface.PermitSuspendAndWaitForResume(aStatus);
       
    99 	}
       
   100 
       
   101 TInt CBulkOnlyTransport::InitialiseTransport()
       
   102 	{
       
   103     __MSFNLOG
       
   104 	TInt BulkOutEpAddr;
       
   105 	TInt BulkInEpAddr;
       
   106 	const TUint8 KEpDirectionIn = 0x80;
       
   107 	const TUint8 KEpDirectionOut = 0x00;
       
   108 	const TUint8 KTransferTypeBulk = 0x02;
       
   109 
       
   110 	GetEndpointAddress(iInterface,0,KTransferTypeBulk,KEpDirectionOut,BulkOutEpAddr);
       
   111 	GetEndpointAddress(iInterface,0,KTransferTypeBulk,KEpDirectionIn,BulkInEpAddr);
       
   112 	iInterface.OpenPipeForEndpoint(iBulkPipeOut, BulkOutEpAddr, EFalse);
       
   113 	iInterface.OpenPipeForEndpoint(iBulkPipeIn, BulkInEpAddr, EFalse);
       
   114 
       
   115 	if (iInterface.RegisterTransferDescriptor(iBulkOutCbwTd) != KErrNone ||
       
   116 			iInterface.RegisterTransferDescriptor(iBulkDataTd) != KErrNone ||
       
   117 					iInterface.RegisterTransferDescriptor(iBulkInCswTd) != KErrNone)
       
   118         {
       
   119 		return KErrGeneral;
       
   120         }
       
   121 
       
   122 	if (iInterface.InitialiseTransferDescriptors() != KErrNone)
       
   123         {
       
   124 		return KErrGeneral;
       
   125         }
       
   126 	return KErrNone;
       
   127 	}
       
   128 
       
   129 
       
   130 void CBulkOnlyTransport::UnInitialiseTransport()
       
   131 	{
       
   132     __MSFNLOG
       
   133 	iBulkPipeOut.Close();
       
   134 	iBulkPipeIn.Close();
       
   135 	}
       
   136 
       
   137 TInt CBulkOnlyTransport::GetEndpointAddress(RUsbInterface& aUsbInterface,
       
   138                                             TInt aInterfaceSetting,
       
   139                                             TUint8 aTransferType,
       
   140                                             TUint8 aDirection,
       
   141                                             TInt& aEndpointAddress)
       
   142 	{
       
   143     __MSFNLOG
       
   144 	TUsbInterfaceDescriptor alternateInterfaceDescriptor;
       
   145 
       
   146 	if (aUsbInterface.GetAlternateInterfaceDescriptor(aInterfaceSetting, alternateInterfaceDescriptor))
       
   147 		{
       
   148 		__BOTPRINT1(_L("GetEndpointAddress : <Error> Unable to get alternate interface (%x) descriptor"),aInterfaceSetting);
       
   149 		return KErrGeneral;
       
   150 		}
       
   151 
       
   152 	TUsbGenericDescriptor* descriptor = alternateInterfaceDescriptor.iFirstChild;
       
   153 
       
   154 	while (descriptor)
       
   155 		{
       
   156 		TUsbEndpointDescriptor* endpoint = TUsbEndpointDescriptor::Cast(descriptor);
       
   157 		if (endpoint)
       
   158 			{
       
   159 			if ((endpoint->Attributes() & aTransferType) == aTransferType)
       
   160 				{
       
   161 				// Found the endpoint address
       
   162 				if ( (endpoint->EndpointAddress() & 0x80) == aDirection)
       
   163 					{
       
   164 					aEndpointAddress = endpoint->EndpointAddress();
       
   165 					__BOTPRINT(_L("GetEndpointAddress : Endpoint address found"));
       
   166 					return KErrNone;
       
   167 					}
       
   168 				}
       
   169 			}
       
   170 		descriptor = descriptor->iNextPeer;
       
   171 		}
       
   172 
       
   173 	// Unable to find the endpoint address
       
   174 	__BOTPRINT(_L("GetEndpointAddress : Unable to find endpoint address matching the specified attributes"));
       
   175 	return KErrNotFound;
       
   176 	}
       
   177 
       
   178 void CBulkOnlyTransport::GetMaxLun(TLun* aMaxLun, const RMessage2& aMessage)
       
   179 	{
       
   180     __MSFNLOG
       
   181 	iUsbInterfaceHandler->GetMaxLun(aMaxLun, aMessage);
       
   182 	}
       
   183 
       
   184 TInt CBulkOnlyTransport::Reset()
       
   185 	{
       
   186     __MSFNLOG
       
   187 	RUsbInterface::TUsbTransferRequestDetails reqDetails;
       
   188 	_LIT8(KNullDesC8,"");
       
   189 
       
   190 	reqDetails.iRequestType = 0x21;
       
   191 	reqDetails.iRequest = 0xFF;
       
   192 	reqDetails.iValue = 0x0000;
       
   193 	reqDetails.iIndex = 0x0000;
       
   194 	reqDetails.iFlags = 0x04;		// Short transfer OK
       
   195 
       
   196 	iInterface.Ep0Transfer(reqDetails, KNullDesC8, (TDes8 &) KNullDesC8, iStatus);
       
   197 	User::WaitForRequest(iStatus);
       
   198     __BOTPRINT1(_L("BOT RESET[%d]"), iStatus.Int());
       
   199 
       
   200 	if (iStatus.Int() != KErrNone)
       
   201         {
       
   202 		return KErrGeneral;
       
   203         }
       
   204 
       
   205 	return KErrNone;
       
   206 	}
       
   207 
       
   208 void CBulkOnlyTransport::DoResetRecovery()
       
   209 	{
       
   210     __MSFNLOG
       
   211 
       
   212     __BOTPRINT(_L("BOT RESET RECOVERY"));
       
   213 #ifdef MASSSTORAGE_PUBLISHER
       
   214     TMsPublisher publisher(TMsPublisher::KBotResetProperty);
       
   215 #endif
       
   216 	Reset();
       
   217 	iBulkPipeIn.ClearRemoteStall();
       
   218 	iBulkPipeOut.ClearRemoteStall();
       
   219 	}
       
   220 
       
   221 
       
   222 void CBulkOnlyTransport::SendCbwL(const MClientCommandServiceReq* aReq,
       
   223                                   TBotCbw::TCbwDirection aDirection,
       
   224                                   TUint32 aTransferLength)
       
   225 	{
       
   226     __MSFNLOG
       
   227     __BOTPRINT1(_L("Cbw Tag=0x%x"), iCbwTag);
       
   228 
       
   229 	iCbw.SetTag(iCbwTag++);
       
   230     iCbw.SetDataTransferLength(aTransferLength);
       
   231     iCbw.SetDataTransferDirection(aDirection);
       
   232     iCbw.SetLun(iLun);
       
   233 
       
   234     TPtr8 buf = iBulkOutCbwTd.WritableBuffer();
       
   235     iCbw.EncodeL(buf, aReq);
       
   236 
       
   237     iBulkOutCbwTd.SaveData(buf.Length());
       
   238     iBulkPipeOut.Transfer(iBulkOutCbwTd, iStatus);
       
   239     User::WaitForRequest(iStatus);
       
   240 
       
   241 	TInt r = iStatus.Int();
       
   242     if (r != KErrNone)
       
   243         {
       
   244 		if (r == KErrUsbStalled)
       
   245             {
       
   246             __BOTPRINT(_L("Cbw: BulkOut stalled"));
       
   247             DoResetRecovery();
       
   248             }
       
   249 		__BOTPRINT1(_L("Usb transfer error %d"),r);
       
   250 		User::Leave(KErrGeneral);
       
   251         }
       
   252 	}
       
   253 
       
   254 
       
   255 void CBulkOnlyTransport::ReceiveCswL()
       
   256 	{
       
   257     __MSFNLOG
       
   258 	iBulkInCswTd.SaveData(KCswPacketSize);
       
   259 	iBulkPipeIn.Transfer(iBulkInCswTd, iStatus);
       
   260 	User::WaitForRequest(iStatus);
       
   261 
       
   262 	TInt r = iStatus.Int();
       
   263 	if (r != KErrNone)
       
   264         {
       
   265 		if (r == KErrUsbStalled)
       
   266 			{
       
   267             __BOTPRINT(_L("Csw: Clearing BulkIn stall"));
       
   268 			iBulkPipeIn.ClearRemoteStall();
       
   269 			iBulkInCswTd.SaveData(KCswPacketSize);
       
   270 			iBulkPipeIn.Transfer(iBulkInCswTd, iStatus);
       
   271 			User::WaitForRequest(iStatus);
       
   272 #ifdef MASSSTORAGE_PUBLISHER
       
   273             TMsPublisher publisher(TMsPublisher::KStallProperty);
       
   274 #endif
       
   275 			r = iStatus.Int();
       
   276 			if (r == KErrUsbStalled)
       
   277                 {
       
   278 				__BOTPRINT(_L("Csw: BulkIn stalled"));
       
   279 				DoResetRecovery();
       
   280                 }
       
   281 			}
       
   282 		// Handle other usb error and retry failures
       
   283 		if (r != KErrNone)
       
   284 			{
       
   285 			__BOTPRINT1(_L("Usb transfer error %d"), r);
       
   286 			User::Leave(KErrGeneral);
       
   287 			}
       
   288         }
       
   289 
       
   290 	TPtrC8 data = iBulkInCswTd.Buffer();
       
   291 	r = iCsw.Decode(data);
       
   292     if (r != KErrNone)
       
   293         {
       
   294         __BOTPRINT(_L("Csw: Invalid"));
       
   295         DoResetRecovery();
       
   296         User::Leave(KErrGeneral);
       
   297         }
       
   298 	}
       
   299 
       
   300 
       
   301 TInt CBulkOnlyTransport::SendControlCmdL(const MClientCommandServiceReq* aCommand)
       
   302 	{
       
   303     __MSFNLOG
       
   304     SendCbwL(aCommand, TBotCbw::EDataOut, 0);
       
   305     ReceiveCswL();
       
   306     return ProcessZeroTransferL();
       
   307 	}
       
   308 
       
   309 
       
   310 TInt CBulkOnlyTransport::SendControlCmdL(const MClientCommandServiceReq* aCommand,
       
   311                                          MClientCommandServiceResp* aResp)
       
   312 	{
       
   313     __MSFNLOG
       
   314 
       
   315 	SendCbwL(aCommand, TBotCbw::EDataIn, aResp->DataLength());
       
   316 
       
   317 	if (aResp->DataLength() > KResponsePacketSize)
       
   318         {
       
   319 		__BOTPRINT(_L("Control command response length not supported"));
       
   320 		User::Leave(KErrGeneral);
       
   321         }
       
   322 
       
   323 	iBulkDataTd.SaveData(KResponsePacketSize);
       
   324 	iBulkPipeIn.Transfer(iBulkDataTd, iStatus);
       
   325 	User::WaitForRequest(iStatus);
       
   326 	TInt r = iStatus.Int();
       
   327 	if (r != KErrNone)
       
   328         {
       
   329 		if (r != KErrUsbStalled)
       
   330 			{
       
   331 			__BOTPRINT1(_L("Usb transfer error %d"),r);
       
   332 			User::Leave(KErrGeneral);
       
   333 			}
       
   334 		__BOTPRINT(_L("SendControlCmdL ClearRemoteStall"));
       
   335 		iBulkPipeIn.ClearRemoteStall();
       
   336         ReceiveCswL();
       
   337         return KErrCommandStalled;        
       
   338         }
       
   339 	TPtrC8 data = iBulkDataTd.Buffer();
       
   340 
       
   341 	ReceiveCswL();
       
   342 
       
   343     TUint32 dataReceived = 0;
       
   344 	r = ProcessInTransferL(dataReceived);
       
   345     if (!r)
       
   346         {
       
   347 
       
   348         if (dataReceived == 0)
       
   349             {
       
   350             __BOTPRINT1(_L("Warning: No data received"), dataReceived);
       
   351             return KErrCommandNotSupported;
       
   352             }
       
   353 
       
   354         TRAP(r, aResp->DecodeL(data));
       
   355         }
       
   356 	return r;
       
   357 	}
       
   358 
       
   359 
       
   360 TInt CBulkOnlyTransport::SendDataRxCmdL(const MClientCommandServiceReq* aCommand,
       
   361                                         TDes8& aCopyBuf,
       
   362                                         TInt& aLen)
       
   363 	{
       
   364     __MSFNLOG
       
   365 
       
   366 	TInt r = KErrNone;
       
   367 	SendCbwL(aCommand, TBotCbw::EDataIn, aLen);
       
   368 
       
   369     // store initial length as data is appended to the buffer
       
   370     TInt startPos = aCopyBuf.Length();
       
   371 
       
   372 	TInt len = aLen;
       
   373 
       
   374 	while (len)
       
   375         {
       
   376 		if(len > KResponsePacketSize)
       
   377 			iBulkDataTd.SaveData(KResponsePacketSize);
       
   378 		else
       
   379 			iBulkDataTd.SaveData(len);
       
   380 		iBulkPipeIn.Transfer(iBulkDataTd, iStatus);
       
   381 		User::WaitForRequest(iStatus);
       
   382 
       
   383 		r = iStatus.Int();
       
   384 		if (r != KErrNone)
       
   385 			{
       
   386 			if (r == KErrUsbStalled)
       
   387 				{
       
   388 				__BOTPRINT(_L("SendDataRxCmdL ClearRemoteStall"));
       
   389 				iBulkPipeIn.ClearRemoteStall();
       
   390 #ifdef MASSSTORAGE_PUBLISHER
       
   391                 TMsPublisher publisher(TMsPublisher::KStallProperty);
       
   392 #endif
       
   393 				break;
       
   394 				}
       
   395 			DoResetRecovery();
       
   396 			__BOTPRINT1(_L("Usb transfer error %d"),r);
       
   397 			User::Leave(KErrGeneral);
       
   398 			}
       
   399 
       
   400 		TPtrC8 data = iBulkDataTd.Buffer();
       
   401 		aCopyBuf.Append(data.Ptr(), data.Length());
       
   402 		if(len > KResponsePacketSize)
       
   403 			len -= KResponsePacketSize;
       
   404 		else
       
   405 			len = 0;
       
   406         }
       
   407 
       
   408 	ReceiveCswL();
       
   409 	TUint32 lenReceived = 0;
       
   410 
       
   411 	r = ProcessInTransferL(lenReceived);
       
   412     aLen = lenReceived;
       
   413     aCopyBuf.SetLength(startPos + lenReceived);
       
   414 
       
   415 	return r;
       
   416 	}
       
   417 
       
   418 TInt CBulkOnlyTransport::SendDataTxCmdL(const MClientCommandServiceReq* aCommand,
       
   419                                         TDesC8& aData,
       
   420                                         TUint aPos,
       
   421                                         TInt& aLen)
       
   422 	{
       
   423     __MSFNLOG
       
   424    	TInt r = KErrNone;
       
   425 
       
   426    	SendCbwL(aCommand, TBotCbw::EDataOut, aLen);
       
   427 
       
   428    	TInt len = aLen;
       
   429    	TInt length = 0;
       
   430    	iBulkDataTd.SetZlpStatus(RUsbTransferDescriptor::ESuppressZlp);
       
   431    	while (len)
       
   432         {
       
   433    		TPtr8 senddata = iBulkDataTd.WritableBuffer();
       
   434 		senddata.Append(aData.Ptr() + length + aPos, len > KResponsePacketSize? KResponsePacketSize : len);
       
   435 
       
   436    		iBulkDataTd.SaveData(senddata.Length());
       
   437    		iBulkPipeOut.Transfer(iBulkDataTd, iStatus);
       
   438    		User::WaitForRequest(iStatus);
       
   439 
       
   440 		if (iStatus.Int() != KErrNone)
       
   441    			{
       
   442    			if (iStatus.Int() == KErrUsbStalled)
       
   443    				{
       
   444 				__BOTPRINT(_L("SendDataTxCmdL ClearRemoteStall"));
       
   445    				iBulkPipeOut.ClearRemoteStall();
       
   446 #ifdef MASSSTORAGE_PUBLISHER
       
   447                 TMsPublisher publisher(TMsPublisher::KStallProperty);
       
   448 #endif
       
   449    				break;
       
   450    				}
       
   451    			DoResetRecovery();
       
   452 			__BOTPRINT1(_L("Usb transfer error %d"), r);
       
   453    			User::Leave(KErrGeneral);
       
   454    			}
       
   455 
       
   456 		if(len > KResponsePacketSize)
       
   457 			{
       
   458    			len -= KResponsePacketSize;
       
   459    			length += KResponsePacketSize;
       
   460 			}
       
   461 		else
       
   462 			{
       
   463    			length += len;
       
   464    			len = 0;
       
   465 			}
       
   466         }
       
   467 
       
   468    	ReceiveCswL();
       
   469 
       
   470    	TUint32 lenSent = 0;
       
   471    	r = ProcessOutTransferL(lenSent);
       
   472    	aLen = lenSent;
       
   473 
       
   474    	return r;
       
   475 	}
       
   476 
       
   477 
       
   478 TInt CBulkOnlyTransport::ProcessZeroTransferL()
       
   479     {
       
   480     __MSFNLOG
       
   481     // process 13 cases
       
   482 
       
   483 	__ASSERT_DEBUG(iCbw.iDirection == TBotCbw::EDataOut, User::Invariant());
       
   484 	__ASSERT_DEBUG(iCbw.iDataTransferLength == 0, User::Invariant());
       
   485 
       
   486     // Hn - Host expects no data transfers
       
   487     if (!iCsw.IsValidCsw(iCbw.iTag))
       
   488         {
       
   489         __BOTPRINT(_L("BOT CSW Invalid"));
       
   490         DoResetRecovery();
       
   491 		User::Leave(KErrGeneral);
       
   492         }
       
   493     if (!iCsw.IsMeaningfulCsw(iCbw.iDataTransferLength))
       
   494         {
       
   495         __BOTPRINT(_L("BOT CSW not meaningful"));
       
   496         DoResetRecovery();
       
   497 		User::Leave(KErrGeneral);
       
   498         }
       
   499 
       
   500     if (iCsw.iStatus == TBotCsw::EPhaseError)
       
   501         {
       
   502         // Case (2) or (3)
       
   503         __BOTPRINT(_L("BOT Phase Error"));
       
   504         // Reset Recovery
       
   505         DoResetRecovery();
       
   506 		User::Leave(KErrGeneral);
       
   507         }
       
   508 
       
   509     if (iCsw.iDataResidue != 0)
       
   510         {
       
   511         // should not happen
       
   512         __BOTPRINT(_L("BOT Residue is invalid!"));
       
   513         // Reset Recovery
       
   514         DoResetRecovery();
       
   515 		User::Leave(KErrGeneral);
       
   516         }
       
   517 
       
   518     // all ok if here
       
   519     return (iCsw.iStatus == TBotCsw::ECommandPassed) ? KErrNone : KErrCommandFailed;
       
   520     }
       
   521 
       
   522 
       
   523 TInt CBulkOnlyTransport::ProcessInTransferL(TUint32& aDataReceived)
       
   524     {
       
   525     __MSFNLOG
       
   526     aDataReceived = 0;
       
   527     // process 13 cases
       
   528 
       
   529 	__ASSERT_DEBUG(iCbw.iDirection == TBotCbw::EDataIn, User::Invariant());
       
   530 
       
   531     // Hi - Host expects to receive data from the device
       
   532     if (!iCsw.IsValidCsw(iCbw.iTag))
       
   533         {
       
   534         __BOTPRINT(_L("BOT CSW Invalid"));
       
   535         DoResetRecovery();
       
   536         User::Leave(KErrGeneral);
       
   537         }
       
   538     if (!iCsw.IsMeaningfulCsw(iCbw.iDataTransferLength))
       
   539         {
       
   540         __BOTPRINT(_L("BOT CSW not meaningful"));
       
   541         DoResetRecovery();
       
   542         User::Leave(KErrGeneral);
       
   543         }
       
   544 
       
   545 
       
   546     if (iCsw.iStatus == TBotCsw::EPhaseError)
       
   547         {
       
   548         __BOTPRINT(_L("BOT Phase Error"));
       
   549         // Case (7) or (8)
       
   550         // Reset Recovery
       
   551         DoResetRecovery();
       
   552 		User::Leave(KErrGeneral);
       
   553         }
       
   554 
       
   555     // all ok if here
       
   556     // Case (4), (5) or (6)
       
   557     aDataReceived = iCbw.iDataTransferLength - iCsw.iDataResidue;
       
   558     return (iCsw.iStatus == TBotCsw::ECommandPassed) ? KErrNone : KErrCommandFailed;
       
   559     }
       
   560 
       
   561 
       
   562 TInt CBulkOnlyTransport::ProcessOutTransferL(TUint32& aDataReceived)
       
   563     {
       
   564     __MSFNLOG
       
   565     aDataReceived = 0;
       
   566     // process 13 cases
       
   567 
       
   568 	__ASSERT_DEBUG(iCbw.iDirection == TBotCbw::EDataOut, User::Invariant());
       
   569 
       
   570     // Ho - Host expects to send data to the device
       
   571     if (!iCsw.IsValidCsw(iCbw.iTag))
       
   572         {
       
   573         __BOTPRINT(_L("BOT CSW Invalid"));
       
   574         DoResetRecovery();
       
   575         User::Leave(KErrGeneral);
       
   576         }
       
   577     if (!iCsw.IsMeaningfulCsw(iCbw.iDataTransferLength))
       
   578         {
       
   579         __BOTPRINT(_L("BOT CSW not meaningful"));
       
   580         DoResetRecovery();
       
   581         User::Leave(KErrGeneral);
       
   582         }
       
   583 
       
   584     if (iCsw.iStatus == TBotCsw::EPhaseError)
       
   585         {
       
   586         __BOTPRINT(_L("BOT Phase Error"));
       
   587         // Case (10) or (13)
       
   588         // Reset Recovery
       
   589         DoResetRecovery();
       
   590 		User::Leave(KErrGeneral);
       
   591         }
       
   592 
       
   593     // all ok if here
       
   594     // Case (9), (11) or (12)
       
   595     aDataReceived = iCbw.iDataTransferLength - iCsw.iDataResidue;
       
   596     return (iCsw.iStatus == TBotCsw::ECommandPassed) ? KErrNone : KErrCommandFailed;
       
   597     }
       
   598 
       
   599 
       
   600 void CBulkOnlyTransport::SetLun(TLun aLun)
       
   601     {
       
   602     __MSFNLOG
       
   603     iLun = aLun;
       
   604     __BOTPRINT1(_L("CBulkOnlyTransport::SetLun(%d)"), aLun)
       
   605     }
       
   606 
       
   607 
       
   608 /**
       
   609 Encode CBW into the supplied buffer. The command is also encoded using the
       
   610 supplied encoding method of MClientCommandServiceReq.
       
   611 
       
   612 @param aBuffer The buffer to copy the encoded stream in to
       
   613 @param aCommand The command to be encoded into the Command Block field
       
   614 */
       
   615 void TBotCbw::EncodeL(TPtr8 &aBuffer, const MClientCommandServiceReq* aCommand) const
       
   616     {
       
   617     __MSFNSLOG
       
   618 	aBuffer.SetLength(KCbwLength);
       
   619 
       
   620 	TPtr8 commandBlock = aBuffer.MidTPtr(TBotCbw::KCbwCbOffset);
       
   621 
       
   622 	aBuffer.FillZ();
       
   623 
       
   624     TInt cbLength = aCommand->EncodeRequestL(commandBlock);
       
   625 
       
   626 	TUint8* ptr = (TUint8 *) aBuffer.Ptr();
       
   627     LittleEndian::Put32(&ptr[KCbwSignatureOffset], 0x43425355);
       
   628     LittleEndian::Put32(&ptr[KCbwTagOffset], iTag);
       
   629     LittleEndian::Put32(&ptr[KCbwDataTransferLengthOffset], iDataTransferLength);
       
   630     aBuffer[KCbwFlagOffset] = (iDirection == EDataOut) ? 0x00 : 0x80;
       
   631     aBuffer[KCbwLunOffset] = iLun;
       
   632     aBuffer[KCbwCbLengthOffset] = cbLength;
       
   633 	__BOTPRINT1(_L("BOT TBotCbw::Encode Lun=%d"), iLun);
       
   634     }
       
   635 
       
   636 
       
   637 /**
       
   638 Decode stream into TBotCsw.
       
   639 
       
   640 @param aPtr A buffer containing CSW stream
       
   641 */
       
   642 TInt TBotCsw::Decode(const TDesC8& aPtr)
       
   643     {
       
   644     __MSFNLOG
       
   645     if (aPtr.Length() != KCswLength)
       
   646         {
       
   647 		__BOTPRINT1(_L("Invalid CSW length %d"), aPtr.Length());
       
   648         return KErrGeneral;
       
   649         }
       
   650 
       
   651     iSignature = LittleEndian::Get32(&aPtr[KCswSignatureOffset]);
       
   652     iTag = LittleEndian::Get32(&aPtr[KCswTagOffset]);
       
   653     iDataResidue = LittleEndian::Get32(&aPtr[KCswDataResidueOffset]);
       
   654 
       
   655     TInt status = aPtr[KCswStatusOffset];
       
   656     iStatus = static_cast<TCswStatus>(status);
       
   657     __BOTPRINT1(_L("BOT CSW Status = %d"), iStatus);
       
   658     return KErrNone;
       
   659     }
       
   660 
       
   661 
       
   662 /**
       
   663 Checks that CSW contents are valid, USB Mass Storage Class Bulk-Only
       
   664 Transport 6.3.
       
   665 
       
   666 @param aTag The tag value received from the device
       
   667 
       
   668 @return TBool Return ETrue if valid else EFalse
       
   669 */
       
   670 TBool TBotCsw::IsValidCsw(TUint32 aTag) const
       
   671     {
       
   672     __MSFNSLOG
       
   673     if (iSignature != 0x53425355)
       
   674         {
       
   675         return EFalse;
       
   676         }
       
   677     if (iTag != aTag)
       
   678         {
       
   679         return EFalse;
       
   680         }
       
   681     return ETrue;
       
   682     }
       
   683 
       
   684 
       
   685 /**
       
   686 Checks that CSW contents are meaningful, USB Mass Storage Class Bulk-Only
       
   687 Transport 6.3.
       
   688 
       
   689 @param aTransferLength Number of bytes transferred
       
   690 
       
   691 @return TBool Return ETrue if meaningful else EFalse
       
   692 */
       
   693 TBool TBotCsw::IsMeaningfulCsw(TUint32 aTransferLength) const
       
   694     {
       
   695     __MSFNSLOG
       
   696     if (iStatus != EPhaseError)
       
   697         {
       
   698         if (iDataResidue > aTransferLength)
       
   699             {
       
   700             return EFalse;
       
   701             }
       
   702         }
       
   703     return ETrue;
       
   704     }
       
   705 
       
   706 #ifdef MASSSTORAGE_PUBLISHER
       
   707 TMsPublisher::TMsPublisher(TPropertyKeys aKey)
       
   708     {
       
   709 	RProperty prop;
       
   710 
       
   711     const TUid KUidHostMassStorageCategory = {KMyUid};
       
   712 
       
   713 	TInt ret = prop.Attach(KUidHostMassStorageCategory, aKey);
       
   714     __BOTPRINT2(_L("Property Key[%d] attach ret=%d"), aKey, ret);
       
   715 	if (ret == KErrNone)
       
   716         {
       
   717         TInt flag;
       
   718         ret = prop.Get(KUidHostMassStorageCategory, aKey, flag);
       
   719         if (ret == KErrNone)
       
   720             {
       
   721             flag++;
       
   722             ret = prop.Set(KUidHostMassStorageCategory, aKey, flag);
       
   723             }
       
   724 	    __BOTPRINT3(_L("Property Set[%d] ret=%d Counter=%d"), aKey, ret, flag);
       
   725 		prop.Close();
       
   726         }
       
   727     }
       
   728 
       
   729 #endif
       
   730