sl@0: // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // Class implementation of the drive publishing classes - sl@0: // RDriveMediaErrorPublisher, sl@0: // RDriveStateChangedPublisher, sl@0: // CDriveTransferPublisher, sl@0: // CDriveWriteTransferPublisher, sl@0: // CDriveReadTransferPublisher, sl@0: // CUsbTransferPublisher, sl@0: // CUsbReadTransferPublisher, sl@0: // CUsbReadTransferPublisher. sl@0: // sl@0: // sl@0: sl@0: /** sl@0: @file sl@0: @internalTechnology sl@0: */ sl@0: sl@0: #include "massstoragedebug.h" sl@0: #include "drivepublisher.h" sl@0: #include "drivemanager.h" sl@0: sl@0: sl@0: // sl@0: // Use Lookup table to translate from the internal pair of state variables sl@0: // to the externally published drive state code. sl@0: // sl@0: LOCAL_D const TUint8 table[][5] = sl@0: { sl@0: //TMountState=EDisconnected sl@0: {EUsbMsDriveState_Disconnected, sl@0: EUsbMsDriveState_Disconnected, sl@0: EUsbMsDriveState_Disconnected, sl@0: EUsbMsDriveState_Disconnected, sl@0: EUsbMsDriveState_Disconnected}, sl@0: //TMountState=EConnecting sl@0: {EUsbMsDriveState_Connecting, sl@0: EUsbMsDriveState_Connecting, sl@0: EUsbMsDriveState_Connecting, sl@0: EUsbMsDriveState_Connecting, sl@0: EUsbMsDriveState_Connecting}, sl@0: //TMountState=EConnected sl@0: //EIdle,EActive,ELocked,EMediaNotPresent,EErrDisMounted sl@0: {EUsbMsDriveState_Connected, sl@0: EUsbMsDriveState_Active, sl@0: EUsbMsDriveState_Locked, sl@0: EUsbMsDriveState_MediaNotPresent, sl@0: EUsbMsDriveState_Removed}, sl@0: //TMountState=EDisconnecting sl@0: {EUsbMsDriveState_Disconnecting, sl@0: EUsbMsDriveState_Disconnecting, sl@0: EUsbMsDriveState_Disconnecting, sl@0: EUsbMsDriveState_Disconnecting, sl@0: EUsbMsDriveState_Disconnecting} sl@0: }; sl@0: sl@0: sl@0: //---------------------------------------------------------------------------- sl@0: /** sl@0: Constructor sl@0: */ sl@0: RDriveMediaErrorPublisher::RDriveMediaErrorPublisher() sl@0: { sl@0: __FNLOG("RDriveMediaErrorPublisher::RDriveMediaErrorPublisher()"); sl@0: sl@0: _LIT_SECURITY_POLICY_PASS(KMassStorageReadPolicy); sl@0: _LIT_SECURITY_POLICY_S0(KMassStorageWritePolicy, KUsbMsDriveState_Category.iUid); sl@0: sl@0: TInt result = RProperty::Define(EUsbMsDriveState_MediaError, RProperty::EInt, sl@0: KMassStorageReadPolicy, KMassStorageWritePolicy); sl@0: sl@0: __ASSERT_DEBUG(result == KErrAlreadyExists || result == KErrNone, User::Invariant()); sl@0: sl@0: result = iMediaErrorProperty.Attach(KUsbMsDriveState_Category, EUsbMsDriveState_MediaError); sl@0: __ASSERT_DEBUG(result == KErrNone, User::Invariant()); sl@0: } sl@0: sl@0: sl@0: RDriveMediaErrorPublisher::~RDriveMediaErrorPublisher() sl@0: { sl@0: __FNLOG("RDriveStatePublisher::~RDriveStatePublisher()"); sl@0: sl@0: iMediaErrorProperty.Close(); sl@0: RProperty::Delete(KUsbMsDriveState_Category, EUsbMsDriveState_MediaError); sl@0: } sl@0: sl@0: /** sl@0: Publishing method sl@0: sl@0: Publishes the Media Error property event sl@0: sl@0: @param aError ETrue if drive media has an error else EFalse for no error sl@0: */ sl@0: void RDriveMediaErrorPublisher::PublishError(TBool aError) sl@0: { sl@0: __PRINT1(_L("<< RDriveMediaErrorPublisher::PublishError %x"), aError); sl@0: sl@0: TInt oldValue; sl@0: iMediaErrorProperty.Get(oldValue); sl@0: sl@0: if (oldValue != aError) sl@0: { sl@0: User::LeaveIfError(iMediaErrorProperty.Set(aError)); sl@0: } sl@0: } sl@0: sl@0: //---------------------------------------------------------------------------- sl@0: /** sl@0: Constructor sl@0: sl@0: @param aDrives sl@0: @param aDriveMap sl@0: */ sl@0: RDriveStateChangedPublisher::RDriveStateChangedPublisher(TRefMsDriveList aDrives, sl@0: TRefDriveMap aDriveMap) sl@0: : sl@0: iDrives(aDrives), sl@0: iDriveMap(aDriveMap) sl@0: { sl@0: __FNLOG("RDriveStateChangedPublisher::RDriveStateChangedPublisher()"); sl@0: sl@0: _LIT_SECURITY_POLICY_PASS(KMassStorageReadPolicy); sl@0: _LIT_SECURITY_POLICY_S0(KMassStorageWritePolicy, KUsbMsDriveState_Category.iUid); sl@0: sl@0: TInt result = RProperty::Define(KUsbMsDriveState_Category, sl@0: EUsbMsDriveState_DriveStatus, RProperty::EByteArray, sl@0: KMassStorageReadPolicy, KMassStorageWritePolicy, sl@0: KUsbMsMaxDrives*2); sl@0: __ASSERT_DEBUG(result == KErrAlreadyExists || result == KErrNone, User::Invariant()); sl@0: result = result; // remove urel warning sl@0: } sl@0: sl@0: sl@0: RDriveStateChangedPublisher::~RDriveStateChangedPublisher() sl@0: { sl@0: __FNLOG("RDriveStateChangedPublisher::~RDriveStateChangedPublisher()"); sl@0: sl@0: RProperty::Delete(KUsbMsDriveState_Category, EUsbMsDriveState_DriveStatus); sl@0: } sl@0: sl@0: sl@0: /** sl@0: Publishing method sl@0: sl@0: Sends a property event on behalf of CMassStorageDrive, with the mountstate and drivestate sl@0: values encoded into one 32-bit word. sl@0: */ sl@0: void RDriveStateChangedPublisher::DriveStateChanged() sl@0: { sl@0: __FNLOG("RDriveStateChangedPublisher::DriveStateChanged"); sl@0: sl@0: sl@0: TUsbMsDrivesStatus allDrivesStatus; sl@0: for(TUint8 i=0; iMountState(); sl@0: CMassStorageDrive::TDriveState ds = iDrives[i]->DriveState(); sl@0: TInt driveStatus = EUsbMsDriveState_Error; sl@0: if((TUint8)ds < sizeof(table[0]) && (TUint8)ms < sizeof(table)/sizeof(table[0])) sl@0: { sl@0: driveStatus = table[ms][ds]; sl@0: __PRINT3(_L("ms=%d ds=%d %d"), ms, ds, driveStatus); sl@0: } sl@0: allDrivesStatus.Append(driveStatus); sl@0: } sl@0: sl@0: __PRINT1(_L("Publishing EUsbMsDriveState_DriveStatus for %d drives\n"), sl@0: allDrivesStatus.Length()/2); sl@0: sl@0: if(KErrNone != RProperty::Set(KUsbMsDriveState_Category, sl@0: EUsbMsDriveState_DriveStatus, sl@0: allDrivesStatus)) sl@0: { sl@0: __ASSERT_DEBUG(EFalse,User::Invariant()); sl@0: } sl@0: } sl@0: sl@0: sl@0: //---------------------------------------------------------------------------- sl@0: #ifndef USB_TRANSFER_PUBLISHER sl@0: /** sl@0: Private default constructor to ensure that NewL is used sl@0: sl@0: @param aSubKey sl@0: @param aDrives sl@0: */ sl@0: CDriveTransferPublisher::CDriveTransferPublisher( sl@0: TUsbMsDriveState_Subkey aSubKey, sl@0: TRefMsDriveList aDrives) sl@0: : sl@0: iSubKey(aSubKey), sl@0: iDrives(aDrives) sl@0: { sl@0: } sl@0: sl@0: sl@0: void CDriveTransferPublisher::ConstructL() sl@0: { sl@0: __FNLOG("CDriveTransferPublisher::ConstructL"); sl@0: sl@0: _LIT_SECURITY_POLICY_PASS(KMassStorageReadPolicy); sl@0: _LIT_SECURITY_POLICY_S0(KMassStorageWritePolicy, KUsbMsDriveState_Category.iUid); sl@0: sl@0: TInt r = RProperty::Define(iSubKey, RProperty::EByteArray, sl@0: KMassStorageReadPolicy, KMassStorageWritePolicy, sl@0: KUsbMsMaxDrives*sizeof(TInt)); sl@0: sl@0: if (r != KErrAlreadyExists) sl@0: { sl@0: User::LeaveIfError(r); sl@0: } sl@0: sl@0: User::LeaveIfError(iProperty.Attach(KUsbMsDriveState_Category, iSubKey)); sl@0: sl@0: // Create the EDataTransferred timer sl@0: iTimer = CPeriodic::NewL(CActive::EPriorityStandard); sl@0: iTimerRunning = EFalse; sl@0: } sl@0: sl@0: sl@0: /** sl@0: Destructor sl@0: */ sl@0: CDriveTransferPublisher::~CDriveTransferPublisher() sl@0: { sl@0: __FNLOG("CDriveTransferPublisher::~CDriveTransferPublisher"); sl@0: sl@0: if(iTimer) sl@0: { sl@0: iTimer->Cancel(); sl@0: } sl@0: delete iTimer; sl@0: sl@0: iProperty.Close(); sl@0: sl@0: RProperty::Delete(KUsbMsDriveState_Category, iSubKey); sl@0: } sl@0: sl@0: sl@0: /** sl@0: A static wrapper for the DoPublishDataTransferredEvent member function sl@0: for use as a timer callback function. sl@0: sl@0: @param obj 'this' pointer sl@0: @return not used in CPeriodic callback (see TCallback) sl@0: */ sl@0: TInt CDriveTransferPublisher::PublishDataTransferredEvent(TAny* obj) sl@0: { sl@0: __FNLOG("CDrivePublisher::PublishDataTransferredEvent"); sl@0: static_cast(obj)->DoPublishDataTransferredEvent(); sl@0: return 1; sl@0: } sl@0: sl@0: sl@0: /** sl@0: Update the data transferred properties if the counts have changed since sl@0: the last update. sl@0: */ sl@0: void CDriveTransferPublisher::DoPublishDataTransferredEvent() sl@0: { sl@0: if (PublishDataTransferred()) sl@0: { sl@0: // some data has been transfered so reset the counter sl@0: iTimerCancelCnt = ETimerCancelDelay; sl@0: } sl@0: sl@0: // Update the cancel count if no data was transferred the last sl@0: // (few) times this has been called sl@0: if (--iTimerCancelCnt == 0) sl@0: { sl@0: StopTimer(); sl@0: iTimerCancelCnt = ETimerCancelDelay; sl@0: } sl@0: } sl@0: sl@0: sl@0: /** sl@0: Update the data transferred properties if the counts have changed since sl@0: the last update. sl@0: */ sl@0: TBool CDriveTransferPublisher::PublishDataTransferred() sl@0: { sl@0: __FNLOG("CDriveWriteTransferPublisher::PublishDataTransferred"); sl@0: sl@0: TUsbMsBytesTransferred bytesTransferred; sl@0: TBool dataTransferred = EFalse; sl@0: sl@0: for (TInt i=0; i < iDrives.Count() && iDrives[i]; i++) sl@0: { sl@0: bytesTransferred[i] = GetBytesTransferred(i); sl@0: } sl@0: sl@0: // Update the properties only if they have changed sl@0: // (or if there's an error reading the old value.) sl@0: // Possible optimisation: keep a copy of the value sl@0: // as a member variable so we don't need the Get. sl@0: TUsbMsBytesTransferred oldValue; sl@0: sl@0: if ((iProperty.Get(oldValue) != KErrNone) || (oldValue != bytesTransferred)) sl@0: { sl@0: #ifdef __PRINT3 sl@0: for (TInt j=0; j < iDrives.Count() && iDrives[j]; j++) sl@0: { sl@0: if(oldValue[j] != bytesTransferred[j]) sl@0: { sl@0: __PRINT3(_L("CDrivePublisher: KBytes[%d] %d->%d\n"), j, oldValue[j], bytesTransferred[j]); sl@0: } sl@0: } sl@0: #endif sl@0: if (KErrNone != iProperty.Set(bytesTransferred)) sl@0: { sl@0: __ASSERT_DEBUG(EFalse, User::Invariant()); sl@0: } sl@0: dataTransferred = ETrue; sl@0: } sl@0: sl@0: return dataTransferred; sl@0: } sl@0: sl@0: sl@0: /** sl@0: Starts timer to periodically publish results. sl@0: If the timer is not yet running then start it. sl@0: */ sl@0: void CDriveTransferPublisher::StartTimer() sl@0: { sl@0: __FNLOG("CDrivePublisher::StartTimer"); sl@0: sl@0: if (!iTimerRunning) sl@0: { sl@0: // EDataTransferred event every second sl@0: const TTimeIntervalMicroSeconds32 interval = 1 * 1000 * 1000; sl@0: TCallBack callback(PublishDataTransferredEvent, this); sl@0: __PRINT(_L("Starting timer")); sl@0: iTimer->Start(interval, interval, callback); sl@0: iTimerRunning = ETrue; sl@0: } sl@0: } sl@0: sl@0: sl@0: /** sl@0: Ensure that the Timer is stopped sl@0: */ sl@0: void CDriveTransferPublisher::StopTimer() sl@0: { sl@0: __FNLOG("CDrivePublisher::StopTimer"); sl@0: sl@0: if (iTimerRunning) sl@0: { sl@0: __PRINT(_L("Stopping timer")); sl@0: iTimer->Cancel(); sl@0: iTimerRunning = EFalse; sl@0: } sl@0: } sl@0: sl@0: sl@0: //---------------------------------------------------------------------------- sl@0: /** sl@0: Constructor for Write property sl@0: sl@0: @param aDrives sl@0: */ sl@0: CDriveWriteTransferPublisher* CDriveWriteTransferPublisher::NewL(TRefMsDriveList aDrives) sl@0: { sl@0: __FNLOG("CDriveWriteTransferPublisher::NewL"); sl@0: sl@0: CDriveWriteTransferPublisher* self = new (ELeave) CDriveWriteTransferPublisher(aDrives); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: sl@0: /** sl@0: Constructor sl@0: sl@0: @param aDrives sl@0: */ sl@0: CDriveWriteTransferPublisher::CDriveWriteTransferPublisher(TRefMsDriveList aDrives) sl@0: : sl@0: CDriveTransferPublisher(EUsbMsDriveState_KBytesWritten, aDrives) sl@0: { sl@0: } sl@0: sl@0: sl@0: /** sl@0: Transfer function for Write property sl@0: sl@0: @param aLun sl@0: */ sl@0: TUint CDriveWriteTransferPublisher::GetBytesTransferred(TUint aLun) const sl@0: { sl@0: return iDrives[aLun]->KBytesWritten(); sl@0: } sl@0: sl@0: sl@0: //---------------------------------------------------------------------------- sl@0: /** sl@0: Constructor for Read property sl@0: sl@0: @param aDrives sl@0: */ sl@0: CDriveReadTransferPublisher* CDriveReadTransferPublisher::NewL(TRefMsDriveList aDrives) sl@0: { sl@0: __FNLOG("CDriveWriteTransferPublisher::NewL"); sl@0: sl@0: CDriveReadTransferPublisher* self = new (ELeave) CDriveReadTransferPublisher(aDrives); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: sl@0: /** sl@0: Constructor sl@0: sl@0: @param aDrives sl@0: */ sl@0: CDriveReadTransferPublisher::CDriveReadTransferPublisher(TRefMsDriveList aDrives) sl@0: : sl@0: CDriveTransferPublisher(EUsbMsDriveState_KBytesRead, aDrives) sl@0: { sl@0: } sl@0: sl@0: sl@0: /** sl@0: Transfer function for Read property sl@0: sl@0: @param aLun sl@0: */ sl@0: TUint CDriveReadTransferPublisher::GetBytesTransferred(TUint aLun) const sl@0: { sl@0: return iDrives[aLun]->KBytesRead(); sl@0: } sl@0: sl@0: sl@0: //---------------------------------------------------------------------------- sl@0: #else sl@0: /** sl@0: Private default constructor to ensure that NewL is used sl@0: sl@0: @param aSubKey sl@0: @param aArray sl@0: */ sl@0: CUsbTransferPublisher::CUsbTransferPublisher( sl@0: TUsbMsDriveState_Subkey aSubKey, sl@0: TRefBytesTransferedList aArray) sl@0: : sl@0: iSubKey(aSubKey), sl@0: iArray(aArray) sl@0: { sl@0: } sl@0: sl@0: sl@0: void CUsbTransferPublisher::ConstructL() sl@0: { sl@0: __FNLOG("CUsbTransferPublisher::ConstructL"); sl@0: sl@0: _LIT_SECURITY_POLICY_PASS(KMassStorageReadPolicy); sl@0: _LIT_SECURITY_POLICY_S0(KMassStorageWritePolicy, KUsbMsDriveState_Category.iUid); sl@0: sl@0: TInt r = RProperty::Define(iSubKey, RProperty::EByteArray, sl@0: KMassStorageReadPolicy, KMassStorageWritePolicy, sl@0: KUsbMsMaxDrives*sizeof(TInt)); sl@0: sl@0: if (r != KErrAlreadyExists) sl@0: { sl@0: User::LeaveIfError(r); sl@0: } sl@0: sl@0: // Attach to the properties here. Only do this once, continuously attaching sl@0: // will currently cause a memory leak sl@0: User::LeaveIfError(iProperty.Attach(KUsbMsDriveState_Category, iSubKey)); sl@0: sl@0: // Create the EDataTransferred timer sl@0: iTimer = CPeriodic::NewL(CActive::EPriorityStandard); sl@0: iTimerRunning = EFalse; sl@0: } sl@0: sl@0: sl@0: /** sl@0: Destructor sl@0: */ sl@0: CUsbTransferPublisher::~CUsbTransferPublisher() sl@0: { sl@0: __FNLOG("CUsbTransferPublisher::~CDriveTransferPublisher"); sl@0: sl@0: if(iTimer) sl@0: { sl@0: iTimer->Cancel(); sl@0: } sl@0: delete iTimer; sl@0: sl@0: iProperty.Close(); sl@0: sl@0: RProperty::Delete(KUsbMsDriveState_Category, iSubKey); sl@0: } sl@0: sl@0: sl@0: /** sl@0: A static wrapper for the DoPublishDataTransferredEvent member function sl@0: for use as a timer callback function. sl@0: sl@0: @param obj 'this' pointer sl@0: @return not used in CPeriodic callback (see TCallback) sl@0: */ sl@0: TInt CUsbTransferPublisher::PublishDataTransferredEvent(TAny* obj) sl@0: { sl@0: __FNLOG("CUsbTransferPublisher::PublishDataTransferredEvent"); sl@0: static_cast(obj)->DoPublishDataTransferredEvent(); sl@0: return 1; sl@0: } sl@0: sl@0: sl@0: /** sl@0: Update the data transferred properties if the counts have changed since sl@0: the last update. sl@0: */ sl@0: void CUsbTransferPublisher::DoPublishDataTransferredEvent() sl@0: { sl@0: if (PublishDataTransferred()) sl@0: { sl@0: // some data has been transfered so reset the counter sl@0: iTimerCancelCnt = ETimerCancelDelay; sl@0: } sl@0: sl@0: // Update the cancel count if no data was transferred the last sl@0: // (few) times this has been called sl@0: if (--iTimerCancelCnt == 0) sl@0: { sl@0: StopTimer(); sl@0: iTimerCancelCnt = ETimerCancelDelay; sl@0: } sl@0: } sl@0: sl@0: sl@0: /** sl@0: Update the data transferred properties if the counts have changed since sl@0: the last update. sl@0: */ sl@0: TBool CUsbTransferPublisher::PublishDataTransferred() sl@0: { sl@0: __FNLOG("CUsbWriteTransferPublisher::PublishDataTransferred"); sl@0: sl@0: TUsbMsBytesTransferred bytesTransferred; sl@0: TBool dataTransferred = EFalse; sl@0: sl@0: for (TInt i = 0; i < iArray.Count(); i++) sl@0: { sl@0: bytesTransferred[i] = GetBytesTransferred(i); sl@0: } sl@0: sl@0: // Update the properties only if they have changed sl@0: // (or if there's an error reading the old value.) sl@0: // Possible optimisation: keep a copy of the value sl@0: // as a member variable so we don't need the Get. sl@0: TUsbMsBytesTransferred oldValue; sl@0: sl@0: if ((iProperty.Get(oldValue) != KErrNone) || (oldValue != bytesTransferred)) sl@0: { sl@0: #ifdef __PRINT3 sl@0: // trace of the bytes transferred sl@0: for (TInt j=0; j < iArray.Count(); j++) sl@0: { sl@0: if(oldValue[j] != bytesTransferred[j]) sl@0: { sl@0: __PRINT3(_L("CDrivePublisher: KBytes[%d] %d->%d\n"), j, oldValue[j], bytesTransferred[j]); sl@0: } sl@0: } sl@0: #endif sl@0: if (KErrNone != iProperty.Set(bytesTransferred)) sl@0: { sl@0: __ASSERT_DEBUG(EFalse, User::Invariant()); sl@0: } sl@0: dataTransferred = ETrue; sl@0: } sl@0: sl@0: return dataTransferred; sl@0: } sl@0: sl@0: sl@0: /** sl@0: Starts timer to periodically publish results. sl@0: If the timer is not yet running then start it. sl@0: */ sl@0: void CUsbTransferPublisher::StartTimer() sl@0: { sl@0: __FNLOG("CUsbTransferPublisher::StartTimer"); sl@0: sl@0: if (!iTimerRunning) sl@0: { sl@0: // EDataTransferred event every second sl@0: const TTimeIntervalMicroSeconds32 interval = 1 * 1000 * 1000; sl@0: TCallBack callback(PublishDataTransferredEvent, this); sl@0: __PRINT(_L("Starting timer")); sl@0: iTimer->Start(interval, interval, callback); sl@0: iTimerRunning = ETrue; sl@0: } sl@0: } sl@0: sl@0: sl@0: /** sl@0: Ensure that the Timer is stopped sl@0: */ sl@0: void CUsbTransferPublisher::StopTimer() sl@0: { sl@0: __FNLOG("CUsbTransferPublisher::StopTimer"); sl@0: sl@0: if (iTimerRunning) sl@0: { sl@0: __PRINT(_L("Stopping timer")); sl@0: iTimer->Cancel(); sl@0: iTimerRunning = EFalse; sl@0: } sl@0: } sl@0: sl@0: sl@0: //---------------------------------------------------------------------------- sl@0: /** sl@0: Constructor for Write property sl@0: sl@0: @param aArray sl@0: */ sl@0: CUsbWriteTransferPublisher* CUsbWriteTransferPublisher::NewL(TRefBytesTransferedList aArray) sl@0: { sl@0: __FNLOG("CUsbWriteTransferPublisher::NewL"); sl@0: sl@0: CUsbWriteTransferPublisher* self = new (ELeave) CUsbWriteTransferPublisher(aArray); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: sl@0: CUsbWriteTransferPublisher::CUsbWriteTransferPublisher( sl@0: TRefBytesTransferedList aArray) sl@0: : sl@0: CUsbTransferPublisher(EUsbMsDriveState_KBytesWritten, aArray) sl@0: { sl@0: } sl@0: sl@0: sl@0: //---------------------------------------------------------------------------- sl@0: /** sl@0: Constructor for Read property sl@0: sl@0: @param aArray sl@0: */ sl@0: CUsbReadTransferPublisher* CUsbReadTransferPublisher::NewL(TRefBytesTransferedList aArray) sl@0: { sl@0: __FNLOG("CUsbWriteTransferPublisher::NewL"); sl@0: sl@0: CUsbReadTransferPublisher* self = new (ELeave) CUsbReadTransferPublisher(aArray); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: sl@0: CUsbReadTransferPublisher::CUsbReadTransferPublisher( sl@0: TRefBytesTransferedList aArray) sl@0: : sl@0: CUsbTransferPublisher(EUsbMsDriveState_KBytesRead, aArray) sl@0: { sl@0: } sl@0: #endif // USB_TRANSFER_PUBLISHER