First public contribution.
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 - also used as an improvised boot loader mechanism
25 #include <e32std_private.h>
30 #include <usbmsshared.h>
31 #include <massstorage.h>
33 TBool gSharedChunkLdd = EFalse;
34 #include <d32usbcsc.h>
37 #ifdef BUILD_OTG_USBMSAPP
41 #include <nkern/nk_trace.h>
44 #ifdef USB_BOOT_LOADER
46 #include "usbbootvar.h"
47 #include <rebootdrv.h>
48 #define KNANDLDRLDD_NAME _L("REBOOT.LDD")
49 static RReboot* RebootDrv;
52 /// Global number of seconds to delay before reboot
53 static TInt gRebootDelay = 0;
59 EUsbDeviceStateUndefined = EUsbcDeviceStateUndefined,
60 EUsbDeviceStateConfigured = EUsbcDeviceStateConfigured,
63 static CConsoleBase* console = NULL;
65 static TInt selectedDriveIndex = 0;
66 static TBuf<0x40> mountList;
68 static TFixedArray<TBool, KMaxDrives> msfsMountedList; ///< 'true' entry corresponds to the drive with mounted MSFS.FSY
69 static TFixedArray<CFileSystemDescriptor*, KMaxDrives> unmountedFsList; ///< every non-NULL entry corresponds to the unmounted original FS for the drive
72 _LIT(KMsFsy, "MSFS.FSY");
73 _LIT(KMsFs, "MassStorageFileSystem");
77 _LIT(KBytesTransferredFmt, "%c:%d/%d ");
78 _LIT(KErrFmt, "Error: %d\r");
80 #ifndef USB_BOOT_LOADER
81 _LIT(KTxtApp,"USBMSAPP");
85 //-- if defined, some useful information will be printed out via RDebug interface
86 //#define LOGGING_ENABLED
88 //-----------------------------------------------------------------------------
90 prints a line to the console and copies it to the debug log if LOGGING_ENABLED
92 void LogPrint(TRefByValue<const TDesC> aFmt,...)
98 // coverity[uninit_use_in_call]
99 buf.FormatList(aFmt, list); //-- ignore overflows
104 #ifdef LOGGING_ENABLED
105 //-- print out the line via RDebug::Print
106 const TInt bufLen = buf.Length();
107 if(bufLen >0 && buf[bufLen-1] == '\n')
109 buf.Insert(bufLen-1, _L("\r"));
113 buf.Append(_L("\r\n"));
116 RDebug::RawPrint(buf);
120 //-----------------------------------------------------------------------------
122 prints a line to the debug log if LOGGING_ENABLED
124 void Log(TRefByValue<const TDesC> aFmt,...)
126 #ifdef LOGGING_ENABLED
129 VA_START(list, aFmt);
132 buf.FormatList(aFmt, list); //-- ignore overflows
134 //-- print out the line via RDebug::Print
135 const TInt bufLen = buf.Length();
136 if(bufLen >0 && buf[bufLen-1] == '\n')
138 buf.Insert(bufLen-1, _L("\r"));
141 RDebug::RawPrint(buf);
148 //-----------------------------------------------------------------------------
150 static void Clear(int row, int count=1)
153 for(TInt i=0; i<count; i++)
155 console->SetPos(0,row+i);
156 console->Printf(KBlank);
158 console->SetPos(0,row);
162 static void ShowDriveSelection()
164 console->SetPos(0,15);
165 if(PropertyHandlers::allDrivesStatus.Length()/2 > selectedDriveIndex)
167 LogPrint(_L("Selected Drive: %c"), 'A' + PropertyHandlers::allDrivesStatus[selectedDriveIndex*2]);
171 LogPrint(_L("Selected Drive: (none)"));
176 #ifdef USB_BOOT_LOADER
178 static void rebootit()
180 TInt r=User::LoadLogicalDevice(KNANDLDRLDD_NAME);
181 RebootDrv=new RReboot;
184 User::Panic(_L("Loading driver"),1);
189 User::Panic(_L("Opening driver"),r);
194 _LIT(KMsgRebooting,"*** Reboot in %d secs ***\n");
195 TInt delay=gRebootDelay;
196 console->SetPos(0,20);
199 LogPrint(KMsgRebooting, delay);
200 User::After(1000000);
203 r=RebootDrv->VariantCtrl(KVariantUsbmsVariantRebootReason, NULL);
206 User::Panic(_L("Rebooting"),r);
212 class CPeriodUpdate : public CActive
215 static CPeriodUpdate* NewLC();
227 CPeriodUpdate* CPeriodUpdate::NewLC()
229 CPeriodUpdate* me=new(ELeave) CPeriodUpdate();
230 CleanupStack::PushL(me);
235 CPeriodUpdate::CPeriodUpdate()
236 : CActive(0), iUpTime(0)
239 void CPeriodUpdate::ConstructL()
241 CActiveScheduler::Add(this);
242 iTimer.CreateLocal();
246 CPeriodUpdate::~CPeriodUpdate()
251 void CPeriodUpdate::DoCancel()
255 void CPeriodUpdate::RunL()
258 // Print RAM usage & up time
261 TUint totmins=(iUpTime/60);
262 TUint tothrs=(totmins/60);
264 if (HAL::Get(HALData::EMemoryRAMFree, mem)==KErrNone)
266 console->SetPos(0,22);
267 console->Printf(_L("mem (bytes) : %d\n"), mem);
268 console->Printf(_L("up time : %dh:%dm:%ds\n"),
269 tothrs, totmins%60, iUpTime%60);
271 iTimer.After(iStatus, 1000000);
274 //-----------------------------------------------------------------------------
276 Dismounts the originally mounted FS and optional primary extension from the drive and stores
277 this information in the FS descriptor
279 @return on success returns a pointer to the instantinated FS descriptor
281 static CFileSystemDescriptor* DoDismountOrginalFS(RFs& aFs, TInt aDrive)
285 TBuf<128> primaryExtName;
286 TBool bDrvSync = EFalse;
288 Log(_L("# DoDismountOrginalFS drv:%d\n"), aDrive);
290 //-- 1. get file system name
291 nRes = aFs.FileSystemName(fsName, aDrive);
293 {//-- probably no file system installed at all
297 //-- 2. find out if the drive sync/async
298 TPckgBuf<TBool> drvSyncBuf;
299 nRes = aFs.QueryVolumeInfoExt(aDrive, EIsDriveSync, drvSyncBuf);
302 bDrvSync = drvSyncBuf();
305 //-- 3. find out primary extension name if it is present; we will need to add it againt when mounting the FS
306 //-- other extensions (non-primary) are not supported yet
307 nRes = aFs.ExtensionName(primaryExtName, aDrive, 0);
310 primaryExtName.SetLength(0);
313 //-- 3.1 check if the drive has non-primary extensions, fail in this case, because this FS can't be mounted back normally
314 nRes = aFs.ExtensionName(primaryExtName, aDrive, 1);
317 LogPrint(_L("Non-primary extensions are not supported!\n"));
321 Log(_L("# DoDismountOrginalFS FS:%S, Prim ext:%S, synch:%d\n"), &fsName, &primaryExtName, bDrvSync);
323 //-- create FS descriptor and dismount the FS
324 CFileSystemDescriptor* pFsDesc = NULL;
326 TRAP(nRes, pFsDesc = CFileSystemDescriptor::NewL(fsName, primaryExtName, bDrvSync));
328 return NULL; //-- OOM ?
330 nRes = aFs.DismountFileSystem(fsName, aDrive);
335 Log(_L("# DoDismountOrginalFS Dismounting Err:%d\n"), nRes);
341 //-----------------------------------------------------------------------------
343 Tries to restore the original FS on the drive using the FS descriptor provided
344 @return standard error code.
346 static TInt DoRestoreFS(RFs& aFs, TInt aDrive, CFileSystemDescriptor* apFsDesc)
350 Log(_L("# DoRestoreFS drv:%d\n"), aDrive);
352 //-- 1. check that there is no FS installed
355 nRes = aFs.FileSystemName(fsName, aDrive);
357 {//-- probably no file system installed at all
358 Log(_L("# This drive already has FS intalled:%S \n"), &fsName);
359 return KErrAlreadyExists;
363 TPtrC ptrN (apFsDesc->FsName());
364 TPtrC ptrExt(apFsDesc->PrimaryExtName());
365 Log(_L("# Mounting FS:%S, Prim ext:%S, synch:%d\n"), &ptrN, &ptrExt, apFsDesc->DriveIsSynch());
367 if(ptrExt.Length() >0)
368 {//-- there is a primary extension to be mounted
369 nRes = aFs.AddExtension(ptrExt);
370 if(nRes != KErrNone && nRes != KErrAlreadyExists)
375 nRes = aFs.MountFileSystem(ptrN, ptrExt, aDrive, apFsDesc->DriveIsSynch());
379 nRes = aFs.MountFileSystem(ptrN, aDrive, apFsDesc->DriveIsSynch());
384 Log(_L("# Mount failed! code:%d\n"),nRes);
391 //-----------------------------------------------------------------------------
393 Dismount the original FS from the drive and mount MsFS instead
395 static void MountMsFs(TInt driveNumber)
397 TInt x = console->WhereX();
398 TInt y = console->WhereY();
400 //-- 1. try dismounting the original FS
401 CFileSystemDescriptor* fsDesc = DoDismountOrginalFS(fs, driveNumber);
402 unmountedFsList[driveNumber] = fsDesc;
404 console->SetPos(0, 10);
408 TPtrC ptrN(fsDesc->FsName());
409 LogPrint(_L("drv:%d FS:%S Dismounted OK"),driveNumber, &ptrN);
413 LogPrint(_L("drv:%d Dismount FS Failed!"),driveNumber);
416 console->ClearToEndOfLine();
418 //-- 2. try to mount the "MSFS"
420 error = fs.MountFileSystem(KMsFs, driveNumber);
421 console->SetPos(0, 11);
422 LogPrint(_L("MSFS Mount: %S (%d)"), (error?&KError:&KOk), error);
423 console->ClearToEndOfLine();
426 msfsMountedList[driveNumber] = ETrue;
428 // restore console position
429 console->SetPos(x,y);
432 //-----------------------------------------------------------------------------
434 Dismount MsFS and mount the original FS
436 static TInt RestoreMount(TInt driveNumber)
440 TInt x = console->WhereX();
441 TInt y = console->WhereY();
443 //-- 1. try dismounting the "MSFS"
444 if (msfsMountedList[driveNumber])
446 err = fs.DismountFileSystem(KMsFs, driveNumber);
447 console->SetPos(0, 11);
448 LogPrint(_L("MSFS Dismount:%S (%d)"), (err?&KError:&KOk), err);
449 console->ClearToEndOfLine();
453 msfsMountedList[driveNumber] = EFalse;
456 //-- 2. try to mount the original FS back
457 CFileSystemDescriptor* fsDesc = unmountedFsList[driveNumber];
460 err = DoRestoreFS(fs, driveNumber, fsDesc);
462 TPtrC ptrN(fsDesc->FsName());
463 console->SetPos(0, 10);
464 LogPrint(_L("%S Mount: %S (%d)"), &ptrN, (err?&KError:&KOk), err);
465 console->ClearToEndOfLine();
468 unmountedFsList[driveNumber] = NULL;
472 // restore console position
473 console->SetPos(x,y);
477 //////////////////////////////////////////////////////////////////////////////
480 // An active object that tracks changes to the KUsbMsDriveState properties
482 //////////////////////////////////////////////////////////////////////////////
484 CPropertyWatch* CPropertyWatch::NewLC(TUsbMsDriveState_Subkey aSubkey, PropertyHandlers::THandler aHandler)
486 CPropertyWatch* me=new(ELeave) CPropertyWatch(aHandler);
487 CleanupStack::PushL(me);
488 me->ConstructL(aSubkey);
492 CPropertyWatch::CPropertyWatch(PropertyHandlers::THandler aHandler)
493 : CActive(0), iHandler(aHandler)
496 void CPropertyWatch::ConstructL(TUsbMsDriveState_Subkey aSubkey)
498 User::LeaveIfError(iProperty.Attach(KUsbMsDriveState_Category, aSubkey));
499 CActiveScheduler::Add(this);
500 // initial subscription and process current property value
504 CPropertyWatch::~CPropertyWatch()
510 void CPropertyWatch::DoCancel()
515 void CPropertyWatch::RunL()
517 // resubscribe before processing new value to prevent missing updates
518 iProperty.Subscribe(iStatus);
524 //////////////////////////////////////////////////////////////////////////////
528 //////////////////////////////////////////////////////////////////////////////
530 CUsbWatch* CUsbWatch::NewLC(TAny* aUsb)
532 CUsbWatch* me=new(ELeave) CUsbWatch(aUsb);
533 CleanupStack::PushL(me);
538 CUsbWatch::CUsbWatch(TAny* aUsb)
542 iUsbDeviceState(EUsbDeviceStateUndefined),
543 iWasConfigured(EFalse)
546 void CUsbWatch::ConstructL()
548 CActiveScheduler::Add(this);
552 CUsbWatch::~CUsbWatch()
555 // iUsb.DeviceStateNotificationCancel();
557 ((RDevUsbcScClient*)iUsb)->AlternateDeviceStatusNotifyCancel();
559 ((RDevUsbcClient*)iUsb)->AlternateDeviceStatusNotifyCancel();
562 void CUsbWatch::DoCancel()
564 // iUsb.DeviceStateNotificationCancel();
566 ((RDevUsbcScClient*)iUsb)->AlternateDeviceStatusNotifyCancel();
568 ((RDevUsbcClient*)iUsb)->AlternateDeviceStatusNotifyCancel();
571 static TBool IsDriveConnected(TInt driveStatusIndex)
573 TInt driveStatus = PropertyHandlers::allDrivesStatus[2*driveStatusIndex+1];
574 return driveStatus >= EUsbMsDriveState_Connected ? ETrue : EFalse;
577 static TChar DriveNumberToLetter(TInt driveNumber)
579 TChar driveLetter = '?';
580 fs.DriveToChar(driveNumber, driveLetter);
584 static TBool IsDriveInMountList(TUint driveLetter)
586 TUint16 driveLetter16 = static_cast<TUint16>(driveLetter);
587 return(!mountList.Length() || KErrNotFound != mountList.Find(&driveLetter16, 1));
590 void CUsbWatch::RunL()
592 // RDebug::Print(_L(">> CUsbWatch[%d] %d"), iUsbDeviceState, iWasConfigured);
594 // const TUint stateMask = 0xFF;
595 // iUsb.DeviceStateNotification(stateMask, iUsbDeviceState, iStatus);
597 ((RDevUsbcScClient*)iUsb)->AlternateDeviceStatusNotify(iStatus, iUsbDeviceState);
599 ((RDevUsbcClient*)iUsb)->AlternateDeviceStatusNotify(iStatus, iUsbDeviceState);
603 //RDebug::Print(_L("CUsbWatch DeviceStateNotification: iUsbDeviceState=%d"), iUsbDeviceState);
605 // If the cable is disconnected, unmount all the connected drives.
606 if(iWasConfigured && iUsbDeviceState == EUsbDeviceStateUndefined)
608 for(TInt i=0; i<PropertyHandlers::allDrivesStatus.Length()/2; i++)
610 if(IsDriveConnected(i))
612 //RDebug::Print(_L("CUsbWatch calling RestoreMount"));
613 RestoreMount(PropertyHandlers::allDrivesStatus[2*i]);
614 #ifdef USB_BOOT_LOADER
616 CActiveScheduler::Stop();
621 iWasConfigured = EFalse;
624 // If cable is connected, mount all drives in the auto-mount list.
625 // This is done for performance, since if this is not done here,
626 // mounting will happen later after each drive enters the
628 if(iUsbDeviceState == EUsbDeviceStateConfigured)
630 for(TInt i=0; i<PropertyHandlers::allDrivesStatus.Length()/2; i++)
632 TInt driveNumber = PropertyHandlers::allDrivesStatus[2*i];
633 if(!IsDriveConnected(i) && IsDriveInMountList(DriveNumberToLetter(driveNumber)))
635 //RDebug::Print(_L("CUsbWatch calling MountMsFs"));
636 MountMsFs(driveNumber);
640 iWasConfigured = ETrue;
644 //////////////////////////////////////////////////////////////////////////////
648 //////////////////////////////////////////////////////////////////////////////
650 TBuf8<16> PropertyHandlers::allDrivesStatus;
651 TUsbMsBytesTransferred PropertyHandlers::iKBytesRead;
652 TUsbMsBytesTransferred PropertyHandlers::iKBytesWritten;
653 TInt PropertyHandlers::iMediaError;
655 void PropertyHandlers::Read(RProperty& aProperty)
657 Transferred(aProperty, iKBytesRead);
660 void PropertyHandlers::Written(RProperty& aProperty)
662 Transferred(aProperty, iKBytesWritten);
665 void PropertyHandlers::Transferred(RProperty& aProperty, TUsbMsBytesTransferred& aReadOrWritten)
667 console->SetPos(0,1);
668 console->Printf(_L("KB R/W: "));
669 TInt err = aProperty.Get(aReadOrWritten);
672 for(TInt i = 0; i < allDrivesStatus.Length()/2; i++)
674 console->Printf(KBytesTransferredFmt, (char)DriveNumberToLetter(allDrivesStatus[2*i]), iKBytesRead[i], iKBytesWritten[i]);
676 console->ClearToEndOfLine();
680 console->Printf(KErrFmt, err);
684 void PropertyHandlers::DriveStatus(RProperty& aProperty)
686 // RDebug::Print(_L(">> PropertyHandlers::DriveStatus"));
687 TInt err = aProperty.Get(allDrivesStatus);
688 console->SetPos(0,0);
691 LogPrint(_L("Status: "));
692 for(TInt i = 0; i < allDrivesStatus.Length()/2; i++)
694 TInt driveNumber = allDrivesStatus[2*i];
695 TInt driveStatus = allDrivesStatus[2*i+1];
696 TChar driveLetter = DriveNumberToLetter(driveNumber);
698 // RDebug::Print(_L("%c:%d "), (char)driveLetter, driveStatus);
702 case EUsbMsDriveState_Disconnected:
704 LogPrint(_L("%c:%d:Disconnected "), (char)driveLetter, driveStatus);
707 case EUsbMsDriveState_Connecting:
709 LogPrint(_L("%c:%d:Connecting "), (char)driveLetter, driveStatus);
712 case EUsbMsDriveState_Connected:
714 LogPrint(_L("%c:%d:Connected "), (char)driveLetter, driveStatus);
717 case EUsbMsDriveState_Disconnecting:
719 LogPrint(_L("%c:%d:Disconnecting"), (char)driveLetter, driveStatus);
722 case EUsbMsDriveState_Active:
724 LogPrint(_L("%c:%d:Active "), (char)driveLetter, driveStatus);
727 case EUsbMsDriveState_Locked:
729 LogPrint(_L("%c:%d:Locked "), (char)driveLetter, driveStatus);
732 case EUsbMsDriveState_MediaNotPresent:
734 LogPrint(_L("%c:%d:Not Present "), (char)driveLetter, driveStatus);
737 case EUsbMsDriveState_Removed:
739 LogPrint(_L("%c:%d:Removed "), (char)driveLetter, driveStatus);
742 case EUsbMsDriveState_Error:
744 LogPrint(_L("%c:%d:Error "), (char)driveLetter, driveStatus);
749 LogPrint(_L("%c:%d:Unknown "), (char)driveLetter, driveStatus);
754 if(IsDriveInMountList(driveLetter))
756 #ifndef USB_BOOT_LOADER
757 if (driveStatus == EUsbMsDriveState_Connecting)
759 MountMsFs(driveNumber);
761 else if (driveStatus == EUsbMsDriveState_Disconnected)
763 RestoreMount(driveNumber);
766 if (driveStatus == EUsbMsDriveState_Disconnecting)
768 RestoreMount(driveNumber);
770 else if (driveStatus == EUsbMsDriveState_Disconnected)
772 static TBool firstTime = ETrue;
776 RDebug::Print(_L("Eject..."));
777 // Exit and reboot the target upon receipt of an eject
778 CActiveScheduler::Stop();
787 //RDebug::Print(_L("PropertyHandlers::DriveStatus: nothing to do"));
792 //RDebug::Print(_L("PropertyHandlers::DriveStatus: %c: is not in mountList\n"), driveLetter);
798 LogPrint(KErrFmt, err);
801 //RDebug::Print(_L("<< PropertyHandlers::DriveStatus"));
804 void PropertyHandlers::MediaError(RProperty& aProperty)
806 TInt err = aProperty.Get(iMediaError);
809 // RDebug::Printf("RProperty::Get returned %d", err);
813 //RDebug::Printf("PropertyHandlers::MediaError %x", iMediaError);
815 TInt x = console->WhereX();
816 TInt y = console->WhereY();
818 LogPrint(_L("Media Error %x"), iMediaError);
819 // restore console position
820 console->SetPos(x,y);
823 //////////////////////////////////////////////////////////////////////////////
825 // CMessageKeyProcessor
827 //////////////////////////////////////////////////////////////////////////////
828 CMessageKeyProcessor::CMessageKeyProcessor(CConsoleBase* aConsole)
829 : CActive(CActive::EPriorityUserInput), iConsole(aConsole)
833 CMessageKeyProcessor* CMessageKeyProcessor::NewLC(CConsoleBase* aConsole
836 CMessageKeyProcessor* self=new (ELeave) CMessageKeyProcessor(aConsole);
837 CleanupStack::PushL(self);
842 CMessageKeyProcessor* CMessageKeyProcessor::NewL(CConsoleBase* aConsole
845 CMessageKeyProcessor* self = NewLC(aConsole);
850 void CMessageKeyProcessor::ConstructL()
852 // Add to active scheduler
853 CActiveScheduler::Add(this);
857 #ifndef USB_BOOT_LOADER
858 void CMessageKeyProcessor::MakePassword(TMediaPassword &aPassword)
860 // Create password with same format as eshell and S60
861 TBuf<3> password(KDefPwd);
863 // fill aPassword with contents of password, not converting to ASCII
864 const TInt byteLen = password.Length() * 2;
865 aPassword.Copy(reinterpret_cast<const TUint8 *>(password.Ptr()), byteLen);
870 CMessageKeyProcessor::~CMessageKeyProcessor()
872 // Make sure we're cancelled
876 void CMessageKeyProcessor::DoCancel()
878 iConsole->ReadCancel();
881 void CMessageKeyProcessor::RunL()
883 // Handle completed request
884 ProcessKeyPress(TChar(iConsole->KeyCode()));
887 void CMessageKeyProcessor::RequestCharacter()
889 // A request is issued to the CConsoleBase to accept a
890 // character from the keyboard.
891 iConsole->Read(iStatus);
895 void CMessageKeyProcessor::ProcessKeyPress(TChar aChar)
897 #ifndef USB_BOOT_LOADER
898 TInt error = KErrNone;
901 static TBool tracetoggle=EFalse;
911 for(TInt j=0; j<KMaxDrives; j++)
913 err = RestoreMount(j);
917 // Mount is busy/locked and can not be restored.
925 #ifdef USB_BOOT_LOADER
926 gRebootDelay=0; // Force reboot to occur immediately
928 CActiveScheduler::Stop();
938 tracetoggle=!tracetoggle;
939 if (tracetoggle) // 0x44008401
940 User::SetDebugMask(KHARDWARE|KDLL|KSCRATCH|KPOWER|KMEMTRACE);
942 User::SetDebugMask(0);
946 #ifndef USB_BOOT_LOADER
949 if(++selectedDriveIndex >= PropertyHandlers::allDrivesStatus.Length()/2)
951 selectedDriveIndex = 0;
953 ShowDriveSelection();
958 if(PropertyHandlers::allDrivesStatus.Length())
960 MountMsFs(PropertyHandlers::allDrivesStatus[selectedDriveIndex*2]);
966 if(PropertyHandlers::allDrivesStatus.Length())
968 RestoreMount(PropertyHandlers::allDrivesStatus[selectedDriveIndex*2]);
974 // lock unprotected drive
975 TMediaPassword password;
976 MakePassword(password);
981 error = fs.LockDrive(PropertyHandlers::allDrivesStatus[selectedDriveIndex*2],
982 nul, password, ETrue);
983 console->SetPos(0,9);
984 LogPrint(_L("LockDrive %S (%d)"), (error?&KError:&KOk), error);
990 // lock password protected drive
991 TMediaPassword password;
992 MakePassword(password);
993 error = fs.LockDrive(PropertyHandlers::allDrivesStatus[selectedDriveIndex*2],
994 password, password, ETrue);
995 console->SetPos(0,9);
996 LogPrint(_L("LockDrive %S (%d)"), (error?&KError:&KOk), error);
1003 TMediaPassword password;
1004 MakePassword(password);
1005 error = fs.UnlockDrive(PropertyHandlers::allDrivesStatus[selectedDriveIndex*2],
1008 LogPrint(_L("UnlockDrive %S (%d)"), (error?&KError:&KOk), error);
1015 TMediaPassword password;
1016 MakePassword(password);
1017 error = fs.ClearPassword(PropertyHandlers::allDrivesStatus[selectedDriveIndex*2],
1020 LogPrint(_L("ClearPassword %S (%d)"), (error?&KError:&KOk), error);
1031 #ifdef USB_BOOT_LOADER
1033 static void RunMode()
1037 TInt r=fs.Connect();
1040 RDebug::Print(_L("Help\n"));
1044 TFileName sessionpath = _L("?:\\");
1046 TDriveList drivelist;
1047 fs.DriveList(drivelist);
1048 for (TInt driveno=EDriveC; driveno<=EDriveZ; driveno++)
1050 if (!drivelist[driveno])
1053 sessionpath[0]='A'+driveno;
1056 If a filename with the format EJECTDELAY.nnn is found, delay any reboot
1057 action by "nnn" seconds
1060 TFindFile finder(fs);
1061 r=finder.FindWildByPath(_L("EJECTDELAY.*"),&sessionpath,dir);
1063 { // Found one or more files
1068 parser.Set(entry.iName, NULL, NULL);
1069 TPtrC tok = parser.Ext();
1072 tok.Set(lex.NextToken());
1075 r=lex.Val(gRebootDelay);
1084 //////////////////////////////////////////////////////////////////////////////
1086 // Application entry point
1088 //////////////////////////////////////////////////////////////////////////////
1089 static void RunAppL()
1091 #ifdef USB_BOOT_LOADER
1095 TInt error = KErrUnknown;
1097 //RDebug::Print(_L("USBMSAPP: Creating console\n"));
1099 #ifdef USB_BOOT_LOADER
1100 console = Console::NewL(KVariantUsbmsTitle,TSize(KConsFullScreen,KConsFullScreen));
1102 console = Console::NewL(KTxtApp,TSize(KConsFullScreen,KConsFullScreen));
1105 CleanupStack::PushL(console);
1107 console->SetPos(0,2);
1108 console->Printf(_L("========================================"));
1110 CActiveScheduler* sched = new(ELeave) CActiveScheduler;
1111 CleanupStack::PushL(sched);
1112 CActiveScheduler::Install(sched);
1114 TBuf<20> KDriverFileName;
1115 // Load the logical device
1117 RDevUsbcScClient usbsc;
1121 CleanupClosePushL(fs);
1123 _LIT(KMountAllDefault,"(all)");
1124 console->SetPos(0,3);
1125 LogPrint(_L("Drives to auto-mount: %S"), (mountList.Length() ? &mountList : &KMountAllDefault));
1127 // Add MS file system
1128 error = fs.AddFileSystem(KMsFsy);
1130 if(error != KErrNone && error != KErrAlreadyExists)
1134 console->SetPos(0,4);
1135 LogPrint(_L("MSFS file system:\tAdded OK\n"));
1137 if (gSharedChunkLdd)
1139 KDriverFileName = _L("EUSBCSC.LDD");
1140 error = User::LoadLogicalDevice(KDriverFileName);
1144 KDriverFileName = _L("EUSBC.LDD");
1145 error = User::LoadLogicalDevice(KDriverFileName);
1148 if (error != KErrAlreadyExists)
1150 User::LeaveIfError(error);
1154 if (gSharedChunkLdd)
1156 error = usbsc.Open(0);
1160 error = usb.Open(0);
1163 User::LeaveIfError(error);
1165 #ifdef BUILD_OTG_USBMSAPP
1167 _LIT(KOtgdiLddFilename, "otgdi");
1168 // Check for OTG support
1169 TBuf8<KUsbDescSize_Otg> otg_desc;
1170 if (gSharedChunkLdd)
1172 error = usbsc.GetOtgDescriptor(otg_desc);
1176 error = usb.GetOtgDescriptor(otg_desc);
1179 if (!(error == KErrNotSupported || error == KErrNone))
1181 LogPrint(_L("Error %d while fetching OTG descriptor"), error);
1186 // On an OTG device we have to start the OTG driver, otherwise the Client
1187 // stack will remain disabled forever.
1188 if (error == KErrNotSupported)
1190 if (gSharedChunkLdd)
1192 CleanupClosePushL(usbsc);
1196 CleanupClosePushL(usb);
1202 error = User::LoadLogicalDevice(KOtgdiLddFilename);
1204 if (error != KErrNone)
1206 LogPrint(_L("Error %d on loading OTG LDD"), error);
1211 RUsbOtgDriver iOtgPort;
1213 error = iOtgPort.Open();
1215 if (error != KErrNone)
1217 LogPrint(_L("Error %d on opening OTG port"), error);
1221 error = iOtgPort.StartStacks();
1223 if (error != KErrNone)
1225 LogPrint(_L("Error %d on starting USB stack"), error);
1232 if (gSharedChunkLdd)
1234 CleanupClosePushL(usbsc);
1235 RChunk *tChunk = &gChunk;
1236 usbsc.FinalizeInterface(tChunk);
1240 CleanupClosePushL(usb);
1244 // RDebug::Print(_L("USBMSAPP: Create active objects\n"));
1245 CMessageKeyProcessor::NewLC(console);
1246 CPropertyWatch::NewLC(EUsbMsDriveState_KBytesRead, PropertyHandlers::Read);
1247 CPropertyWatch::NewLC(EUsbMsDriveState_KBytesWritten, PropertyHandlers::Written);
1248 CPropertyWatch::NewLC(EUsbMsDriveState_DriveStatus, PropertyHandlers::DriveStatus);
1249 CPropertyWatch::NewLC(EUsbMsDriveState_MediaError, PropertyHandlers::MediaError);
1250 if (gSharedChunkLdd)
1252 CUsbWatch::NewLC(&usbsc);
1256 CUsbWatch::NewLC(&usb);
1259 CPeriodUpdate::NewLC();
1261 RUsbMassStorage UsbMs;
1262 TBuf<8> t_vendorId(_L("vendor"));
1263 TBuf<16> t_productId(_L("product"));
1264 TBuf<4> t_productRev(_L("1.00"));
1266 TMassStorageConfig msConfig;
1267 msConfig.iVendorId.Copy(t_vendorId);
1268 msConfig.iProductId.Copy(t_productId);
1269 msConfig.iProductRev.Copy(t_productRev);
1271 // console->Printf(_L("Connect to Mass Storage"));
1272 error = UsbMs.Connect();
1273 User::LeaveIfError(error);
1275 // console->Printf(_L("Start Mass Storage"));
1276 error = UsbMs.Start(msConfig);
1277 User::LeaveIfError(error);
1279 TBuf8<KUsbDescSize_Device> deviceDescriptor;
1280 if (gSharedChunkLdd)
1282 error = usbsc.GetDeviceDescriptor(deviceDescriptor);
1286 error = usb.GetDeviceDescriptor(deviceDescriptor);
1289 User::LeaveIfError(error);
1291 const TInt KUsbSpecOffset = 2;
1292 const TInt KUsbDeviceClassOffset = 4;
1293 const TInt KUsbVendorIdOffset = 8;
1294 const TInt KUsbProductIdOffset = 10;
1295 const TInt KUsbDevReleaseOffset = 12;
1296 //Change the USB spec number to 2.00
1297 deviceDescriptor[KUsbSpecOffset] = 0x00;
1298 deviceDescriptor[KUsbSpecOffset+1] = 0x02;
1299 //Change the Device Class, Device SubClass and Device Protocol
1300 deviceDescriptor[KUsbDeviceClassOffset] = 0x00;
1301 deviceDescriptor[KUsbDeviceClassOffset+1] = 0x00;
1302 deviceDescriptor[KUsbDeviceClassOffset+2] = 0x00;
1303 //Change the device vendor ID (VID) to 0x0E22 (Symbian)
1304 deviceDescriptor[KUsbVendorIdOffset] = 0x22; // little endian
1305 deviceDescriptor[KUsbVendorIdOffset+1] = 0x0E;
1306 //Change the device product ID (PID) to 0x1111
1307 deviceDescriptor[KUsbProductIdOffset] = 0x12;
1308 deviceDescriptor[KUsbProductIdOffset+1] = 0x11;
1309 //Change the device release number to 3.05
1310 deviceDescriptor[KUsbDevReleaseOffset] = 0x05;
1311 deviceDescriptor[KUsbDevReleaseOffset+1] = 0x03;
1312 if (gSharedChunkLdd)
1314 error = usbsc.SetDeviceDescriptor(deviceDescriptor);
1318 error = usb.SetDeviceDescriptor(deviceDescriptor);
1321 User::LeaveIfError(error);
1323 // Remove possible Remote-Wakup support in Configuration descriptor,
1324 // so that we can use the MSC device also easily for Chapter9 testing.
1325 TBuf8<KUsbDescSize_Config> configDescriptor;
1326 if (gSharedChunkLdd)
1328 error = usbsc.GetConfigurationDescriptor(configDescriptor);
1332 error = usb.GetConfigurationDescriptor(configDescriptor);
1335 User::LeaveIfError(error);
1336 const TInt KConfDesc_AttribOffset = 7;
1337 configDescriptor[KConfDesc_AttribOffset] &= ~KUsbDevAttr_RemoteWakeup;
1338 if (gSharedChunkLdd)
1340 error = usbsc.SetConfigurationDescriptor(configDescriptor);
1344 error = usb.SetConfigurationDescriptor(configDescriptor);
1347 User::LeaveIfError(error);
1349 _LIT16(productID_L, "Symbian USB Mass Storage Device (Base)");
1350 TBuf16<KUsbStringDescStringMaxSize / 2> productID(productID_L);
1351 if (gSharedChunkLdd)
1353 error = usbsc.SetProductStringDescriptor(productID);
1357 error = usb.SetProductStringDescriptor(productID);
1360 User::LeaveIfError(error);
1362 TRequestStatus enum_status;
1363 console->SetPos(0,5);
1364 LogPrint(_L("Re-enumerating...\n"));
1366 #ifdef BUILD_OTG_USBMSAPP
1367 // For OTG: The USB stack may not yet in the peripheral role. If it is not,
1368 // then ReEnumerate() will not work here as the stack will ignore the call
1369 // since the stack is not active. Therefore we simulate device connection to
1370 // force the stack into peripheral role by calling DeviceConnectToHost().
1371 if (gSharedChunkLdd)
1373 usbsc.DeviceConnectToHost();
1374 usbsc.ReEnumerate(enum_status);
1379 usb.DeviceConnectToHost();
1380 usb.ReEnumerate(enum_status);
1383 if (gSharedChunkLdd)
1385 usbsc.ReEnumerate(enum_status);
1389 usb.ReEnumerate(enum_status);
1393 User::LeaveIfError(error);
1394 console->SetPos(0,5);
1395 User::WaitForRequest(enum_status);
1396 if(enum_status.Int() == KErrNone)
1397 LogPrint(_L("Re-enumeration Done\n"));
1399 LogPrint(_L("Re-enumeration not successfully done\n"));
1401 #ifndef USB_BOOT_LOADER
1402 console->SetPos(0,14);
1403 TBuf<3>password(KDefPwd);
1404 LogPrint(_L("Password: %S"), &password);
1406 ShowDriveSelection();
1408 console->SetPos(0,17);
1409 #ifdef USB_BOOT_LOADER
1410 _LIT(KMsgTitleB,"Menu:\n[Esc,Q]=RESET (boot image)\n");
1412 _LIT(KMsgTitleB,"Menu: q=quit d=chg drv\n m=mount u=unmount\n l=lock n=unlock\n c=clr pwd");
1415 //RDebug::Print(_L("USBMSAPP: Start CActiveScheduler\n"));
1417 console->Printf(KMsgTitleB);
1419 #ifdef USB_BOOT_LOADER
1420 // Mount the mass storage on variant specific drive
1421 MountMsFs(KVariantUsbmsRemoveableDrive);
1424 CActiveScheduler::Start();
1426 error = UsbMs.Stop();
1427 User::LeaveIfError(error);
1429 error = fs.RemoveFileSystem(KMsFs);
1430 User::LeaveIfError(error);
1432 //The console object is left on the Cleanup Stack,
1433 //which is used in the delay processing logic of rebootit().
1434 CleanupStack::PopAndDestroy(10);
1436 #ifdef BUILD_OTG_USBMSAPP
1437 iOtgPort.StopStacks();
1439 error = User::FreeLogicalDevice(RUsbOtgDriver::Name());
1440 User::LeaveIfError(error);
1443 // UnLoad the logical device
1444 TBuf<20> KDriverName;
1445 if (gSharedChunkLdd)
1447 KDriverName = _L("USBCSC");
1450 User::After(100000);
1451 error = User::FreeLogicalDevice(KDriverName);
1455 KDriverName = _L("USBC");
1456 error = User::FreeLogicalDevice(KDriverName);
1459 User::LeaveIfError(error);
1461 #ifdef USB_BOOT_LOADER
1464 CleanupStack::PopAndDestroy(1);
1467 TInt ParseCommandLine()
1470 User::CommandLine(args);
1475 TPtrC token=lex.NextToken();
1477 if(token.Length()!=0)
1479 if ((token.MatchF(_L("-sc")) == KErrNone))
1481 gSharedChunkLdd = ETrue;
1486 // Command line: list of drive letters to auto-mount (all if not specified)
1487 mountList.Append(token);
1488 mountList.UpperCase();
1500 GLDEF_C TInt E32Main()
1503 CTrapCleanup* cleanup=CTrapCleanup::New();
1505 if (ParseCommandLine())
1508 msfsMountedList.Reset();
1509 unmountedFsList.Reset();
1512 TRAPD(error,RunAppL());
1513 #ifdef USB_BOOT_LOADER
1514 __ASSERT_ALWAYS(!error, User::Panic(KVariantUsbmsTitle, error));
1516 __ASSERT_ALWAYS(!error, User::Panic(KTxtApp, error));
1527 //-----------------------------------------------------------------------------
1529 CFileSystemDescriptor::~CFileSystemDescriptor()
1532 iPrimaryExtName.Close();
1535 //-----------------------------------------------------------------------------
1536 CFileSystemDescriptor* CFileSystemDescriptor::NewL(const TDesC& aFsName, const TDesC& aPrimaryExtName, TBool aDrvSynch)
1538 CFileSystemDescriptor* pSelf = new (ELeave) CFileSystemDescriptor;
1540 CleanupStack::PushL(pSelf);
1542 pSelf->iFsName.CreateMaxL(aFsName.Length());
1543 pSelf->iFsName.Copy(aFsName);
1545 pSelf->iPrimaryExtName.CreateMaxL(aPrimaryExtName.Length());
1546 pSelf->iPrimaryExtName.Copy(aPrimaryExtName);
1548 pSelf->iDriveSynch = aDrvSynch;
1550 CleanupStack::Pop();