userlibandfileserver/fileserver/smassstorage/cbulkonlytransport.cpp
changeset 286 48e57fb1237e
parent 271 dc268b18d709
equal deleted inserted replaced
285:ff5437e4337c 286:48e57fb1237e
    15 
    15 
    16 /**
    16 /**
    17  @file
    17  @file
    18  @internalTechnology
    18  @internalTechnology
    19 */
    19 */
       
    20 
       
    21 #include <e32std.h>
       
    22 #include "mtransport.h"
       
    23 #include "mprotocol.h"
       
    24 #include "mldddevicestatenotification.h"
       
    25 #include "tbulkmm.h"
       
    26 
       
    27 #include "drivemanager.h"
       
    28 #include "cusbmassstoragecontroller.h"
       
    29 
    20 #include "cbulkonlytransport.h"
    30 #include "cbulkonlytransport.h"
    21 #include "cbulkonlytransportusbcldd.h"
    31 #include "cbulkonlytransportusbcldd.h"
    22 #if !defined(__WINS__) && !defined(__X86__)
    32 #if !defined(__WINS__) && !defined(__X86__)
    23 #include "cbulkonlytransportusbcscldd.h"
    33 #include "cbulkonlytransportusbcscldd.h"
    24 #endif
    34 #endif
    25 #include "usbmsshared.h"
    35 #include "smassstorage.h"
    26 #include "massstoragedebug.h"
    36 
    27 #include "cusbmassstorageserver.h"
    37 #include "OstTraceDefinitions.h"
       
    38 #ifdef OST_TRACE_COMPILER_IN_USE
       
    39 #include "cbulkonlytransportTraces.h"
       
    40 #endif
    28 
    41 
    29 
    42 
    30 //CBW offsets
    43 //CBW offsets
    31 LOCAL_D const TInt KCbwSignatureOffset 			= 0;
    44 static const TInt KCbwSignatureOffset          = 0;
    32 LOCAL_D const TInt KCbwTagOffset 				= 4;
    45 static const TInt KCbwTagOffset                = 4;
    33 LOCAL_D const TInt KCbwDataTransferLengthOffset = 8;
    46 static const TInt KCbwDataTransferLengthOffset = 8;
    34 LOCAL_D const TInt KCbwFlagOffset 				= 12;
    47 static const TInt KCbwFlagOffset               = 12;
    35 LOCAL_D const TInt KCbwLunOffset				= 13;
    48 static const TInt KCbwLunOffset                = 13;
    36 LOCAL_D const TInt KCbwCbLengthOffset  			= 14;
    49 static const TInt KCbwCbLengthOffset           = 14;
    37 
    50 
    38 LOCAL_D const TInt KMaxCbwcbLength 				= 16;
    51 static const TInt KMaxCbwcbLength              = 16;
    39 
    52 
    40 // CSW offsets
    53 // CSW offsets
    41 LOCAL_D const TInt KCswSingnatureOffset 		= 0;
    54 static const TInt KCswSingnatureOffset         = 0;
    42 LOCAL_D const TInt KCswTagOffset 				= 4;
    55 static const TInt KCswTagOffset                = 4;
    43 LOCAL_D const TInt KCswDataResidueOffset 		= 8;
    56 static const TInt KCswDataResidueOffset        = 8;
    44 LOCAL_D const TInt KCswStatusOffset 			= 12;
    57 static const TInt KCswStatusOffset             = 12;
    45 
       
    46 
    58 
    47 
    59 
    48 /**
    60 /**
    49  This function unpacks into the TUsbRequestHdr class from a descriptor with
    61  This function unpacks into the TUsbRequestHdr class from a descriptor with
    50  the alignment that would be introduced on the USB bus.
    62  the alignment that would be introduced on the USB bus.
    52  @param aBuffer Input buffer
    64  @param aBuffer Input buffer
    53  @param aTarget Unpacked header.
    65  @param aTarget Unpacked header.
    54  @return Error.
    66  @return Error.
    55  */
    67  */
    56 TInt TUsbRequestHdr::Decode(const TDesC8& aBuffer)
    68 TInt TUsbRequestHdr::Decode(const TDesC8& aBuffer)
    57 	{
    69     {
    58 	if (aBuffer.Length() < static_cast<TInt>(KRequestHdrSize))
    70     if (aBuffer.Length() < static_cast<TInt>(KRequestHdrSize))
    59 		{
    71         {
    60         __PRINT1(_L("TUsbRequestHdr::Decode buffer invalid length %d"), aBuffer.Length());
    72         OstTrace1(TRACE_SMASSSTORAGE_USB, TUSBREQUESTHDR_DECODE_ERR,
    61 		return KErrGeneral;
    73                  "ERROR: USB DEVICE REQUEST invalid length 0x%x", aBuffer.Length());
    62 		}
    74         return KErrGeneral;
    63 
    75         }
    64 	iRequestType = aBuffer[0];
    76 
    65 	iRequest = static_cast<TEp0Request>(aBuffer[1]);
    77     iRequestType = aBuffer[0];
    66 	iValue	 = static_cast<TUint16>(aBuffer[2] + (aBuffer[3] << 8));
    78     iRequest = static_cast<TEp0Request>(aBuffer[1]);
    67 	iIndex	 = static_cast<TUint16>(aBuffer[4] + (aBuffer[5] << 8));
    79     iValue   = static_cast<TUint16>(aBuffer[2] + (aBuffer[3] << 8));
    68 	iLength  = static_cast<TUint16>(aBuffer[6] + (aBuffer[7] << 8));
    80     iIndex   = static_cast<TUint16>(aBuffer[4] + (aBuffer[5] << 8));
    69     __PRINT5(_L("type=%d request=%d value=%d index=%d length=%d"), iRequestType,iRequest,iValue,iIndex,iLength);
    81     iLength  = static_cast<TUint16>(aBuffer[6] + (aBuffer[7] << 8));
    70 
    82     OstTraceExt5(TRACE_SMASSSTORAGE_USB, TUSBREQUESTHDR_DECODE,
    71 	return KErrNone;
    83               "USB DEVICE REQUEST type=0x%x request=0x%x value=%d index=%d length=%d",
    72 	}
    84               iRequestType, iRequest, iValue, iIndex, iLength);
       
    85 
       
    86     return KErrNone;
       
    87     }
    73 
    88 
    74 
    89 
    75 /**
    90 /**
    76 This function determines whether data is required by the host in response
    91 This function determines whether data is required by the host in response
    77 to a message header.
    92 to a message header.
    78 
    93 
    79 @return TBool	Flag indicating whether a data response required.
    94 @return TBool   Flag indicating whether a data response required.
    80 */
    95 */
    81 TBool TUsbRequestHdr::IsDataResponseRequired() const
    96 TBool TUsbRequestHdr::IsDataResponseRequired() const
    82 
    97 
    83 	{
    98     {
    84 	return (iRequestType & 0x80) ? (TBool)ETrue : (TBool)EFalse;
    99     return (iRequestType & 0x80) ? (TBool)ETrue : (TBool)EFalse;
    85 	}
   100     }
    86 
   101 
    87 //-------------------------------------
   102 //-------------------------------------
    88 /**
   103 /**
    89 Create an object of a class derived from CBulkOnlyTransport (default to CBulkOnlyTransportUsbcLdd object)
   104 Create an object of a class derived from CBulkOnlyTransport (default to CBulkOnlyTransportUsbcLdd object)
    90 @param aNumDrives - The number of drives available for MS
   105 @param aNumDrives - The number of drives available for MS
    91 @param aController - reference to the parent
   106 @param aController - reference to the parent
    92 @return pointer to newly created derived class object
   107 @return pointer to newly created derived class object
    93 */
   108 */
    94 CBulkOnlyTransport* CBulkOnlyTransport::NewL(TInt aNumDrives,CUsbMassStorageController& aController)
   109 CBulkOnlyTransport* CBulkOnlyTransport::NewL(TInt aNumDrives,CUsbMassStorageController& aController)
    95 	{
   110     {
    96 	__FNLOG("CBulkOnlyTransport::NewL()");
   111     return NewL(aNumDrives,aController, (CUsbMassStorageController::TTransportldd) 1);
    97 	
   112     }
    98 	return NewL(aNumDrives,aController, (CUsbMassStorageController::TTransportldd) 1);
   113 
    99 	}
   114 /**
   100 
   115 Create an object of a class derived from CBulkOnlyTransport
   101 /**
       
   102 Create an object of a class derived from CBulkOnlyTransport 
       
   103 @param aNumDrives - The number of drives available for MS
   116 @param aNumDrives - The number of drives available for MS
   104 @param aController - reference to the parent
   117 @param aController - reference to the parent
   105 @param aTransportLddFlag - Type of usb client ldd
   118 @param aTransportLddFlag - Type of usb client ldd
   106 @return pointer to newly created derived class object
   119 @return pointer to newly created derived class object
   107 */
   120 */
   108 CBulkOnlyTransport* CBulkOnlyTransport::NewL(TInt aNumDrives,CUsbMassStorageController& aController, CUsbMassStorageController::TTransportldd aTransportLddFlag)
   121 CBulkOnlyTransport* CBulkOnlyTransport::NewL(TInt aNumDrives,CUsbMassStorageController& aController, CUsbMassStorageController::TTransportldd aTransportLddFlag)
   109 	{
   122     {
   110 	__FNLOG("CBulkOnlyTransport::NewL()");
   123     if (aNumDrives <=0 || static_cast<TUint>(aNumDrives) > KUsbMsMaxDrives)
   111 
   124         {
   112 	if (aNumDrives <=0 || static_cast<TUint>(aNumDrives) > KUsbMsMaxDrives)
   125         User::Leave(KErrArgument);
   113 		{
   126         }
   114 		User::Leave(KErrArgument);
       
   115 		}
       
   116 
   127 
   117 #if !defined(__WINS__) && !defined(__X86__)
   128 #if !defined(__WINS__) && !defined(__X86__)
   118 	CBulkOnlyTransportUsbcScLdd* scTransport;
   129     CBulkOnlyTransportUsbcScLdd* scTransport;
   119 #endif
   130 #endif
   120 	CBulkOnlyTransportUsbcLdd* nonscTransport;
   131     CBulkOnlyTransportUsbcLdd* nonscTransport;
   121 	switch (aTransportLddFlag)
   132     switch (aTransportLddFlag)
   122 		{
   133         {
   123 		case 1: 
   134         case 1:
   124 			nonscTransport = new(ELeave) CBulkOnlyTransportUsbcLdd(aNumDrives, aController);
   135             nonscTransport = new(ELeave) CBulkOnlyTransportUsbcLdd(aNumDrives, aController);
   125 			return nonscTransport;
   136             OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_NEWL1, "CBulkOnlyTransportUsbcLdd created.");
       
   137             return nonscTransport;
   126 #if !defined(__WINS__) && !defined(__X86__)
   138 #if !defined(__WINS__) && !defined(__X86__)
   127 		case 2: 
   139         case 2:
   128 			scTransport = new(ELeave) CBulkOnlyTransportUsbcScLdd(aNumDrives, aController);
   140             scTransport = new(ELeave) CBulkOnlyTransportUsbcScLdd(aNumDrives, aController);
   129 			return scTransport;
   141             OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_NEWL2, "CBulkOnlyTransportUsbcScLdd created.");
       
   142             return scTransport;
   130 #endif
   143 #endif
   131         default:
   144         default:
   132             __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsCBulkOnlyTransportNull));		    
   145             __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsCBulkOnlyTransportNull));
   133 			return NULL;
   146             return NULL;
   134 
   147 
   135 		}
   148         }
   136 	}
   149     }
   137 
   150 
   138 
   151 
   139 TInt CBulkOnlyTransport::InitialiseTransportL(TInt aTransportLddFlag)
   152 TInt CBulkOnlyTransport::InitialiseTransportL(TInt aTransportLddFlag)
   140 	{
   153     {
   141 	__FNLOG("CBulkOnlyTransportUsbcScLdd::InitialiseTransportL()");
   154     TInt ret = KErrNone;
   142 	TInt ret = KErrNone;
   155     MTransportBase* transport;
   143 	MTransportBase* transport;
   156     iController.GetTransport(transport);
   144 	iController.GetTransport(transport);
   157     switch (aTransportLddFlag)
   145 	switch (aTransportLddFlag)
   158         {
   146 		{
       
   147 #if !defined(__WINS__) && !defined(__X86__)
   159 #if !defined(__WINS__) && !defined(__X86__)
   148 		case 2: 
   160         case 2:
   149 				ret = ((CBulkOnlyTransportUsbcScLdd*) transport)->Ldd().Open(0);
   161                 ret = ((CBulkOnlyTransportUsbcScLdd*) transport)->Ldd().Open(0);
   150 				if (ret != KErrNone)
   162                 if (ret != KErrNone)
   151 					{
   163                     {
   152 					return ret;
   164                     return ret;
   153 					}
   165                     }
   154 				else
   166                 else
   155 					{
   167                     {
   156 					((CBulkOnlyTransportUsbcScLdd*) transport)->Ldd().Close();		
   168                     ((CBulkOnlyTransportUsbcScLdd*) transport)->Ldd().Close();
   157 					CleanupStack::PushL(transport);
   169                     CleanupStack::PushL(transport);
   158 					((CBulkOnlyTransportUsbcScLdd*) transport)->ConstructL();
   170                     ((CBulkOnlyTransportUsbcScLdd*) transport)->ConstructL();
   159 					CleanupStack::Pop(transport);
   171                     CleanupStack::Pop(transport);
   160 					return ret;
   172                     return ret;
   161 					}
   173                     }
   162 #endif
   174 #endif
   163 		case 1:
   175         case 1:
   164 				ret = ((CBulkOnlyTransportUsbcLdd*) transport)->Ldd().Open(0);
   176                 ret = ((CBulkOnlyTransportUsbcLdd*) transport)->Ldd().Open(0);
   165 				if (ret != KErrNone)
   177                 if (ret != KErrNone)
   166 					{
   178                     {
   167 					return ret;
   179                     return ret;
   168 					}
   180                     }
   169 				else
   181                 else
   170 					{
   182                     {
   171 					((CBulkOnlyTransportUsbcLdd*) transport)->Ldd().Close();
   183                     ((CBulkOnlyTransportUsbcLdd*) transport)->Ldd().Close();
   172 					CleanupStack::PushL(transport);
   184                     CleanupStack::PushL(transport);
   173 					((CBulkOnlyTransportUsbcLdd*) transport)->ConstructL();
   185                     ((CBulkOnlyTransportUsbcLdd*) transport)->ConstructL();
   174 					CleanupStack::Pop(transport);
   186                     CleanupStack::Pop(transport);
   175 					return ret;
   187                     return ret;
   176 					}
   188                     }
   177 		default:
   189         default:
   178 				return KErrNotFound;
   190                 return KErrNotFound;
   179 		}
   191         }
   180 	}	
   192     }
   181 
   193 
   182 /**
   194 /**
   183 c'tor
   195 c'tor
   184 @param aNumDrives - The number of drives available for MS
   196 @param aNumDrives - The number of drives available for MS
   185 @param aController - reference to the parent
   197 @param aController - reference to the parent
   186 */
   198 */
   187 CBulkOnlyTransport::CBulkOnlyTransport(TInt aNumDrives,CUsbMassStorageController& aController):
   199 CBulkOnlyTransport::CBulkOnlyTransport(TInt aNumDrives,CUsbMassStorageController& aController):
   188 	CActive(EPriorityStandard),
   200     CActive(EPriorityStandard),
   189 	iMaxLun(aNumDrives-1),
   201     iMaxLun(aNumDrives-1),
   190 	iController(aController),
   202     iController(aController),
   191 	iStallAllowed(ETrue),
   203     iStallAllowed(ETrue),
   192 	iInterfaceConfigured(EFalse),
   204     iInterfaceConfigured(EFalse),
   193 	iCommandBufPtr(NULL,0),
   205     iCommandBufPtr(NULL,0),
   194 	iDataBufPtr(NULL,0),
   206     iDataBufPtr(NULL,0),
   195 	iCswBufPtr(NULL,0),
   207     iCswBufPtr(NULL,0),
   196 	iPaddingBufPtr(NULL,0),
   208     iPaddingBufPtr(NULL,0),
   197 	iWriteBufPtr(NULL,0),
   209     iWriteBufPtr(NULL,0),
   198 	iReadBufPtr(NULL, 0),
   210     iReadBufPtr(NULL, 0),
   199 	iCbwBufPtr(NULL,0)
   211     iCbwBufPtr(NULL,0)
   200 	{
   212     {
   201 	__FNLOG("CBulkOnlyTransport::CBulkOnlyTransport");
   213     }
   202 	}
       
   203 
   214 
   204 /**
   215 /**
   205 Destructor
   216 Destructor
   206 */
   217 */
   207 CBulkOnlyTransport::~CBulkOnlyTransport()
   218 CBulkOnlyTransport::~CBulkOnlyTransport()
   208 	{
   219     {
   209 	}
   220     }
   210 
   221 
   211 
   222 
   212 /**
   223 /**
   213 Called by the protocol after processing the packet to indicate that more data is required.
   224 Called by the protocol after processing the packet to indicate that more data is required.
   214 
   225 
   215 @param aData reference to the data buffer.
   226 @param aData reference to the data buffer.
   216 */
   227 */
   217 void CBulkOnlyTransport::SetupReadData(TUint aLength)
   228 void CBulkOnlyTransport::SetupReadData(TUint aLength)
   218 	{
   229     {
   219 	__FNLOG("CBulkOnlyTransport::SetupReadData");
   230     OstTrace1(TRACE_SMASSSTORAGE_BOTDATA, CBULKONLYTRANSPORT_SETUPREADDATA,
   220 	__PRINT1(_L("Length = %d  (bytes)\n"), aLength);
   231               "BOT SetupReadData Length = 0x%x bytes", aLength);
   221 	iBufSize = aLength;
   232     iBufSize = aLength;
   222 	iReadSetUp = ETrue;
   233     iReadSetUp = ETrue;
   223 	}
   234     }
   224 
   235 
   225 
   236 
   226 /**
   237 /**
   227 Called by the protocol after processing the packet to indicate that data should be written to the host.
   238 Called by the protocol after processing the packet to indicate that data should be written to the host.
   228 
   239 
   229 @param aData reference to the data buffer.
   240 @param aData reference to the data buffer.
   230 */
   241 */
   231 void CBulkOnlyTransport::SetupWriteData(TPtrC8& aData)
   242 void CBulkOnlyTransport::SetupWriteData(TPtrC8& aData)
   232 	{
   243     {
   233 	__FNLOG("CBulkOnlyTransport::SetupWriteData");
   244     OstTrace1(TRACE_SMASSSTORAGE_BOTDATA, CBULKONLYTRANSPORT_SETUPWRITEDATA,
   234 	__PRINT1(_L("Length = %d  (bytes)\n"), aData.Length());
   245               "BOT SetupWriteData Length = 0x%x bytes", aData.Length());
   235 	iWriteBufPtr.Set(aData);
   246     iWriteBufPtr.Set(aData);
   236 	iWriteSetUp = ETrue;
   247     iWriteSetUp = ETrue;
   237 	}
   248     }
   238 
   249 
   239 
   250 
   240 TInt CBulkOnlyTransport::Start()
   251 TInt CBulkOnlyTransport::Start()
   241 	{
   252     {
   242 	__FNLOG("CBulkOnlyTransport::Start");
   253     OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_START, "Start...");
   243 
   254     if (!iProtocol)
   244 	TInt err = KErrNone;
   255         {
   245 
   256         return KErrBadHandle;   //protocol should be set up before start
   246 	if (!iProtocol)
   257         }
   247 		{
   258 
   248 		return KErrBadHandle;   //protocol should be set up before start
   259     if (IsActive())
   249 		}
   260         {
   250 
   261         OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_START1, "Error: active before start!");
   251 	if (IsActive())
   262         return KErrInUse;
   252 		{
   263         }
   253 		__PRINT(_L("CBulkOnlyTransport::Start  - active before start!\n"));
   264 
   254 		return KErrInUse;
   265     TInt err = KErrNone;
   255 		}
   266     if ((err = SetupConfigurationDescriptor())  != KErrNone ||
   256 
   267         (err = SetupInterfaceDescriptors())     != KErrNone )
   257 	if ((err = SetupConfigurationDescriptor()) 	!= KErrNone ||
   268         {
   258 		(err = SetupInterfaceDescriptors())		!= KErrNone )
   269         OstTrace1(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_START2, "Error: descriptors setup failed %d", err);
   259 		{
   270         return err;
   260 		__PRINT(_L("CBulkOnlyTransport::Start  - Error during descriptors setup!\n"));
   271         }
   261 		return err;
   272 
   262 		}
   273     AllocateEndpointResources();
   263 
   274     ActivateDeviceStateNotifier();  // activate notifier wich will wait until USB became configured
   264 	AllocateEndpointResources();
   275     TUsbcDeviceState deviceStatus = EUsbcDeviceStateDefault;
   265 	ActivateDeviceStateNotifier();  // activate notifier wich will wait until USB became configured
   276     err = GetDeviceStatus(deviceStatus);
   266 	TUsbcDeviceState deviceStatus = EUsbcDeviceStateDefault;
   277     if (err == KErrNone && deviceStatus == EUsbcDeviceStateConfigured)
   267 	err = GetDeviceStatus(deviceStatus);
   278         {
   268 	__PRINT1(_L("CBulkOnlyTransport::Start - Device status = %d\n"), deviceStatus);
   279         err = HwStart();
   269 	if (err == KErrNone && deviceStatus == EUsbcDeviceStateConfigured)
   280         }
   270 		{
       
   271 		__PRINT(_L("CBulkOnlyTransport::Start  - Starting bulk only transport\n"));
       
   272 		err = HwStart();
       
   273 		}
       
   274 
   281 
   275 #ifdef MSDC_MULTITHREADED
   282 #ifdef MSDC_MULTITHREADED
   276 	TPtr8 aDes1(NULL,0);
   283     TPtr8 aDes1(NULL,0);
   277 	TPtr8 aDes2(NULL,0);
   284     TPtr8 aDes2(NULL,0);
   278 	GetBufferPointers(aDes1, aDes2);
   285     GetBufferPointers(aDes1, aDes2);
   279 	iProtocol->InitializeBufferPointers(aDes1, aDes2); // have to pass pointer to memory not offsets to initialise TPtr, and lengths
   286     iProtocol->InitializeBufferPointers(aDes1, aDes2); // have to pass pointer to memory not offsets to initialise TPtr, and lengths
   280 #endif
   287 #endif
   281 
   288 
   282 	iInterfaceConfigured = ETrue;
   289     iInterfaceConfigured = ETrue;
   283 	return err;
   290     return err;
   284 	}
   291     }
   285 
   292 
   286 TInt CBulkOnlyTransport::HwStart(TBool aDiscard)
   293 TInt CBulkOnlyTransport::HwStart(TBool aDiscard)
   287 	{
   294     {
   288 	__FNLOG("CBulkOnlyTransport::HwStart");
   295     TInt lun = MaxLun();
   289 
   296     OstTrace1(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_HWSTART, "HwStart MAX LUN=%d", lun);
       
   297     do
       
   298         {
       
   299         Controller().DriveManager().Connect(lun);
       
   300         }
       
   301     while(--lun >= 0);
       
   302 
       
   303     TInt res = StartControlInterface();
       
   304 
       
   305     iCurrentState = ENone;
       
   306     iWriteSetUp=EFalse;
       
   307     iReadSetUp=EFalse;
       
   308     iStarted = ETrue;
       
   309 
       
   310     if (aDiscard)
       
   311         {
       
   312         FlushData();
       
   313         }
       
   314 
       
   315     ReadCBW();
       
   316     return res;
       
   317     }
       
   318 
       
   319 
       
   320 TInt CBulkOnlyTransport::HwStop()
       
   321     {
       
   322     OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_HWSTOP, "HwStop");
       
   323     if (iStarted)
       
   324         {
       
   325         StopBulkOnlyEndpoint();
       
   326         CancelControlInterface();
       
   327         iStarted = EFalse;
       
   328         }
       
   329     return KErrNone;
       
   330     }
       
   331 
       
   332 
       
   333 void CBulkOnlyTransport::StopBulkOnlyEndpoint()
       
   334     {
   290     TInt lun = MaxLun();
   335     TInt lun = MaxLun();
   291     do
   336     do
   292         {
   337         {
   293         Controller().DriveManager().Connect(lun);
   338         Controller().DriveManager().Disconnect(lun);
   294         }
   339         }
   295     while(--lun >= 0);
   340     while(--lun >= 0);
   296 
   341     Cancel();
   297 	TInt res = StartControlInterface();
   342     iProtocol->Cancel();
   298 
   343     }
   299 	iCurrentState = ENone;
   344 
   300 	iWriteSetUp=EFalse;
   345 
   301 	iReadSetUp=EFalse;
   346 TInt CBulkOnlyTransport::HwSuspend()
   302 	iStarted = ETrue;
   347     {
   303 
   348     OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_HWSUSPEND, "HwSuspend");
   304     if (aDiscard)
       
   305 		{
       
   306 		FlushData();
       
   307 		}
       
   308 
       
   309 	ReadCBW();
       
   310 	return res;
       
   311 	}
       
   312 
       
   313 
       
   314 TInt CBulkOnlyTransport::HwStop()
       
   315 	{
       
   316 	__FNLOG("CBulkOnlyTransport::HwStop");
       
   317 	if (iStarted)
       
   318 		{
       
   319         StopBulkOnlyEndpoint();
       
   320 		CancelControlInterface();
       
   321 		iStarted = EFalse;
       
   322 		}
       
   323 	return KErrNone;
       
   324 	}
       
   325 
       
   326 
       
   327 void CBulkOnlyTransport::StopBulkOnlyEndpoint()
       
   328 	{
       
   329 	__FNLOG("CBulkOnlyTransport::StopBulkOnlyEndpoint");
       
   330 
       
   331     TInt lun = MaxLun();
   349     TInt lun = MaxLun();
   332     do
   350     do
   333         {
   351         {
   334         Controller().DriveManager().Disconnect(lun);
   352         Controller().DriveManager().Disconnect(lun);
   335         }
   353         }
   336     while(--lun >= 0);
   354     while(--lun >= 0);
   337 	Cancel();
   355 
   338 	iProtocol->Cancel();
   356     return KErrNone;
   339 	}
   357     }
   340 
       
   341 
       
   342 TInt CBulkOnlyTransport::HwSuspend()
       
   343 	{
       
   344 	__FNLOG("CBulkOnlyTransport::HwSuspend");
       
   345 
       
   346 	TInt lun = MaxLun();
       
   347 	do
       
   348 		{
       
   349 		Controller().DriveManager().Disconnect(lun);
       
   350 		}
       
   351 	while(--lun >= 0);
       
   352 
       
   353 	return KErrNone;
       
   354 	}
       
   355 
   358 
   356 
   359 
   357 TInt CBulkOnlyTransport::HwResume()
   360 TInt CBulkOnlyTransport::HwResume()
   358 	{
   361     {
   359 	__FNLOG("CBulkOnlyTransport::HwResume");
   362     OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_HWRESUME, "HwResume");
   360 
       
   361     TInt lun = MaxLun();
   363     TInt lun = MaxLun();
   362     do
   364     do
   363         {
   365         {
   364         Controller().DriveManager().Connect(lun);
   366         Controller().DriveManager().Connect(lun);
   365         }
   367         }
   366     while(--lun >= 0);
   368     while(--lun >= 0);
   367 
   369 
   368 	return KErrNone;
   370     return KErrNone;
   369 	}
   371     }
   370 
   372 
   371 /**
   373 /**
   372 Stops the Bulk Only Transport
   374 Stops the Bulk Only Transport
   373 */
   375 */
   374 TInt CBulkOnlyTransport::Stop()
   376 TInt CBulkOnlyTransport::Stop()
   375 	{
   377     {
   376 	__FNLOG("CBulkOnlyTransport::Stop");
   378     OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_STOP, "Stop");
   377 	CancelControlInterface();
   379     CancelControlInterface();
   378 	CancelDeviceStateNotifier();
   380     CancelDeviceStateNotifier();
   379 	Cancel();
   381     Cancel();
   380 	if  (iInterfaceConfigured)
   382     if  (iInterfaceConfigured)
   381 		{
   383         {
   382 		ReleaseInterface();
   384         ReleaseInterface();
   383 		SetupConfigurationDescriptor(ETrue);
   385         SetupConfigurationDescriptor(ETrue);
   384 		}
   386         }
   385 	iCurrentState = ENone;
   387     iCurrentState = ENone;
   386 	iInterfaceConfigured = EFalse;
   388     iInterfaceConfigured = EFalse;
   387 
   389 
   388 	return KErrNone;
   390     return KErrNone;
   389 	}
   391     }
   390 
   392 
   391 
   393 
   392 
   394 
   393 void CBulkOnlyTransport::DoCancel()
   395 void CBulkOnlyTransport::DoCancel()
   394 	{
   396     {
   395 	__FNLOG("CBulkOnlyTransport::DoCancel");
   397     CancelReadWriteRequests();
   396 	CancelReadWriteRequests();
   398     }
   397 	}
       
   398 
   399 
   399 
   400 
   400 void CBulkOnlyTransport::Activate(TInt aReason)
   401 void CBulkOnlyTransport::Activate(TInt aReason)
   401     {
   402     {
   402     SetActive();
   403     SetActive();
   404     User::RequestComplete(r, aReason);
   405     User::RequestComplete(r, aReason);
   405     }
   406     }
   406 
   407 
   407 
   408 
   408 void CBulkOnlyTransport::RunL()
   409 void CBulkOnlyTransport::RunL()
   409 	{
   410     {
   410 	__FNLOG("CBulkOnlyTransport::RunL");
   411     if (iStatus != KErrNone)
   411 	if (iStatus != KErrNone)
   412         {
   412 		{
   413         OstTrace1(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_RUNL, "Error %d in RunL, halt endpoints", iStatus.Int());
   413 		__PRINT1(_L("Error %d in RunL, halt endpoints \n"), iStatus.Int());
   414         SetPermError(); //halt endpoints for reset recovery
   414 		SetPermError(); //halt endpoints for reset recovery
   415         return;
   415 		return;
   416         }
   416 		}
   417     switch (iCurrentState)
   417 	switch (iCurrentState)
   418         {
   418 		{
   419         case EWaitForCBW:
   419 		case EWaitForCBW:
   420             OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_RUNL1, "EWaitForCBW");
   420 			__PRINT(_L("EWaitForCBW"));
   421             ProcessCbwEvent();
   421 			ProcessCbwEvent();
   422             break;
   422 			break;
   423 
   423 
   424         case EWritingData:
   424 		case EWritingData:
   425             OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_RUNL2, "EWritingData");
   425             __PRINT(_L("EWritingData"));
   426             iWriteSetUp = EFalse;  //the buffer was used
   426 			iWriteSetUp = EFalse;  //the buffer was used
   427 
   427 
   428             if (iDataResidue && iStallAllowed)
   428 			if (iDataResidue && iStallAllowed)
   429                 {
   429 				{
   430                 StallEndpointAndWaitForClear();
   430 				StallEndpointAndWaitForClear();
   431                 }
   431 				}
   432 
   432 
   433             SendCSW(iCbwTag, iDataResidue, iCmdStatus);
   433 			SendCSW(iCbwTag, iDataResidue, iCmdStatus);
   434             break;
   434 			break;
   435 
   435 
   436         case EReadingData:
   436 		case EReadingData:
   437             {
   437 			{
   438             OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_RUNL3, "EReadingData");
   438 			__PRINT(_L("EReadingData"));
   439             ProcessReadingDataEvent();
   439 
   440             }
   440 			ProcessReadingDataEvent();
   441             break;
   441 			}
   442 
   442 			break;
   443         case ESendingCSW:
   443 
   444             OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_RUNL4, "ESendingCSW");
   444 		case ESendingCSW:
   445             ReadCBW();
   445 			__PRINT(_L("ESendingCSW"));
   446             break;
   446 			ReadCBW();
       
   447 			break;
       
   448 
   447 
   449         case EPermErr:
   448         case EPermErr:
   450 			__PRINT(_L("EPermErr"));
   449             OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_RUNL5, "EPermErr");
   451 			StallEndpointAndWaitForClear();
   450             StallEndpointAndWaitForClear();
   452             break;
   451             break;
   453 
   452 
   454         default:
   453         default:
   455 			SetPermError();		// unexpected state
   454             SetPermError();     // unexpected state
   456 		}
   455         }
   457 	}
   456     }
   458 
   457 
   459 
   458 
   460 /**
   459 /**
   461 Decode the CBW received from the host via OutEndpoint
   460 Decode the CBW received from the host via OutEndpoint
   462 
   461 
   464 - Depending on the command, more data may be transmitted/received.
   463 - Depending on the command, more data may be transmitted/received.
   465 - ...or the CSW is sent (if not a data command).
   464 - ...or the CSW is sent (if not a data command).
   466 
   465 
   467 */
   466 */
   468 void CBulkOnlyTransport::DecodeCBW()
   467 void CBulkOnlyTransport::DecodeCBW()
   469 	{
   468     {
   470 	__FNLOG("CBulkOnlyTransport::DecodeCBW");
   469     SetCbwPtr();
   471 
   470 
   472 	SetCbwPtr();
   471     if (!CheckCBW())  //check if CBW valid and meaningful
   473 
   472         {
   474 	if (!CheckCBW())  //check if CBW valid and meaningful
       
   475 		{
       
   476         // CBW not valid or meaningful
   473         // CBW not valid or meaningful
   477         // Specification says: "If the CBW is not valid, the device shall STALL
   474         // Specification says: "If the CBW is not valid, the device shall STALL
   478         // the Bulk-In pipe. Also, the device shall either STALL the Bulk-Out pipe,
   475         // the Bulk-In pipe. Also, the device shall either STALL the Bulk-Out pipe,
   479         // or the device shall accept and discard any Bulk-Out data. The device
   476         // or the device shall accept and discard any Bulk-Out data. The device
   480         // shall maintain this state until a Reset Recovery."
   477         // shall maintain this state until a Reset Recovery."
   481         // Here we keep bulk-in ep stalled and ignore bulk-out ep.
   478         // Here we keep bulk-in ep stalled and ignore bulk-out ep.
   482 		SetPermError();
   479         SetPermError();
   483 		ExpireData((TAny*) (iCbwBufPtr.Ptr()));
   480         ExpireData((TAny*) (iCbwBufPtr.Ptr()));
   484 		return;
   481         return;
   485 		}
   482         }
   486 
   483 
   487 	TPtrC8 aData;
   484     TPtrC8 aData;
   488 	aData.Set(&iCbwBufPtr[KCbwCbLengthOffset], KMaxCbwcbLength+1);    //prepare data for protocol starting form Length
   485     aData.Set(&iCbwBufPtr[KCbwCbLengthOffset], KMaxCbwcbLength+1);    //prepare data for protocol starting form Length
   489 	TUint8 lun = static_cast<TUint8>(iCbwBufPtr[13] & 0x0f);
   486     TUint lun = static_cast<TUint8>(iCbwBufPtr[13] & 0x0f);
   490 
   487 
   491 	iCbwTag  =	static_cast<TUint32>(iCbwBufPtr[KCbwTagOffset])		|
   488     iCbwTag  =  static_cast<TUint32>(iCbwBufPtr[KCbwTagOffset])     |
   492 				static_cast<TUint32>(iCbwBufPtr[KCbwTagOffset+1])	<<8 |
   489                 static_cast<TUint32>(iCbwBufPtr[KCbwTagOffset+1])   <<8 |
   493 				static_cast<TUint32>(iCbwBufPtr[KCbwTagOffset+2])	<<16|
   490                 static_cast<TUint32>(iCbwBufPtr[KCbwTagOffset+2])   <<16|
   494 				static_cast<TUint32>(iCbwBufPtr[KCbwTagOffset+3])	<<24;
   491                 static_cast<TUint32>(iCbwBufPtr[KCbwTagOffset+3])   <<24;
   495 
   492 
   496 	TInt i = KCbwDataTransferLengthOffset;
   493     TInt i = KCbwDataTransferLengthOffset;
   497 	TUint hostDataLength = 	static_cast<TUint32>(iCbwBufPtr[i  ])		|
   494     TUint32 hostDataLength =  static_cast<TUint32>(iCbwBufPtr[i  ])       |
   498 							static_cast<TUint32>(iCbwBufPtr[i+1]) <<8 	|
   495                             static_cast<TUint32>(iCbwBufPtr[i+1]) <<8   |
   499 							static_cast<TUint32>(iCbwBufPtr[i+2]) <<16	|
   496                             static_cast<TUint32>(iCbwBufPtr[i+2]) <<16  |
   500 							static_cast<TUint32>(iCbwBufPtr[i+3]) <<24;
   497                             static_cast<TUint32>(iCbwBufPtr[i+3]) <<24;
   501 
   498 
   502 	TBool dataToHost = iCbwBufPtr[KCbwFlagOffset] & 0x80;
   499     TBool dataToHost = iCbwBufPtr[KCbwFlagOffset] & 0x80;
   503 
   500 
   504 	__PRINT4(_L("lun =%d, hostDataLength=%d, CBWtag = 0x%x, dataToHost=%d\n"), lun, hostDataLength, iCbwTag, dataToHost);
   501     OstTrace1(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_DECODECBW,
   505 	//////////////////////////////////////////////
   502               "CBW LUN=%d", lun);
   506 	TBool ret = iProtocol->DecodePacket(aData, lun);
   503     OstTraceExt3(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_DECODECBW0,
   507 	//////////////////////////////////////////////
   504               "CBW hostDataLength=0x%x, CBWtag = 0x%x, dataToHost=%d",
   508 	ExpireData((TAny*) (iCbwBufPtr.Ptr()));
   505               hostDataLength, iCbwTag, (TUint32)dataToHost);
   509 
   506     //////////////////////////////////////////////
   510 
   507     TBool ret = iProtocol->DecodePacket(aData, lun);
   511 	iStallAllowed = ETrue;
   508     //////////////////////////////////////////////
   512 
   509     ExpireData((TAny*) (iCbwBufPtr.Ptr()));
   513 	if (!ret)
   510 
   514 		{
   511     iStallAllowed = ETrue;
   515 		__PRINT(_L("Command Failed\n"));
   512 
   516 		iCmdStatus = ECommandFailed;
   513     if (!ret)
   517 		}
   514         {
   518 	else
   515         OstTrace1(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_DECODECBW1, "ERROR: DecodePacket err=%d", ret);
   519 		{
   516         iCmdStatus = ECommandFailed;
   520 		__PRINT(_L("Command Passed\n"));
   517         }
   521 		iCmdStatus = ECommandPassed;
   518     else
   522 		}
   519         {
   523 
   520         OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW2, "ERROR: DecodePacket OK");
   524 	if (hostDataLength)    // Host  expected data transfer
   521         iCmdStatus = ECommandPassed;
   525 		{
   522         }
   526 		if (dataToHost)  // send data to host
   523 
   527 			{
   524     if (hostDataLength)    // Host  expected data transfer
   528 			if (!iWriteSetUp) //write buffer was not set up
   525         {
   529 				{
   526         if (dataToHost)  // send data to host
   530 				__PRINT(_L("Write buffer was not setup\n"));
   527             {
   531 				iDataResidue =hostDataLength;
   528             if (!iWriteSetUp) //write buffer was not set up
   532 				__PRINT1(_L("DataResidue (write to host)=%d\n"),iDataResidue);
   529                 {
       
   530                 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW3, "Write buffer was not setup");
       
   531                 iDataResidue =hostDataLength;
       
   532                 OstTrace1(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW4, "DataResidue (write to host)=%d", iDataResidue);
   533 
   533 
   534 //------------------------------------
   534 //------------------------------------
   535 				if (hostDataLength <= KBOTMaxBufSize)
   535                 if (hostDataLength <= KBOTMaxBufSize)
   536 					{
   536                     {
   537 					__PRINT(_L("Case 4 or 8\n"));
   537                     OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW5, "Case 4 or 8");
   538 					SetPaddingBufPtr(hostDataLength);
   538                     SetPaddingBufPtr(hostDataLength);
   539 					iPaddingBufPtr.FillZ(hostDataLength);
   539                     iPaddingBufPtr.FillZ(hostDataLength);
   540 					TPtrC8 ptr(NULL, 0);
   540                     TPtrC8 ptr(NULL, 0);
   541 					ptr.Set((TUint8*)iPaddingBufPtr.Ptr(), hostDataLength);
   541                     ptr.Set((TUint8*)iPaddingBufPtr.Ptr(), hostDataLength);
   542 					WriteData(iStatus, ptr, hostDataLength, EFalse);
   542                     WriteData(iStatus, ptr, hostDataLength, EFalse);
   543 					iStallAllowed = EFalse;
   543                     iStallAllowed = EFalse;
   544 					if (iReadSetUp)  //read buffer WAS set up - case (8)
   544                     if (iReadSetUp)  //read buffer WAS set up - case (8)
   545 						{
   545                         {
   546 						__PRINT(_L("It is Case 8\n"));
   546                         OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW6, "It is Case 8");
   547 						iCmdStatus = EPhaseError;
   547                         iCmdStatus = EPhaseError;
   548 						}
   548                         }
   549 					return;
   549                     return;
   550 					}
   550                     }
   551 				else
   551                 else
   552 //------------------------------------
   552 //------------------------------------
   553 //					Use next block instead of StallEndpointAndWaitForClear(InEndpoint);
   553 //                  Use next block instead of StallEndpointAndWaitForClear(InEndpoint);
   554 					{
   554                     {
   555 					SetPaddingBufPtr(hostDataLength);
   555                     SetPaddingBufPtr(hostDataLength);
   556 					iPaddingBufPtr.FillZ(KBOTMaxBufSize);
   556                     iPaddingBufPtr.FillZ(KBOTMaxBufSize);
   557 					TUint c =0;
   557                     TUint c =0;
   558 					TRequestStatus status;
   558                     TRequestStatus status;
   559 					while (c<hostDataLength)
   559                     while (c<hostDataLength)
   560 						{
   560                         {
   561 						TInt len;
   561                         TInt len;
   562 						if (hostDataLength - c >  KBOTMaxBufSize)
   562                         if (hostDataLength - c >  KBOTMaxBufSize)
   563 							{
   563                             {
   564 							len = KBOTMaxBufSize;
   564                             len = KBOTMaxBufSize;
   565 							}
   565                             }
   566 						else
   566                         else
   567 							{
   567                             {
   568 							len = hostDataLength - c;
   568                             len = hostDataLength - c;
   569 							}
   569                             }
   570 
   570 
   571 							TPtrC8 ptr(NULL, 0);
   571                             TPtrC8 ptr(NULL, 0);
   572 							ptr.Set((TUint8*)iPaddingBufPtr.Ptr(), len);
   572                             ptr.Set((TUint8*)iPaddingBufPtr.Ptr(), len);
   573 							WriteUsb(status, ptr, len);
   573                             WriteUsb(status, ptr, len);
   574 							User::WaitForRequest(status);
   574                             User::WaitForRequest(status);
   575 							c +=  KBOTMaxBufSize;
   575                             c +=  KBOTMaxBufSize;
   576 						}
   576                         }
   577 					}
   577                     }
   578 
   578 
   579 				if (iReadSetUp)  //read buffer WAS set up - case (8)
   579                 if (iReadSetUp)  //read buffer WAS set up - case (8)
   580 					{
   580                     {
   581 					__PRINT(_L("Case 8\n"));
   581                     OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW7, "Case 8");
   582 					SendCSW(iCbwTag, hostDataLength, EPhaseError);
   582                     SendCSW(iCbwTag, hostDataLength, EPhaseError);
   583 					  //don't care to reset any flag - should get reset recovery
   583                       //don't care to reset any flag - should get reset recovery
   584 					}
   584                     }
   585 				else   // case (4)
   585                 else   // case (4)
   586 					{
   586                     {
   587 					__PRINT(_L("Case 4\n"));
   587                     OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW8, "Case 4");
   588 					SendCSW(iCbwTag, hostDataLength, iCmdStatus);
   588                     SendCSW(iCbwTag, hostDataLength, iCmdStatus);
   589 					}
   589                     }
   590 				return;
   590                 return;
   591 				}	// if (!iWriteSetUp)
   591                 }   // if (!iWriteSetUp)
   592 
   592 
   593 //==================
   593 //==================
   594 			TUint deviceDataLength = static_cast<TUint>(iWriteBufPtr.Length());
   594             TUint32 deviceDataLength = iWriteBufPtr.Length();
   595 			iDataResidue =hostDataLength - deviceDataLength ;
   595             iDataResidue =hostDataLength - deviceDataLength ;
   596 			__PRINT2(_L("Device data length = %d, DataResidue (write to host)=%d\n"), deviceDataLength, iDataResidue);
   596             OstTraceExt2(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW9,
   597 
   597                          "Device data length = 0x%x, DataResidue (write to host)=0x%x", deviceDataLength, iDataResidue);
   598 			if (deviceDataLength < hostDataLength  &&
   598 
   599 				hostDataLength < KBOTMaxBufSize )
   599             if (deviceDataLength < hostDataLength  &&
   600 					{
   600                 hostDataLength < KBOTMaxBufSize )
   601 					__PRINT(_L("Case 5 (padding)\n"));
   601                     {
   602 					SetPaddingBufPtr(hostDataLength);
   602                     OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW10, "Case 5 (padding)");
   603 					iPaddingBufPtr.Zero();
   603                     SetPaddingBufPtr(hostDataLength);
   604 					iPaddingBufPtr.Append(iWriteBufPtr);
   604                     iPaddingBufPtr.Zero();
   605 					iStallAllowed = EFalse;
   605                     iPaddingBufPtr.Append(iWriteBufPtr);
   606 					__PRINT1(_L("iPaddingBufPtr.Length = %d\n"),iPaddingBufPtr.Length());
   606                     iStallAllowed = EFalse;
   607 					TPtrC8 ptr(NULL, 0);
   607                     OstTrace1(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW11,
   608 					ptr.Set((TUint8*)iPaddingBufPtr.Ptr(), hostDataLength);
   608                               "iPaddingBufPtr.Length = 0x%x",
   609 					WriteData(iStatus, ptr, hostDataLength, EFalse);
   609                               iPaddingBufPtr.Length());
   610 					return;
   610                     TPtrC8 ptr(NULL, 0);
   611 					}
   611                     ptr.Set((TUint8*)iPaddingBufPtr.Ptr(), hostDataLength);
       
   612                     WriteData(iStatus, ptr, hostDataLength, EFalse);
       
   613                     return;
       
   614                     }
   612 
   615 
   613 //===================
   616 //===================
   614 
   617 
   615 			if (deviceDataLength == hostDataLength)  	//case (6)[==]
   618             if (deviceDataLength == hostDataLength)     //case (6)[==]
   616 				{
   619                 {
   617 				__PRINT(_L("Case 6\n"));
   620                 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW12, "Case 6");
   618 				WriteData(iStatus, iWriteBufPtr, deviceDataLength);
   621                 WriteData(iStatus, iWriteBufPtr, deviceDataLength);
   619 				return;
   622                 return;
   620 				}
   623                 }
   621 			else if (deviceDataLength < hostDataLength)	//case (5)[<]
   624             else if (deviceDataLength < hostDataLength) //case (5)[<]
   622 				{
   625                 {
   623 				__PRINT(_L("Case 5\n"));
   626                 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW13, "Case 5");
   624 				WriteData(iStatus, iWriteBufPtr, deviceDataLength, ETrue);		// Send ZLP
   627                 WriteData(iStatus, iWriteBufPtr, deviceDataLength, ETrue);      // Send ZLP
   625 				return;
   628                 return;
   626 				}
   629                 }
   627 			else 										// deviceDataLength > hostDataLength - case (7)
   630             else                                        // deviceDataLength > hostDataLength - case (7)
   628 				{
   631                 {
   629 				__PRINT(_L("Case 7\n"));
   632                 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW14, "Case 7");
   630 				iCmdStatus = EPhaseError;
   633                 iCmdStatus = EPhaseError;
   631 				iDataResidue = 0;
   634                 iDataResidue = 0;
   632 				WriteData(iStatus, iWriteBufPtr, hostDataLength);
   635                 WriteData(iStatus, iWriteBufPtr, hostDataLength);
   633 				return;
   636                 return;
   634 				}
   637                 }
   635 			}
   638             }
   636 		else  //read data from host
   639         else  //read data from host
   637 			{
   640             {
   638 			if (!iReadSetUp)
   641             if (!iReadSetUp)
   639 				{
   642                 {
   640 				iDataResidue = hostDataLength;
   643                 iDataResidue = hostDataLength;
   641 				__PRINT(_L("Read buffer was not setup\n"));
   644                 OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_DECODECBW15, "Read buffer was not setup");
   642 //				Use next block instead of StallEndpointAndWaitForClear(OutEndpoint);
   645 //              Use next block instead of StallEndpointAndWaitForClear(OutEndpoint);
   643 				DiscardData(hostDataLength);
   646                 DiscardData(hostDataLength);
   644 
   647 
   645 				if (iWriteSetUp) //case (10)
   648                 if (iWriteSetUp) //case (10)
   646 					{
   649                     {
   647 					__PRINT(_L("case 10\n"));
   650                     OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW16, "case 10");
   648 					SendCSW(iCbwTag, hostDataLength, EPhaseError);
   651                     SendCSW(iCbwTag, hostDataLength, EPhaseError);
   649 					}
   652                     }
   650 				else // case (9)
   653                 else // case (9)
   651 					{
   654                     {
   652 					__PRINT(_L("Case 9\n"));
   655                     OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW17, "Case 9");
   653 					SendCSW(iCbwTag, hostDataLength, iCmdStatus);
   656                     SendCSW(iCbwTag, hostDataLength, iCmdStatus);
   654 					}
   657                     }
   655 
   658 
   656 				return;
   659                 return;
   657 				}
   660                 }
   658 
   661 
   659 			TUint deviceDataLength = iBufSize;
   662             TUint32 deviceDataLength = iBufSize;
   660 			iDataResidue = hostDataLength;  // calculate residue later
   663             iDataResidue = hostDataLength;  // calculate residue later
   661 
   664 
   662 			__PRINT2(_L("deviceDataLength = iBufSize = %d, DataResidue = HDL for now (read from host) =%d\n"),deviceDataLength,iDataResidue);
   665             OstTraceExt2(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW18,
   663 
   666                       "deviceDataLength = iBufSize = 0x%x, DataResidue = HDL for now (read from host) =0x%x",
   664 			if (deviceDataLength <= hostDataLength)  // case (11) and (12)
   667                       deviceDataLength, iDataResidue);
   665 				{
   668 
   666 				__PRINT(_L("Case 11 or 12\n"));
   669             if (deviceDataLength <= hostDataLength)  // case (11) and (12)
   667 				ReadData(deviceDataLength);
   670                 {
   668 				return;
   671                 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW19, "Case 11 or 12");
   669 				}
   672                 ReadData(deviceDataLength);
   670 			if (deviceDataLength > hostDataLength) // case  (13)
   673                 return;
   671 				{
   674                 }
   672 				__PRINT(_L("Case 13\n"));
   675             if (deviceDataLength > hostDataLength) // case  (13)
       
   676                 {
       
   677                 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW20, "Case 13");
   673                 /**
   678                 /**
   674                  * Comment following line in order to pass compliant test.
   679                  * Comment following line in order to pass compliant test.
   675                  * As spec said in case 13:"The device may receive data up to a
   680                  * As spec said in case 13:"The device may receive data up to a
   676                  * total of dCBWDataTransferLength."
   681                  * total of dCBWDataTransferLength."
   677                  * Here we choose to ignore incoming data.
   682                  * Here we choose to ignore incoming data.
   678                  */
   683                  */
   679 				//StallEndpointAndWaitForClear(OutEndpoint); //Stall Out endpoint
   684                 //StallEndpointAndWaitForClear(OutEndpoint); //Stall Out endpoint
   680                 if (iReadSetUp)
   685                 if (iReadSetUp)
   681                     {
   686                     {
   682 					WriteToClient(hostDataLength);
   687                     WriteToClient(hostDataLength);
   683                     iReadSetUp = EFalse;
   688                     iReadSetUp = EFalse;
   684                     }
   689                     }
   685                 SendCSW(iCbwTag, hostDataLength, EPhaseError);
   690                 SendCSW(iCbwTag, hostDataLength, EPhaseError);
   686 				return;
   691                 return;
   687 				}
   692                 }
   688 			}
   693             }
   689 		}
   694         }
   690 	else  // Host expected no data transfer
   695     else  // Host expected no data transfer
   691 		{
   696         {
   692 		__PRINT(_L("No data transfer expected\n"));
   697         OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW21, "No data transfer expected");
   693 		iDataResidue = 0;
   698         iDataResidue = 0;
   694 		if (iWriteSetUp || iReadSetUp)   // case (2) and (3)
   699         if (iWriteSetUp || iReadSetUp)   // case (2) and (3)
   695 			{
   700             {
   696 			__PRINT(_L("Case 2 or 3\n"));
   701             OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW22, "Case 2 or 3");
   697 			SendCSW(iCbwTag, 0, EPhaseError);
   702             SendCSW(iCbwTag, 0, EPhaseError);
   698 			}
   703             }
   699 		else
   704         else
   700 			{
   705             {
   701 			__PRINT(_L("Case 1\n"));
   706             OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW23, "Case 1");
   702 			SendCSW(iCbwTag, 0, iCmdStatus);  //case (1)
   707             SendCSW(iCbwTag, 0, iCmdStatus);  //case (1)
   703 			}
   708             }
   704 		}
   709         }
   705 	}
   710     }
   706 
   711 
   707 
   712 
   708 /**
   713 /**
   709 Check if CBW Valid and Meaningful.
   714 Check if CBW Valid and Meaningful.
   710 
   715 
   711 @return ETrue if CBW is Valid and Meaningful, EFalse otherwise
   716 @return ETrue if CBW is Valid and Meaningful, EFalse otherwise
   712 */
   717 */
   713 TBool CBulkOnlyTransport::CheckCBW()
   718 TBool CBulkOnlyTransport::CheckCBW()
   714 	{
   719     {
   715 	__FNLOG("CBulkOnlyTransport::CheckCBW");
       
   716 
       
   717     //
   720     //
   718     // Check valid
   721     // Check valid
   719     //
   722     //
   720 
   723 
   721     // Check length
   724     // Check length
   722     if ((TUint) (iCbwBufPtr.Length()) != KCbwLength)
   725     if ((TUint) (iCbwBufPtr.Length()) != KCbwLength)
   723         {
   726         {
   724 		__PRINT2(_L("Bad length: %d != KCbwLength"), iCbwBufPtr.Length(), KCbwLength);
   727         OstTrace1(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_CHECKCBW, "ERROR Bad length: 0x%x != KCbwLength", iCbwBufPtr.Length());
   725 		return EFalse;
   728         return EFalse;
   726         }
   729         }
   727 
   730 
   728     // Check signature
   731     // Check signature
   729 	TInt i = KCbwSignatureOffset;
   732     TInt i = KCbwSignatureOffset;
   730 	if (iCbwBufPtr[i  ] != 0x55 ||         // CBW Singature from USB Bulk-Only Transport spec
   733     if (iCbwBufPtr[i  ] != 0x55 ||         // CBW Singature from USB Bulk-Only Transport spec
   731 		iCbwBufPtr[i+1] != 0x53 ||
   734         iCbwBufPtr[i+1] != 0x53 ||
   732 		iCbwBufPtr[i+2] != 0x42 ||
   735         iCbwBufPtr[i+2] != 0x42 ||
   733 		iCbwBufPtr[i+3] != 0x43)
   736         iCbwBufPtr[i+3] != 0x43)
   734 		{
   737         {
   735 		__PRINT(_L("Bad signature"));
   738         OstTraceData(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_CHECKCBW1,
   736 		__PRINT4(_L(" 0x%x, 0x%x, 0x%x, 0x%x \n"), iCbwBufPtr[i], iCbwBufPtr[i+1], iCbwBufPtr[i+2],iCbwBufPtr[i+3])
   739                      "CBW ERROR: Bad signature %s", &iCbwBufPtr[i], 4);
   737 		return EFalse;
   740         return EFalse;
   738 		}
   741         }
   739 
   742 
   740     //
   743     //
   741     // Check meaningful
   744     // Check meaningful
   742     //
   745     //
   743 
   746 
   744     // Check reserved bits ( must be zero )
   747     // Check reserved bits ( must be zero )
   745     if ((iCbwBufPtr[KCbwLunOffset] & 0xF0) || (iCbwBufPtr[KCbwCbLengthOffset] & 0xE0))
   748     if ((iCbwBufPtr[KCbwLunOffset] & 0xF0) || (iCbwBufPtr[KCbwCbLengthOffset] & 0xE0))
   746 		{
   749         {
   747 		__PRINT(_L("Reserved bits not zero\n"));
   750         OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_CHECKCBW2, "CBW ERROR: Reserved bits not zero");
   748 		return EFalse;
   751         return EFalse;
   749 		}
   752         }
   750 
   753 
   751 	// check command block length
   754     // check command block length
   752 	TInt cbwcbLength = iCbwBufPtr[KCbwCbLengthOffset] & 0x1F;
   755     TInt cbwcbLength = iCbwBufPtr[KCbwCbLengthOffset] & 0x1F;
   753 	if (cbwcbLength >KMaxCbwcbLength)
   756     if (cbwcbLength >KMaxCbwcbLength)
   754 		{
   757         {
   755 		__PRINT(_L("Incorrect block length\n"));
   758         OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_CHECKCBW3, "CBW ERROR: Incorrect block length");
   756 		return EFalse;
   759         return EFalse;
   757 		}
   760         }
   758 
   761 
   759 	//check LUN
   762     //check LUN
   760 	TInt8 lun = static_cast<TUint8>(iCbwBufPtr[KCbwLunOffset] & 0x0f);
   763     TInt8 lun = static_cast<TUint8>(iCbwBufPtr[KCbwLunOffset] & 0x0f);
   761 	if (iMaxLun < lun)
   764     if (iMaxLun < lun)
   762 		{
   765         {
   763 		RDebug::Print(_L("bad lun: %d"), lun);
   766         OstTrace1(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_CHECKCBW4, "CBW ERROR: bad lun: %d", lun);
   764 		return EFalse;
   767         return EFalse;
   765 		}
   768         }
   766 
   769 
   767 	return ETrue;
   770     return ETrue;
   768 	}
   771     }
   769 
   772 
   770 
   773 
   771 /**
   774 /**
   772 Initiate stalling of bulk IN endpoint.
   775 Initiate stalling of bulk IN endpoint.
   773 Used when protocol wants to force host to initiate a reset recovery.
   776 Used when protocol wants to force host to initiate a reset recovery.
   774 */
   777 */
   775 void CBulkOnlyTransport::SetPermError()
   778 void CBulkOnlyTransport::SetPermError()
   776 	{
   779     {
   777 	__FNLOG("CBulkOnlyTransport::SetPermError");
       
   778     iCurrentState = EPermErr;
   780     iCurrentState = EPermErr;
   779     Activate(KErrNone);
   781     Activate(KErrNone);
   780 	}
   782     }
   781 
   783 
   782 
   784 
   783 /**
   785 /**
   784 Send data provided by protocol to the host
   786 Send data provided by protocol to the host
   785 
   787 
   786 @param aLength amount of data (in bytes) to be send to host
   788 @param aLength amount of data (in bytes) to be send to host
   787 */
   789 */
   788 void CBulkOnlyTransport::WriteData(TRequestStatus& aStatus, TPtrC8& aDes, TUint aLength, TBool aZlpRequired)
   790 void CBulkOnlyTransport::WriteData(TRequestStatus& aStatus, TPtrC8& aDes, TUint aLength, TBool aZlpRequired)
   789 	{
   791     {
   790 	__FNLOG("CBulkOnlyTransport::WriteData");
   792     if (IsActive())
   791 
   793         {
   792 	if (IsActive())
   794         __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
   793 		{
   795         return;
   794 		__PRINT(_L("Still active\n"));
   796         }
   795 		__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
   797     WriteUsb(aStatus, aDes, aLength, aZlpRequired);
   796 		return;
   798     iCurrentState = EWritingData;
   797 		}
   799     SetActive();
   798 	WriteUsb(aStatus, aDes, aLength, aZlpRequired);
   800     }
   799 	iCurrentState = EWritingData;
       
   800 	SetActive();
       
   801 	}
       
   802 
   801 
   803 
   802 
   804 /**
   803 /**
   805 Send Command Status Wrapper to the host
   804 Send Command Status Wrapper to the host
   806 
   805 
   808 @param aDataResidue the difference between the amount of data expected by the
   807 @param aDataResidue the difference between the amount of data expected by the
   809        host, and the actual amount of data processed by the device.
   808        host, and the actual amount of data processed by the device.
   810 @param aStatus indicates the success or failure of the command.
   809 @param aStatus indicates the success or failure of the command.
   811 */
   810 */
   812 void CBulkOnlyTransport::SendCSW(TUint aTag, TUint aDataResidue, TCswStatus aStatus)
   811 void CBulkOnlyTransport::SendCSW(TUint aTag, TUint aDataResidue, TCswStatus aStatus)
   813 	{
   812     {
   814 	__FNLOG("CBulkOnlyTransport::SendCSW");
   813     OstTraceExt2(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_SENDCSW,
   815 	__PRINT2(_L("DataResidue = %d, Status = %d \n"), aDataResidue, aStatus);
   814               "CSW DataResidue = 0x%x, Status = %d", aDataResidue, aStatus);
   816 
   815 
   817 	if (IsActive())
   816     if (IsActive())
   818 		{
   817         {
   819 		__PRINT(_L("Still active\n"));
   818         __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
   820 		__ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive));
   819         return;
   821 		return;
   820         }
   822 		}
   821 
   823 
   822     SetCswBufPtr(KCswLength);
   824 	SetCswBufPtr(KCswLength);
   823     TInt i = KCswSingnatureOffset;
   825 	TInt i = KCswSingnatureOffset;
   824     iCswBufPtr[i  ] = 0x55;   // CSW Singature from USB Bulk-Only Transport spec
   826 	iCswBufPtr[i  ] = 0x55;   // CSW Singature from USB Bulk-Only Transport spec
   825     iCswBufPtr[i+1] = 0x53;
   827 	iCswBufPtr[i+1] = 0x53;
   826     iCswBufPtr[i+2] = 0x42;
   828 	iCswBufPtr[i+2] = 0x42;
   827     iCswBufPtr[i+3] = 0x53;
   829 	iCswBufPtr[i+3] = 0x53;
   828 
   830 
   829     i = KCswTagOffset;
   831 	i = KCswTagOffset;
   830 
   832 
   831     iCswBufPtr[i  ] = static_cast<TUint8>((aTag & 0x000000FF));
   833 	iCswBufPtr[i  ] = static_cast<TUint8>((aTag & 0x000000FF));
   832     iCswBufPtr[i+1] = static_cast<TUint8>((aTag & 0x0000FF00) >> 8);
   834 	iCswBufPtr[i+1] = static_cast<TUint8>((aTag & 0x0000FF00) >> 8);
   833     iCswBufPtr[i+2] = static_cast<TUint8>((aTag & 0x00FF0000) >> 16);
   835 	iCswBufPtr[i+2] = static_cast<TUint8>((aTag & 0x00FF0000) >> 16);
   834     iCswBufPtr[i+3] = static_cast<TUint8>((aTag & 0xFF000000) >> 24);
   836 	iCswBufPtr[i+3] = static_cast<TUint8>((aTag & 0xFF000000) >> 24);
   835 
   837 
   836     i = KCswDataResidueOffset;
   838 	i = KCswDataResidueOffset;
   837     iCswBufPtr[i  ] = static_cast<TUint8>((aDataResidue & 0x000000FF));
   839 	iCswBufPtr[i  ] = static_cast<TUint8>((aDataResidue & 0x000000FF));
   838     iCswBufPtr[i+1] = static_cast<TUint8>((aDataResidue & 0x0000FF00) >> 8);
   840 	iCswBufPtr[i+1] = static_cast<TUint8>((aDataResidue & 0x0000FF00) >> 8);
   839     iCswBufPtr[i+2] = static_cast<TUint8>((aDataResidue & 0x00FF0000) >> 16);
   841 	iCswBufPtr[i+2] = static_cast<TUint8>((aDataResidue & 0x00FF0000) >> 16);
   840     iCswBufPtr[i+3] = static_cast<TUint8>((aDataResidue & 0xFF000000) >> 24);
   842 	iCswBufPtr[i+3] = static_cast<TUint8>((aDataResidue & 0xFF000000) >> 24);
   841 
   843 
   842     iCswBufPtr[KCswStatusOffset] = static_cast<TUint8>(aStatus);
   844 	iCswBufPtr[KCswStatusOffset] = static_cast<TUint8>(aStatus);
   843 
   845 
   844     TPtrC8 ptr(NULL, 0);
   846 	TPtrC8 ptr(NULL, 0);
   845     ptr.Set((const TUint8*)iCswBufPtr.Ptr(), KCswLength);
   847 	ptr.Set((const TUint8*)iCswBufPtr.Ptr(), KCswLength);
   846 
   848 
   847     WriteUsb(iStatus, ptr, KCswLength);
   849 	WriteUsb(iStatus, ptr, KCswLength);
   848 
   850 
   849     iCurrentState = ESendingCSW;
   851 	iCurrentState = ESendingCSW;
   850 
   852 
   851     SetActive();
   853 	SetActive();
   852     }
   854 	}
       
   855 
   853 
   856 
   854 
   857 /**
   855 /**
   858 Associates the transport with the protocol.  Called during initialization of the controller.
   856 Associates the transport with the protocol.  Called during initialization of the controller.
   859 
   857 
   860 @param aProtocol reference to the protocol
   858 @param aProtocol reference to the protocol
   861 */
   859 */
   862 void CBulkOnlyTransport::RegisterProtocol(MProtocolBase& aProtocol)
   860 void CBulkOnlyTransport::RegisterProtocol(MProtocolBase& aProtocol)
   863 	{
   861     {
   864 	__FNLOG("CBulkOnlyTransport::RegisterProtocol");
   862     iProtocol = &aProtocol;
   865 	iProtocol = &aProtocol;
   863     }
   866 	}
       
   867 
   864 
   868 
   865 
   869 /**
   866 /**
   870 Used by CControlInterface
   867 Used by CControlInterface
   871 
   868 
   872 @return reference to the controller which instantiate the CBulkOnlyTransport
   869 @return reference to the controller which instantiate the CBulkOnlyTransport
   873 */
   870 */
   874 CUsbMassStorageController& CBulkOnlyTransport::Controller()
   871 CUsbMassStorageController& CBulkOnlyTransport::Controller()
   875 	{
   872     {
   876 	return iController;
   873     return iController;
   877 	}
   874     }
   878 
   875 
   879 
   876 
   880 /**
   877 /**
   881 @return the number of logical units supported by the device.
   878 @return the number of logical units supported by the device.
   882 Logical Unit Numbers on the device shall be numbered contiguously starting from LUN
   879 Logical Unit Numbers on the device shall be numbered contiguously starting from LUN
   883 0 to a maximum LUN of 15 (Fh).
   880 0 to a maximum LUN of 15 (Fh).
   884 */
   881 */
   885 TInt CBulkOnlyTransport::MaxLun()
   882 TInt CBulkOnlyTransport::MaxLun()
   886 	{
   883     {
   887 	return iMaxLun;
   884     return iMaxLun;
   888 	}
   885     }
   889 
   886 
   890 
   887 
   891 void CBulkOnlyTransport::GetCommandBufPtr(TPtr8& aDes, TUint aLength) // Set pointer to buffer of specified aLength for command
   888 void CBulkOnlyTransport::GetCommandBufPtr(TPtr8& aDes, TUint aLength) // Set pointer to buffer of specified aLength for command
   892 	{
   889     {
   893 	aDes.Set(SetCommandBufPtr(aLength));
   890     aDes.Set(SetCommandBufPtr(aLength));
   894 	}
   891     }
   895 
   892 
   896 void CBulkOnlyTransport::GetReadDataBufPtr(TPtr8& aDes) // Set pointer to buffer into which data is to be read from drive (Read10)
   893 void CBulkOnlyTransport::GetReadDataBufPtr(TPtr8& aDes) // Set pointer to buffer into which data is to be read from drive (Read10)
   897 	{
   894     {
   898 	aDes.Set(SetDataBufPtr());
   895     aDes.Set(SetDataBufPtr());
   899 	}
   896     }
   900 
   897 
   901 
   898 
   902 void CBulkOnlyTransport::GetWriteDataBufPtr(TPtrC8& aDes) // Set pointer to buffer from which data is to be written to drive (Write10)
   899 void CBulkOnlyTransport::GetWriteDataBufPtr(TPtrC8& aDes) // Set pointer to buffer from which data is to be written to drive (Write10)
   903 	{
   900     {
   904 	aDes.Set(iReadBufPtr);
   901     aDes.Set(iReadBufPtr);
   905 	}
   902     }
   906 
   903 
   907 #ifdef MSDC_MULTITHREADED
   904 #ifdef MSDC_MULTITHREADED
   908 void CBulkOnlyTransport::ProcessReadData(TAny* aAddress)
   905 void CBulkOnlyTransport::ProcessReadData(TAny* aAddress)
   909 	{
   906     {
   910 	ExpireData(aAddress);
   907     ExpireData(aAddress);
   911 	}
   908     }
   912 #endif
   909 #endif
   913 
   910 
   914 
   911 
   915 
   912 
   916 
   913