Update contrib.
1 // Copyright (c) 2006-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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // USB Mass Storage Application
24 #include "activecontrol.h"
26 #include <usbmsshared.h>
27 #include <massstorage.h>
31 extern CActiveControl* gActiveControl;
33 extern TBool gVerbose;
35 extern TBool gTempTest;
39 LOCAL_D TBuf<0x40> mountList;
41 LOCAL_D TFixedArray<TBool, KMaxDrives> msfsMountedList; ///< 'true' entry corresponds to the drive with mounted MSFS.FSY
42 LOCAL_D TFixedArray<CFileSystemDescriptor*, KMaxDrives> unmountedFsList; ///< every non-NULL entry corresponds to the unmounted original FS for the drive
44 LOCAL_D RUsbMassStorage UsbMs;
46 LOCAL_D CUsbWatch * usbWatch;
48 static const TUint KNumPropWatch = 4;
49 LOCAL_D CPropertyWatch * propWatch[KNumPropWatch];
51 _LIT(KMsFsy, "MSFS.FSY");
52 _LIT(KMsFs, "MassStorageFileSystem");
55 _LIT(KBytesTransferredFmt, "%c:%d/%d \n");
56 _LIT(KErrFmt, "Error: %d\r");
57 _LIT(KConfigured,"Configured");
58 _LIT(KNotConfigured,"NOT Configured");
62 TMediaPassword password(KDefPwd);
64 //-----------------------------------------------------------------------------
66 CFileSystemDescriptor::~CFileSystemDescriptor()
69 iPrimaryExtName.Close();
72 //-----------------------------------------------------------------------------
73 CFileSystemDescriptor* CFileSystemDescriptor::NewL(const TDesC& aFsName, const TDesC& aPrimaryExtName, TBool aDrvSynch)
75 CFileSystemDescriptor* pSelf = new (ELeave) CFileSystemDescriptor;
77 CleanupStack::PushL(pSelf);
79 pSelf->iFsName.CreateMaxL(aFsName.Length());
80 pSelf->iFsName.Copy(aFsName);
82 pSelf->iPrimaryExtName.CreateMaxL(aPrimaryExtName.Length());
83 pSelf->iPrimaryExtName.Copy(aPrimaryExtName);
85 pSelf->iDriveSynch = aDrvSynch;
92 //-----------------------------------------------------------------------------
94 Dismounts the originally mounted FS and optional primary extension from the drive and stores
95 this information in the FS descriptor
97 @return on success returns a pointer to the instantinated FS descriptor
99 LOCAL_C CFileSystemDescriptor* DoDismountOrginalFS(RFs& aFs, TInt aDrive)
103 TBuf<128> primaryExtName;
104 TBool bDrvSync = EFalse;
106 test.Printf(_L("DoDismountOrginalFS drv:%d\n"), aDrive);
108 //-- 1. get file system name
109 nRes = aFs.FileSystemName(fsName, aDrive);
111 {//-- probably no file system installed at all
115 //-- 2. find out if the drive sync/async
116 TPckgBuf<TBool> drvSyncBuf;
117 nRes = aFs.QueryVolumeInfoExt(aDrive, EIsDriveSync, drvSyncBuf);
120 bDrvSync = drvSyncBuf();
123 //-- 3. find out primary extension name if it is present; we will need to add it againt when mounting the FS
124 //-- other extensions (non-primary) are not supported yet
125 nRes = aFs.ExtensionName(primaryExtName, aDrive, 0);
128 primaryExtName.SetLength(0);
131 //-- 3.1 check if the drive has non-primary extensions, fail in this case, because this FS can't be mounted back normally
132 nRes = aFs.ExtensionName(primaryExtName, aDrive, 1);
135 test.Printf(_L("DoDismountOrginalFS Non-primary extensions are not supported!\n"));
139 test.Printf(_L("DoDismountOrginalFS FS:%S, Prim ext:%S, synch:%d\n"), &fsName, &primaryExtName, bDrvSync);
141 //-- create FS descriptor and dismount the FS
142 CFileSystemDescriptor* pFsDesc = NULL;
144 TRAP(nRes, pFsDesc = CFileSystemDescriptor::NewL(fsName, primaryExtName, bDrvSync));
146 return NULL; //-- OOM ?
148 nRes = aFs.DismountFileSystem(fsName, aDrive);
153 test.Printf(_L("DoDismountOrginalFS Dismounting Err:%d\n"), nRes);
159 //-----------------------------------------------------------------------------
161 Tries to restore the original FS on the drive using the FS descriptor provided
162 @return standard error code.
164 LOCAL_C TInt DoRestoreFS(RFs& aFs, TInt aDrive, CFileSystemDescriptor* apFsDesc)
168 test.Printf(_L("DoRestoreFS drv:%d\n"), aDrive);
170 //-- 1. check that there is no FS installed
172 nRes = aFs.FileSystemName(fsName, aDrive);
174 {//-- there is a file system already installed
175 test.Printf(_L("DoRestoreFS This drive already has FS intalled:%S \n"), &fsName);
176 return KErrAlreadyExists;
179 TPtrC ptrN (apFsDesc->FsName());
180 TPtrC ptrExt(apFsDesc->PrimaryExtName());
181 test.Printf(_L("DoRestoreFS Mounting FS:%S, Prim ext:%S, synch:%d\n"), &ptrN, &ptrExt, apFsDesc->DriveIsSynch());
183 if(ptrExt.Length() >0)
184 {//-- there is a primary extension to be mounted
185 nRes = aFs.AddExtension(ptrExt);
186 if(nRes != KErrNone && nRes != KErrAlreadyExists)
191 nRes = aFs.MountFileSystem(ptrN, ptrExt, aDrive, apFsDesc->DriveIsSynch());
195 nRes = aFs.MountFileSystem(ptrN, aDrive, apFsDesc->DriveIsSynch());
200 test.Printf(_L("DoRestoreFS Mount failed! code:%d\n"),nRes);
207 //-----------------------------------------------------------------------------
209 Dismount the original FS from the drive and mount MsFS instead
211 LOCAL_C void MountMsFs(TInt driveNumber)
213 test.Printf(_L("MountMsFs driveNumber=%d\n"), driveNumber);
215 //-- 1. try dismounting the original FS
216 CFileSystemDescriptor* fsDesc = DoDismountOrginalFS(fs, driveNumber);
217 unmountedFsList[driveNumber] = fsDesc;
221 TPtrC ptrN(fsDesc->FsName());
222 test.Printf(_L("drv:%d FS:%S Dismounted OK\n"),driveNumber, &ptrN);
226 test.Printf(_L("drv:%d Dismount FS Failed!\n"),driveNumber);
229 //-- 2. try to mount the "MSFS"
231 error = fs.MountFileSystem(KMsFs, driveNumber);
232 test.Printf(_L("MSFS Mount: %S (%d)\n"), (error?&KError:&KOk), error);
234 msfsMountedList[driveNumber] = ETrue;
238 //-----------------------------------------------------------------------------
240 Dismount MsFS and mount the original FS
242 LOCAL_C TInt RestoreMount(TInt driveNumber)
246 //-- 1. try dismounting the "MSFS"
247 if (msfsMountedList[driveNumber])
249 err = fs.DismountFileSystem(KMsFs, driveNumber);
250 test.Printf(_L("MSFS Dismount:%S (%d)\n"), (err?&KError:&KOk), err);
254 msfsMountedList[driveNumber] = EFalse;
257 //-- 2. try to mount the original FS back
258 CFileSystemDescriptor* fsDesc = unmountedFsList[driveNumber];
261 err = DoRestoreFS(fs, driveNumber, fsDesc);
263 TPtrC ptrN(fsDesc->FsName());
264 test.Printf(_L("%S Mount: %S (%d)\n"), &ptrN, (err?&KError:&KOk), err);
267 unmountedFsList[driveNumber] = NULL;
273 //////////////////////////////////////////////////////////////////////////////
276 // An active object that tracks changes to the KUsbMsDriveState properties
278 //////////////////////////////////////////////////////////////////////////////
280 CPropertyWatch* CPropertyWatch::NewLC(TUsbMsDriveState_Subkey aSubkey, PropertyHandlers::THandler aHandler)
282 CPropertyWatch* me=new(ELeave) CPropertyWatch(aHandler);
283 CleanupStack::PushL (me);
284 me->ConstructL(aSubkey);
289 CPropertyWatch::CPropertyWatch(PropertyHandlers::THandler aHandler)
290 : CActive(0), iHandler(aHandler)
293 void CPropertyWatch::ConstructL(TUsbMsDriveState_Subkey aSubkey)
295 User::LeaveIfError(iProperty.Attach(KUsbMsDriveState_Category, aSubkey));
296 CActiveScheduler::Add(this);
297 // initial subscription and process current property value
301 CPropertyWatch::~CPropertyWatch()
307 void CPropertyWatch::DoCancel()
312 void CPropertyWatch::RunL()
314 // resubscribe before processing new value to prevent missing updates
315 iProperty.Subscribe(iStatus);
321 //////////////////////////////////////////////////////////////////////////////
325 //////////////////////////////////////////////////////////////////////////////
327 CUsbWatch* CUsbWatch::NewLC(RUsb& aUsb)
329 CUsbWatch* me=new(ELeave) CUsbWatch(aUsb);
330 CleanupStack::PushL (me);
336 CUsbWatch::CUsbWatch(RUsb& aUsb)
340 iUsbDeviceState(EUsbcDeviceStateUndefined),
341 iWasConfigured(EFalse)
344 void CUsbWatch::ConstructL()
346 CActiveScheduler::Add(this);
350 CUsbWatch::~CUsbWatch()
353 iUsb.AlternateDeviceStatusNotifyCancel();
356 void CUsbWatch::DoCancel()
358 iUsb.AlternateDeviceStatusNotifyCancel();
361 static TBool IsDriveConnected(TInt driveStatusIndex)
363 TInt driveStatus = PropertyHandlers::allDrivesStatus[2*driveStatusIndex+1];
364 return driveStatus >= EUsbMsDriveState_Connected ? ETrue : EFalse;
367 static TChar DriveNumberToLetter(TInt driveNumber)
369 TChar driveLetter = '?';
370 fs.DriveToChar(driveNumber, driveLetter);
374 static TBool IsDriveInMountList(TUint driveLetter)
376 TUint16 driveLetter16 = static_cast<TUint16>(driveLetter);
377 return(!mountList.Length() || KErrNotFound != mountList.Find(&driveLetter16, 1));
380 void CUsbWatch::RunL()
382 gActiveControl->SetMSFinished(EFalse);
385 switch (iUsbDeviceState)
387 case EUsbcDeviceStateUndefined : // 0
388 test.Printf(_L(">> CUSBWatch:Undefined %S\n"), iWasConfigured ? &KConfigured : &KNotConfigured);
391 case EUsbcDeviceStateAttached : // 1
392 test.Printf(_L(">> CUSBWatch:Attached %S\n"), iWasConfigured ? &KConfigured : &KNotConfigured);
395 case EUsbcDeviceStatePowered : // 2
396 test.Printf(_L(">> CUSBWatch:Powered %S\n"), iWasConfigured ? &KConfigured : &KNotConfigured);
399 case EUsbcDeviceStateDefault : // 3
400 test.Printf(_L(">> CUSBWatch:Default %S\n"), iWasConfigured ? &KConfigured : &KNotConfigured);
403 case EUsbcDeviceStateAddress : // 4
404 test.Printf(_L(">> CUSBWatch:Address %S\n"), iWasConfigured ? &KConfigured : &KNotConfigured);
407 case EUsbcDeviceStateConfigured : // 5
408 test.Printf(_L(">> CUSBWatch:Configured %S\n"), iWasConfigured ? &KConfigured : &KNotConfigured);
411 case EUsbcDeviceStateSuspended : // 6
412 test.Printf(_L(">> CUSBWatch:Suspended %S\n"), iWasConfigured ? &KConfigured : &KNotConfigured);
416 test.Printf(_L(">> CUSBWatch:UNKNOWN %S\n"), iWasConfigured ? &KConfigured : &KNotConfigured);
421 iUsb.AlternateDeviceStatusNotify(iStatus, iUsbDeviceState);
424 // If the cable is disconnected, unmount all the connected drives.
425 if(iWasConfigured && iUsbDeviceState == EUsbcDeviceStateUndefined)
427 for(TInt i=0; i<PropertyHandlers::allDrivesStatus.Length()/2; i++)
429 if(IsDriveConnected(i))
431 RDebug::Print(_L("CUsbWatch calling RestoreMount"));
432 RestoreMount(PropertyHandlers::allDrivesStatus[2*i]);
436 iWasConfigured = EFalse;
439 // If cable is connected, mount all drives in the auto-mount list.
440 // This is done for performance, since if this is not done here,
441 // mounting will happen later after each drive enters the
443 if(iUsbDeviceState == EUsbcDeviceStateConfigured)
445 for(TInt i=0; i<PropertyHandlers::allDrivesStatus.Length()/2; i++)
447 TInt driveNumber = PropertyHandlers::allDrivesStatus[2*i];
448 if(!IsDriveConnected(i) && IsDriveInMountList(DriveNumberToLetter(driveNumber)))
450 RDebug::Print(_L("CUsbWatch calling MountMsFs"));
451 MountMsFs(driveNumber);
455 iWasConfigured = ETrue;
459 //////////////////////////////////////////////////////////////////////////////
463 //////////////////////////////////////////////////////////////////////////////
465 TBuf8<16> PropertyHandlers::allDrivesStatus;
466 TUsbMsBytesTransferred PropertyHandlers::iKBytesRead;
467 TUsbMsBytesTransferred PropertyHandlers::iKBytesWritten;
468 TInt PropertyHandlers::iMediaError;
470 void PropertyHandlers::Read(RProperty& aProperty)
472 Transferred(aProperty, iKBytesRead);
475 void PropertyHandlers::Written(RProperty& aProperty)
477 Transferred(aProperty, iKBytesWritten);
480 void PropertyHandlers::Transferred(RProperty& aProperty, TUsbMsBytesTransferred& aReadOrWritten)
482 TInt err = aProperty.Get(aReadOrWritten);
485 for(TInt i = 0; i < allDrivesStatus.Length()/2; i++)
489 test.Printf(KBytesTransferredFmt,
490 (char)DriveNumberToLetter(allDrivesStatus[2*i]), iKBytesRead[i], iKBytesWritten[i]);
496 test.Printf(KErrFmt, err);
500 void PropertyHandlers::DriveStatus(RProperty& aProperty)
504 test.Printf(_L(">> PropertyHandlers::DriveStatus"));
506 TInt err = aProperty.Get(allDrivesStatus);
511 test.Printf(_L(" Status: "));
513 for(TInt i = 0; i < allDrivesStatus.Length()/2; i++)
515 TInt driveNumber = allDrivesStatus[2*i];
516 TInt driveStatus = allDrivesStatus[2*i+1];
517 TChar driveLetter = DriveNumberToLetter(driveNumber);
523 case EUsbMsDriveState_Disconnected:
525 test.Printf(_L("%c:%d:Disconnected\n"), (char)driveLetter, driveStatus);
528 case EUsbMsDriveState_Connecting:
530 test.Printf(_L("%c:%d:Connecting\n"), (char)driveLetter, driveStatus);
533 case EUsbMsDriveState_Connected:
535 test.Printf(_L("%c:%d:Connected\n"), (char)driveLetter, driveStatus);
538 case EUsbMsDriveState_Disconnecting:
540 test.Printf(_L("%c:%d:Disconnecting\n"), (char)driveLetter, driveStatus);
543 case EUsbMsDriveState_Active:
545 test.Printf(_L("%c:%d:Active\n"), (char)driveLetter, driveStatus);
548 case EUsbMsDriveState_Locked:
550 test.Printf(_L("%c:%d:Locked\n"), (char)driveLetter, driveStatus);
553 case EUsbMsDriveState_MediaNotPresent:
555 test.Printf(_L("%c:%d:Not Present\n"), (char)driveLetter, driveStatus);
558 case EUsbMsDriveState_Removed:
560 test.Printf(_L("%c:%d:Removed\n"), (char)driveLetter, driveStatus);
563 case EUsbMsDriveState_Error:
565 test.Printf(_L("%c:%d:Error\n"), (char)driveLetter, driveStatus);
570 test.Printf(_L("%c:%d:Unknown\n"), (char)driveLetter, driveStatus);
576 if (driveStatus == EUsbMsDriveState_Connected)
578 gActiveControl->SetMSFinished(EFalse);
580 if (driveStatus == EUsbMsDriveState_Disconnected)
582 gActiveControl->SetMSFinished(ETrue);
584 if(IsDriveInMountList(driveLetter))
586 if (driveStatus == EUsbMsDriveState_Connecting)
588 MountMsFs(driveNumber);
590 else if (driveStatus == EUsbMsDriveState_Disconnecting)
592 RestoreMount(driveNumber);
596 //RDebug::Print(_L("PropertyHandlers::DriveStatus: nothing to do"));
601 //RDebug::Print(_L("PropertyHandlers::DriveStatus: %c: is not in mountList\n"), driveLetter);
607 test.Printf(KErrFmt, err);
612 void PropertyHandlers::MediaError(RProperty& aProperty)
614 TInt r = aProperty.Get(iMediaError);
620 test.Printf(_L("Media Error %x\n"), iMediaError);
623 gActiveControl->SetMSFinished(ETrue);
628 void StartMassStorage(RDEVCLIENT* aPort)
630 TInt r = KErrUnknown;
632 test.Start (_L("Start Mass Storage"));
636 // Add MS file system
637 test.Next (_L("Add MS File System"));
638 r = fs.AddFileSystem(KMsFsy);
639 test(r == KErrNone || r == KErrAlreadyExists);
642 aPort->FinalizeInterface();
646 test.Next (_L("Create active objects\n"));
647 propWatch[0] = CPropertyWatch::NewLC(EUsbMsDriveState_KBytesRead, PropertyHandlers::Read);
648 propWatch[1] = CPropertyWatch::NewLC(EUsbMsDriveState_KBytesWritten, PropertyHandlers::Written);
649 propWatch[2] = CPropertyWatch::NewLC(EUsbMsDriveState_DriveStatus, PropertyHandlers::DriveStatus);
650 propWatch[3] = CPropertyWatch::NewLC(EUsbMsDriveState_MediaError, PropertyHandlers::MediaError);
651 usbWatch = CUsbWatch::NewLC(*aPort);
653 TBuf<8> t_vendorId(_L("vendor"));
654 TBuf<16> t_productId(_L("product"));
655 TBuf<4> t_productRev(_L("1.00"));
657 TMassStorageConfig msConfig;
658 msConfig.iVendorId.Copy(t_vendorId);
659 msConfig.iProductId.Copy(t_productId);
660 msConfig.iProductRev.Copy(t_productRev);
662 test.Next(_L("Connect to Mass Storage"));
666 test.Next(_L("Start Mass Storage"));
667 r = UsbMs.Start(msConfig);
673 void StopMassStorage(RDEVCLIENT* aPort)
675 TInt r = KErrUnknown;
677 test.Start (_L("Stop Mass Storage"));
683 for (TInt driveNumber = 0; driveNumber < KMaxDrives; driveNumber++)
685 if (msfsMountedList[driveNumber])
687 r = fs.DismountFileSystem(KMsFs, driveNumber);
690 msfsMountedList[driveNumber] = EFalse;
694 r = fs.RemoveFileSystem(KMsFs);
700 for (TUint i =0; i < KNumPropWatch; i++)