sl@0: // Copyright (c) 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: sl@0: /** sl@0: @file sl@0: @internalTechnology sl@0: */ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #include "mstypes.h" sl@0: #include "msctypes.h" sl@0: #include "usbmsshared.h" sl@0: sl@0: #include "drivepublisher.h" sl@0: #include "drivemanager.h" sl@0: #include "debug.h" sl@0: #include "msdebug.h" 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: __MSFNLOG 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: __MSFNLOG 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::PublishErrorL(TBool aError) sl@0: { sl@0: __MSFNLOG 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(const TMsDriveList& aDrives, sl@0: const TLunToDriveMap& aDriveMap) sl@0: : sl@0: iDrives(aDrives), sl@0: iDriveMap(aDriveMap) sl@0: { sl@0: __MSFNLOG 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: __MSFNLOG 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: __MSFNLOG sl@0: TUsbMsDrivesStatus allDrivesStatus; sl@0: sl@0: for(TUint8 i = 0; i < iDrives.Count(); i++) sl@0: { sl@0: allDrivesStatus.Append(iDriveMap[i]); sl@0: sl@0: CMassStorageDrive::TMountState ms = iDrives[i]->MountState(); sl@0: TLocalDriveRef::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: 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: 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(TUsbMsDriveState_Subkey aSubKey, sl@0: const TBytesTransferedList& aArray) sl@0: : iSubKey(aSubKey), sl@0: iArray(aArray) sl@0: { sl@0: __MSFNLOG sl@0: } sl@0: sl@0: sl@0: void CUsbTransferPublisher::ConstructL() sl@0: { sl@0: __MSFNLOG 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: __MSFNLOG sl@0: if(iTimer) sl@0: { sl@0: iTimer->Cancel(); sl@0: } sl@0: delete iTimer; 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: __MSFNSLOG 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: __MSFNLOG 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: __MSFNLOG 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: __MSFNLOG 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: __MSFNLOG 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(const TBytesTransferedList& aArray) sl@0: { sl@0: __MSFNSLOG 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(const TBytesTransferedList& aArray) sl@0: : CUsbTransferPublisher(EUsbMsDriveState_KBytesWritten, aArray) sl@0: { sl@0: __MSFNLOG 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(const TBytesTransferedList& aArray) sl@0: { sl@0: __MSFNSLOG 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(const TBytesTransferedList& aArray) sl@0: : CUsbTransferPublisher(EUsbMsDriveState_KBytesRead, aArray) sl@0: { sl@0: __MSFNLOG sl@0: } sl@0: sl@0: /** sl@0: Transfer function for the property sl@0: sl@0: @return Cumulative bytes read since the host connected to the drive, sl@0: in multiples of KBytesPerKilobyte rounded to nearest integer value. sl@0: The KBytes refer to multiples of 1000, not 1024. sl@0: */ sl@0: TUint CUsbTransferPublisher::GetBytesTransferred(TLun aLun) const sl@0: { sl@0: return I64LOW(iArray[aLun] / (TUint64)1000); sl@0: }