os/kernelhwsrv/userlibandfileserver/fileserver/smassstorage/drivepublisher.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2007-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 // Class implementation of the drive publishing classes -  
    15 // RDriveMediaErrorPublisher,
    16 // RDriveStateChangedPublisher, 
    17 // CDriveTransferPublisher,
    18 // CDriveWriteTransferPublisher,
    19 // CDriveReadTransferPublisher,
    20 // CUsbTransferPublisher,
    21 // CUsbReadTransferPublisher,
    22 // CUsbReadTransferPublisher.
    23 // 
    24 //
    25 
    26 /**
    27  @file
    28  @internalTechnology
    29 */
    30 
    31 #include "massstoragedebug.h"
    32 #include "drivepublisher.h"
    33 #include "drivemanager.h"
    34 
    35 
    36 // 
    37 // Use Lookup table to translate from the internal pair of state variables
    38 // to the externally published drive state code.
    39 //
    40 LOCAL_D	const TUint8 table[][5] =
    41 {
    42 //TMountState=EDisconnected
    43 	{EUsbMsDriveState_Disconnected, 
    44 	 EUsbMsDriveState_Disconnected, 
    45 	 EUsbMsDriveState_Disconnected, 
    46 	 EUsbMsDriveState_Disconnected, 
    47 	 EUsbMsDriveState_Disconnected},
    48 //TMountState=EConnecting
    49 	{EUsbMsDriveState_Connecting,
    50 	 EUsbMsDriveState_Connecting, 
    51 	 EUsbMsDriveState_Connecting, 
    52 	 EUsbMsDriveState_Connecting, 
    53 	 EUsbMsDriveState_Connecting},
    54 //TMountState=EConnected
    55 	//EIdle,EActive,ELocked,EMediaNotPresent,EErrDisMounted
    56 	{EUsbMsDriveState_Connected, 
    57 	 EUsbMsDriveState_Active, 
    58 	 EUsbMsDriveState_Locked, 
    59 	 EUsbMsDriveState_MediaNotPresent, 
    60 	 EUsbMsDriveState_Removed},
    61 //TMountState=EDisconnecting
    62 	{EUsbMsDriveState_Disconnecting, 
    63 	 EUsbMsDriveState_Disconnecting, 
    64 	 EUsbMsDriveState_Disconnecting, 
    65 	 EUsbMsDriveState_Disconnecting, 
    66 	 EUsbMsDriveState_Disconnecting}
    67 };
    68 
    69 
    70 //----------------------------------------------------------------------------
    71 /**
    72 Constructor
    73 */
    74 RDriveMediaErrorPublisher::RDriveMediaErrorPublisher()
    75 	{
    76 	__FNLOG("RDriveMediaErrorPublisher::RDriveMediaErrorPublisher()");
    77 
    78 	_LIT_SECURITY_POLICY_PASS(KMassStorageReadPolicy);
    79 	_LIT_SECURITY_POLICY_S0(KMassStorageWritePolicy, KUsbMsDriveState_Category.iUid);
    80 
    81 	TInt result = RProperty::Define(EUsbMsDriveState_MediaError, RProperty::EInt,
    82 									KMassStorageReadPolicy, KMassStorageWritePolicy);
    83    
    84 	__ASSERT_DEBUG(result == KErrAlreadyExists || result == KErrNone, User::Invariant());
    85    
    86 	result = iMediaErrorProperty.Attach(KUsbMsDriveState_Category, EUsbMsDriveState_MediaError);
    87 	__ASSERT_DEBUG(result == KErrNone, User::Invariant());
    88 	}
    89 
    90 
    91 RDriveMediaErrorPublisher::~RDriveMediaErrorPublisher()
    92 	{
    93 	__FNLOG("RDriveStatePublisher::~RDriveStatePublisher()");
    94 
    95 	iMediaErrorProperty.Close();
    96 	RProperty::Delete(KUsbMsDriveState_Category, EUsbMsDriveState_MediaError);
    97 	}
    98 
    99 /**
   100 Publishing method
   101 
   102 Publishes the Media Error property event
   103 
   104 @param aError ETrue if drive media has an error else EFalse for no error
   105 */
   106 void RDriveMediaErrorPublisher::PublishError(TBool aError)
   107 	{
   108 	__PRINT1(_L("<< RDriveMediaErrorPublisher::PublishError %x"), aError);
   109 
   110 	TInt oldValue;
   111 	iMediaErrorProperty.Get(oldValue);
   112 
   113 	if (oldValue != aError)
   114 		{
   115 		User::LeaveIfError(iMediaErrorProperty.Set(aError));
   116 		}
   117 	}
   118 
   119 //----------------------------------------------------------------------------
   120 /**
   121 Constructor
   122 
   123 @param aDrives
   124 @param aDriveMap
   125 */
   126 RDriveStateChangedPublisher::RDriveStateChangedPublisher(TRefMsDriveList aDrives,
   127 														 TRefDriveMap aDriveMap)
   128 	:
   129 	iDrives(aDrives),
   130 	iDriveMap(aDriveMap)
   131 	{
   132 	__FNLOG("RDriveStateChangedPublisher::RDriveStateChangedPublisher()");
   133 
   134 	_LIT_SECURITY_POLICY_PASS(KMassStorageReadPolicy);
   135 	_LIT_SECURITY_POLICY_S0(KMassStorageWritePolicy, KUsbMsDriveState_Category.iUid);
   136 
   137 	TInt result = RProperty::Define(KUsbMsDriveState_Category,
   138 									EUsbMsDriveState_DriveStatus, RProperty::EByteArray,
   139 									KMassStorageReadPolicy, KMassStorageWritePolicy,
   140 									KUsbMsMaxDrives*2);
   141 	__ASSERT_DEBUG(result == KErrAlreadyExists || result == KErrNone, User::Invariant());
   142 	result = result;	// remove urel warning
   143 	}
   144 
   145 
   146 RDriveStateChangedPublisher::~RDriveStateChangedPublisher()
   147 	{
   148 	__FNLOG("RDriveStateChangedPublisher::~RDriveStateChangedPublisher()");
   149 
   150 	RProperty::Delete(KUsbMsDriveState_Category, EUsbMsDriveState_DriveStatus);
   151 	}
   152 
   153 
   154 /**
   155 Publishing method
   156 
   157 Sends a property event on behalf of CMassStorageDrive, with the mountstate and drivestate 
   158 values encoded into one 32-bit word.
   159 */
   160 void RDriveStateChangedPublisher::DriveStateChanged()
   161 	{
   162 	__FNLOG("RDriveStateChangedPublisher::DriveStateChanged");
   163 
   164 
   165 	TUsbMsDrivesStatus allDrivesStatus;
   166 	for(TUint8 i=0; i<KUsbMsMaxDrives && iDrives[i]; i++)
   167 		{
   168 		allDrivesStatus.Append(iDriveMap[i]); 
   169 
   170 		CMassStorageDrive::TMountState ms = iDrives[i]->MountState();
   171 		CMassStorageDrive::TDriveState ds = iDrives[i]->DriveState();
   172 		TInt driveStatus = EUsbMsDriveState_Error;
   173 		if((TUint8)ds < sizeof(table[0]) && (TUint8)ms < sizeof(table)/sizeof(table[0]))
   174 			{
   175 			driveStatus = table[ms][ds];
   176 			__PRINT3(_L("ms=%d ds=%d %d"), ms, ds, driveStatus);
   177 			}
   178 		allDrivesStatus.Append(driveStatus);
   179 		}
   180 
   181 	__PRINT1(_L("Publishing EUsbMsDriveState_DriveStatus for %d drives\n"),
   182 				allDrivesStatus.Length()/2);
   183 
   184 	if(KErrNone != RProperty::Set(KUsbMsDriveState_Category,
   185 								  EUsbMsDriveState_DriveStatus, 
   186 								  allDrivesStatus))
   187 		{
   188 		__ASSERT_DEBUG(EFalse,User::Invariant());
   189 		}
   190 	}
   191 
   192 
   193 //----------------------------------------------------------------------------
   194 #ifndef USB_TRANSFER_PUBLISHER
   195 /**
   196 Private default constructor to ensure that NewL is used
   197 
   198 @param aSubKey 
   199 @param aDrives
   200 */
   201 CDriveTransferPublisher::CDriveTransferPublisher(
   202 	TUsbMsDriveState_Subkey aSubKey,
   203 	TRefMsDriveList aDrives)
   204 	:
   205 	iSubKey(aSubKey),
   206 	iDrives(aDrives)
   207 	{
   208 	}
   209 
   210 
   211 void CDriveTransferPublisher::ConstructL()
   212 	{
   213 	__FNLOG("CDriveTransferPublisher::ConstructL");
   214 
   215 	_LIT_SECURITY_POLICY_PASS(KMassStorageReadPolicy);
   216 	_LIT_SECURITY_POLICY_S0(KMassStorageWritePolicy, KUsbMsDriveState_Category.iUid);
   217 
   218 	TInt r = RProperty::Define(iSubKey, RProperty::EByteArray, 
   219 							   KMassStorageReadPolicy, KMassStorageWritePolicy,
   220 							   KUsbMsMaxDrives*sizeof(TInt));
   221 
   222 	if (r != KErrAlreadyExists) 
   223 		{
   224 		User::LeaveIfError(r);
   225 		}
   226 
   227 	User::LeaveIfError(iProperty.Attach(KUsbMsDriveState_Category, iSubKey));
   228 
   229 	// Create the EDataTransferred timer
   230 	iTimer = CPeriodic::NewL(CActive::EPriorityStandard);
   231 	iTimerRunning = EFalse;
   232 	}
   233 
   234 
   235 /**
   236 Destructor
   237 */
   238 CDriveTransferPublisher::~CDriveTransferPublisher()
   239 	{
   240 	__FNLOG("CDriveTransferPublisher::~CDriveTransferPublisher");
   241 
   242 	if(iTimer)
   243 		{
   244 		iTimer->Cancel();
   245 		}
   246 	delete iTimer;
   247 
   248 	iProperty.Close();
   249 
   250 	RProperty::Delete(KUsbMsDriveState_Category, iSubKey);
   251 	}
   252 
   253 
   254 /**
   255 A static wrapper for the DoPublishDataTransferredEvent member function
   256 for use as a timer callback function.
   257 
   258 @param obj 'this' pointer
   259 @return not used in CPeriodic callback (see TCallback)
   260 */
   261 TInt CDriveTransferPublisher::PublishDataTransferredEvent(TAny* obj)
   262 	{
   263 	__FNLOG("CDrivePublisher::PublishDataTransferredEvent");
   264 	static_cast<CDriveTransferPublisher*>(obj)->DoPublishDataTransferredEvent();
   265 	return 1;
   266 	}
   267 
   268 
   269 /**
   270 Update the data transferred properties if the counts have changed since
   271 the last update.
   272 */
   273 void CDriveTransferPublisher::DoPublishDataTransferredEvent()
   274 	{
   275 	if (PublishDataTransferred())
   276 		{
   277 		// some data has been transfered so reset the counter
   278 		iTimerCancelCnt = ETimerCancelDelay;
   279 		}
   280 
   281 	// Update the cancel count if no data was transferred the last
   282 	// (few) times this has been called
   283 	if (--iTimerCancelCnt == 0)
   284 		{
   285 		StopTimer();
   286 		iTimerCancelCnt = ETimerCancelDelay;
   287 		}
   288 	}
   289 
   290 
   291 /**
   292 Update the data transferred properties if the counts have changed since 
   293 the last update.
   294 */
   295 TBool CDriveTransferPublisher::PublishDataTransferred()
   296 	{
   297 	__FNLOG("CDriveWriteTransferPublisher::PublishDataTransferred");
   298 
   299 	TUsbMsBytesTransferred bytesTransferred;
   300 	TBool dataTransferred = EFalse;
   301 
   302 	for (TInt i=0; i < iDrives.Count() && iDrives[i]; i++)
   303 		{
   304 		bytesTransferred[i] = GetBytesTransferred(i);
   305 		}
   306 
   307 	// Update the properties only if they have changed
   308 	// (or if there's an error reading the old value.)
   309 	// Possible optimisation: keep a copy of the value
   310 	// as a member variable so we don't need the Get.
   311 	TUsbMsBytesTransferred oldValue;
   312 
   313 	if ((iProperty.Get(oldValue) != KErrNone) || (oldValue != bytesTransferred))
   314 		{
   315 #ifdef __PRINT3
   316 		for (TInt j=0; j < iDrives.Count() && iDrives[j]; j++)
   317 			{
   318 			if(oldValue[j] != bytesTransferred[j])
   319 				{
   320 				__PRINT3(_L("CDrivePublisher: KBytes[%d] %d->%d\n"), j, oldValue[j], bytesTransferred[j]);
   321 				}
   322 			}
   323 #endif
   324 		if (KErrNone != iProperty.Set(bytesTransferred))
   325 			{
   326 			__ASSERT_DEBUG(EFalse, User::Invariant());
   327 			}
   328 		dataTransferred = ETrue;
   329 		}
   330 
   331 	return dataTransferred;
   332 	}
   333 
   334 
   335 /**
   336 Starts timer to periodically publish results.
   337 If the timer is not yet running then start it.
   338 */
   339 void CDriveTransferPublisher::StartTimer()
   340 	{
   341 	__FNLOG("CDrivePublisher::StartTimer");
   342 
   343 	if (!iTimerRunning)
   344 		{
   345 		// EDataTransferred event every second
   346 		const TTimeIntervalMicroSeconds32 interval = 1 * 1000 * 1000;
   347 		TCallBack callback(PublishDataTransferredEvent, this);
   348 		__PRINT(_L("Starting timer"));
   349 		iTimer->Start(interval, interval, callback);
   350 		iTimerRunning = ETrue;
   351 		}
   352 	}
   353 
   354 
   355 /**
   356 Ensure that the Timer is stopped
   357 */
   358 void CDriveTransferPublisher::StopTimer()
   359 	{
   360 	__FNLOG("CDrivePublisher::StopTimer");
   361 
   362 	if (iTimerRunning)
   363 		{
   364 		__PRINT(_L("Stopping timer"));
   365 		iTimer->Cancel();
   366 		iTimerRunning = EFalse;
   367 		}
   368 	}
   369 
   370 
   371 //----------------------------------------------------------------------------
   372 /**
   373 Constructor for Write property
   374 
   375 @param aDrives
   376 */
   377 CDriveWriteTransferPublisher* CDriveWriteTransferPublisher::NewL(TRefMsDriveList aDrives)
   378 	{
   379 	__FNLOG("CDriveWriteTransferPublisher::NewL");
   380 
   381 	CDriveWriteTransferPublisher* self = new (ELeave) CDriveWriteTransferPublisher(aDrives);
   382 	CleanupStack::PushL(self);
   383 	self->ConstructL();
   384 	CleanupStack::Pop();
   385 	return self;
   386 	}
   387 
   388 
   389 /**
   390 Constructor
   391 
   392 @param aDrives
   393 */
   394 CDriveWriteTransferPublisher::CDriveWriteTransferPublisher(TRefMsDriveList aDrives)
   395 	:
   396 	CDriveTransferPublisher(EUsbMsDriveState_KBytesWritten, aDrives)
   397 	{
   398 	}
   399 
   400 
   401 /**
   402 Transfer function for Write property
   403 
   404 @param aLun
   405 */
   406 TUint CDriveWriteTransferPublisher::GetBytesTransferred(TUint aLun) const
   407 	{
   408 	return iDrives[aLun]->KBytesWritten();
   409 	}
   410 
   411 
   412 //----------------------------------------------------------------------------
   413 /**
   414 Constructor for Read property
   415 
   416 @param aDrives
   417 */
   418 CDriveReadTransferPublisher* CDriveReadTransferPublisher::NewL(TRefMsDriveList aDrives)
   419 	{
   420 	__FNLOG("CDriveWriteTransferPublisher::NewL");
   421 
   422 	CDriveReadTransferPublisher* self = new (ELeave) CDriveReadTransferPublisher(aDrives);
   423 	CleanupStack::PushL(self);
   424 	self->ConstructL();
   425 	CleanupStack::Pop();
   426 	return self;
   427 	}
   428 
   429 
   430 /**
   431 Constructor
   432 
   433 @param aDrives
   434 */
   435 CDriveReadTransferPublisher::CDriveReadTransferPublisher(TRefMsDriveList aDrives)
   436 	:
   437 	CDriveTransferPublisher(EUsbMsDriveState_KBytesRead, aDrives)
   438 	{
   439 	}
   440 
   441 
   442 /**
   443 Transfer function for Read property
   444 
   445 @param aLun
   446 */
   447 TUint CDriveReadTransferPublisher::GetBytesTransferred(TUint aLun) const
   448 	{
   449 	return iDrives[aLun]->KBytesRead();
   450 	}
   451 
   452 
   453 //----------------------------------------------------------------------------
   454 #else
   455 /**
   456 Private default constructor to ensure that NewL is used
   457  
   458 @param aSubKey
   459 @param aArray
   460 */
   461 CUsbTransferPublisher::CUsbTransferPublisher(
   462 	TUsbMsDriveState_Subkey aSubKey,
   463 	TRefBytesTransferedList aArray)
   464 	:
   465 	iSubKey(aSubKey),
   466 	iArray(aArray)
   467 	{
   468 	}
   469 
   470 
   471 void CUsbTransferPublisher::ConstructL()
   472 	{
   473 	__FNLOG("CUsbTransferPublisher::ConstructL");
   474 
   475 	_LIT_SECURITY_POLICY_PASS(KMassStorageReadPolicy);
   476 	_LIT_SECURITY_POLICY_S0(KMassStorageWritePolicy, KUsbMsDriveState_Category.iUid);
   477 
   478 	TInt r = RProperty::Define(iSubKey, RProperty::EByteArray, 
   479 							   KMassStorageReadPolicy, KMassStorageWritePolicy,
   480 							   KUsbMsMaxDrives*sizeof(TInt));
   481 
   482 	if (r != KErrAlreadyExists) 
   483 		{
   484 		User::LeaveIfError(r);
   485 		}
   486 
   487 	// Attach to the properties here. Only do this once, continuously attaching
   488 	// will currently cause a memory leak
   489 	User::LeaveIfError(iProperty.Attach(KUsbMsDriveState_Category, iSubKey));
   490 
   491 	// Create the EDataTransferred timer
   492 	iTimer = CPeriodic::NewL(CActive::EPriorityStandard);
   493 	iTimerRunning = EFalse;
   494 	}
   495 
   496 
   497 /**
   498 Destructor
   499 */
   500 CUsbTransferPublisher::~CUsbTransferPublisher()
   501 	{
   502 	__FNLOG("CUsbTransferPublisher::~CDriveTransferPublisher");
   503 
   504 	if(iTimer)
   505 		{
   506 		iTimer->Cancel();
   507 		}
   508 	delete iTimer;
   509 
   510 	iProperty.Close();
   511 
   512 	RProperty::Delete(KUsbMsDriveState_Category, iSubKey);
   513 	}
   514 
   515 
   516 /**
   517 A static wrapper for the DoPublishDataTransferredEvent member function
   518 for use as a timer callback function.
   519 
   520 @param obj 'this' pointer
   521 @return not used in CPeriodic callback (see TCallback)
   522 */
   523 TInt CUsbTransferPublisher::PublishDataTransferredEvent(TAny* obj)
   524 	{
   525 	__FNLOG("CUsbTransferPublisher::PublishDataTransferredEvent");
   526 	static_cast<CUsbTransferPublisher*>(obj)->DoPublishDataTransferredEvent();
   527 	return 1;
   528 	}
   529 
   530 
   531 /**
   532 Update the data transferred properties if the counts have changed since
   533 the last update.
   534 */
   535 void CUsbTransferPublisher::DoPublishDataTransferredEvent()
   536 	{
   537 	if (PublishDataTransferred())
   538 		{
   539 		// some data has been transfered so reset the counter
   540 		iTimerCancelCnt = ETimerCancelDelay;
   541 		}
   542 
   543 	// Update the cancel count if no data was transferred the last
   544 	// (few) times this has been called
   545 	if (--iTimerCancelCnt == 0)
   546 		{
   547 		StopTimer();
   548 		iTimerCancelCnt = ETimerCancelDelay;
   549 		}
   550 	}
   551 
   552 
   553 /**
   554 Update the data transferred properties if the counts have changed since 
   555 the last update.
   556 */
   557 TBool CUsbTransferPublisher::PublishDataTransferred()
   558 	{
   559 	__FNLOG("CUsbWriteTransferPublisher::PublishDataTransferred");
   560 
   561 	TUsbMsBytesTransferred bytesTransferred;
   562 	TBool dataTransferred = EFalse;
   563 
   564 	for (TInt i = 0; i < iArray.Count(); i++)
   565 		{
   566 		bytesTransferred[i] = GetBytesTransferred(i);
   567 		}
   568 
   569 	// Update the properties only if they have changed
   570 	// (or if there's an error reading the old value.)
   571 	// Possible optimisation: keep a copy of the value
   572 	// as a member variable so we don't need the Get.
   573 	TUsbMsBytesTransferred oldValue;
   574 
   575 	if ((iProperty.Get(oldValue) != KErrNone) || (oldValue != bytesTransferred))
   576 		{
   577 #ifdef __PRINT3
   578 		// trace of the bytes transferred
   579 		for (TInt j=0; j < iArray.Count(); j++)
   580 			{
   581 			if(oldValue[j] != bytesTransferred[j])
   582 				{
   583 				__PRINT3(_L("CDrivePublisher: KBytes[%d] %d->%d\n"), j, oldValue[j], bytesTransferred[j]);
   584 				}
   585 			}
   586 #endif
   587 		if (KErrNone != iProperty.Set(bytesTransferred))
   588 			{
   589 			__ASSERT_DEBUG(EFalse, User::Invariant());
   590 			}
   591 		dataTransferred = ETrue;
   592 		}
   593 
   594 	return dataTransferred;
   595 	}
   596 
   597 
   598 /**
   599 Starts timer to periodically publish results.
   600 If the timer is not yet running then start it.
   601 */
   602 void CUsbTransferPublisher::StartTimer()
   603 	{
   604 	__FNLOG("CUsbTransferPublisher::StartTimer");
   605 
   606 	if (!iTimerRunning)
   607 		{
   608 		// EDataTransferred event every second
   609 		const TTimeIntervalMicroSeconds32 interval = 1 * 1000 * 1000;
   610 		TCallBack callback(PublishDataTransferredEvent, this);
   611 		__PRINT(_L("Starting timer"));
   612 		iTimer->Start(interval, interval, callback);
   613 		iTimerRunning = ETrue;
   614 		}
   615 	}
   616 
   617 
   618 /**
   619 Ensure that the Timer is stopped
   620 */
   621 void CUsbTransferPublisher::StopTimer()
   622 	{
   623 	__FNLOG("CUsbTransferPublisher::StopTimer");
   624 
   625 	if (iTimerRunning)
   626 		{
   627 		__PRINT(_L("Stopping timer"));
   628 		iTimer->Cancel();
   629 		iTimerRunning = EFalse;
   630 		}
   631 	}
   632 
   633 
   634 //----------------------------------------------------------------------------
   635 /**
   636 Constructor for Write property
   637 
   638 @param aArray
   639 */
   640 CUsbWriteTransferPublisher* CUsbWriteTransferPublisher::NewL(TRefBytesTransferedList aArray)
   641 	{
   642 	__FNLOG("CUsbWriteTransferPublisher::NewL");
   643 
   644 	CUsbWriteTransferPublisher* self = new (ELeave) CUsbWriteTransferPublisher(aArray);
   645 	CleanupStack::PushL(self);
   646 	self->ConstructL();
   647 	CleanupStack::Pop();
   648 	return self;
   649 	}
   650 
   651 
   652 CUsbWriteTransferPublisher::CUsbWriteTransferPublisher(
   653 	TRefBytesTransferedList aArray)
   654 	:
   655 	CUsbTransferPublisher(EUsbMsDriveState_KBytesWritten, aArray)
   656 	{
   657 	}
   658 
   659 
   660 //----------------------------------------------------------------------------
   661 /**
   662 Constructor for Read property
   663 
   664 @param aArray
   665 */
   666 CUsbReadTransferPublisher* CUsbReadTransferPublisher::NewL(TRefBytesTransferedList aArray)
   667 	{
   668 	__FNLOG("CUsbWriteTransferPublisher::NewL");
   669 
   670 	CUsbReadTransferPublisher* self = new (ELeave) CUsbReadTransferPublisher(aArray);
   671 	CleanupStack::PushL(self);
   672 	self->ConstructL();
   673 	CleanupStack::Pop();
   674 	return self;
   675 	}
   676 
   677 
   678 CUsbReadTransferPublisher::CUsbReadTransferPublisher(
   679 	TRefBytesTransferedList aArray)
   680 	:
   681 	CUsbTransferPublisher(EUsbMsDriveState_KBytesRead, aArray)
   682 	{
   683 	}
   684 #endif // USB_TRANSFER_PUBLISHER