os/kernelhwsrv/kerneltest/f32test/shostmassstorage/testclient/usbtestclient/usbtestclient.cpp
Update contrib.
1 // Copyright (c) 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
24 #include "usbtestclient.h"
30 #include <usbmsshared.h>
35 #include <nkern/nk_trace.h>
38 #include "rusbmassstorage.h"
42 EUsbDeviceStateUndefined = EUsbcDeviceStateUndefined,
43 EUsbDeviceStateConfigured = EUsbcDeviceStateConfigured,
46 static CConsoleBase* console = NULL;
48 static TInt selectedDriveIndex = 0;
49 static TBuf<0x40> mountList;
51 static TFixedArray<TBool, KMaxDrives> msfsMountedList; ///< 'true' entry corresponds to the drive with mounted MSFS.FSY
52 static TFixedArray<CFileSystemDescriptor*, KMaxDrives> unmountedFsList; ///< every non-NULL entry corresponds to the unmounted original FS for the drive
54 _LIT(KMsFsy, "USBTESTMSCLIENT.FSY");
55 _LIT(KMsFs, "MassStorageFileSystem");
58 _LIT(KBytesTransferredFmt, "%c:%d/%d ");
59 _LIT(KErrFmt, "Error: %d\r");
61 _LIT(KTxtApp,"USB TEST CLIENT");
64 //-- if defined, some useful information will be printed out via RDebug interface
65 //#define LOGGING_ENABLED
67 //-----------------------------------------------------------------------------
69 prints a line to the console and copies it to the debug log if LOGGING_ENABLED
71 void LogPrint(TRefByValue<const TDesC> aFmt,...)
77 buf.FormatList(aFmt, list); //-- ignore overflows
82 #ifdef LOGGING_ENABLED
83 //-- print out the line via RDebug::Print
84 const TInt bufLen = buf.Length();
85 if(bufLen >0 && buf[bufLen-1] == '\n')
87 buf.Insert(bufLen-1, _L("\r"));
91 buf.Append(_L("\r\n"));
94 RDebug::RawPrint(buf);
98 //-----------------------------------------------------------------------------
100 prints a line to the debug log if LOGGING_ENABLED
102 void Log(TRefByValue<const TDesC> aFmt,...)
104 #ifdef LOGGING_ENABLED
107 VA_START(list, aFmt);
110 buf.FormatList(aFmt, list); //-- ignore overflows
112 //-- print out the line via RDebug::Print
113 const TInt bufLen = buf.Length();
114 if(bufLen >0 && buf[bufLen-1] == '\n')
116 buf.Insert(bufLen-1, _L("\r"));
119 RDebug::RawPrint(buf);
126 //-----------------------------------------------------------------------------
128 static void Clear(int row, int count=1)
131 for(TInt i=0; i<count; i++)
133 console->SetPos(0,row+i);
134 console->Printf(KBlank);
136 console->SetPos(0,row);
140 static void ShowDriveSelection()
142 console->SetPos(0,15);
143 if(PropertyHandlers::allDrivesStatus.Length()/2 > selectedDriveIndex)
145 LogPrint(_L("Selected Drive: %c"), 'A' + PropertyHandlers::allDrivesStatus[selectedDriveIndex*2]);
149 LogPrint(_L("Selected Drive: (none)"));
155 class CPeriodUpdate : public CActive
158 static CPeriodUpdate* NewLC();
170 CPeriodUpdate* CPeriodUpdate::NewLC()
172 CPeriodUpdate* me=new(ELeave) CPeriodUpdate();
173 CleanupStack::PushL(me);
178 CPeriodUpdate::CPeriodUpdate()
179 : CActive(0), iUpTime(0)
182 void CPeriodUpdate::ConstructL()
184 CActiveScheduler::Add(this);
185 iTimer.CreateLocal();
189 CPeriodUpdate::~CPeriodUpdate()
194 void CPeriodUpdate::DoCancel()
198 void CPeriodUpdate::RunL()
201 // Print RAM usage & up time
204 TUint totmins=(iUpTime/60);
205 TUint tothrs=(totmins/60);
207 if (HAL::Get(HALData::EMemoryRAMFree, mem)==KErrNone)
209 console->SetPos(0,22);
210 console->Printf(_L("mem (bytes) : %d\n"), mem);
211 console->Printf(_L("up time : %dh:%dm:%ds\n"),
212 tothrs, totmins%60, iUpTime%60);
214 iTimer.After(iStatus, 1000000);
217 //-----------------------------------------------------------------------------
219 Dismounts the originally mounted FS and optional primary extension from the drive and stores
220 this information in the FS descriptor
222 @return on success returns a pointer to the instantinated FS descriptor
224 static CFileSystemDescriptor* DoDismountOrginalFS(RFs& aFs, TInt aDrive)
228 TBuf<128> primaryExtName;
229 TBool bDrvSync = EFalse;
231 Log(_L("# DoDismountOrginalFS drv:%d\n"), aDrive);
233 //-- 1. get file system name
234 nRes = aFs.FileSystemName(fsName, aDrive);
236 {//-- probably no file system installed at all
240 //-- 2. find out if the drive sync/async
241 TPckgBuf<TBool> drvSyncBuf;
242 nRes = aFs.QueryVolumeInfoExt(aDrive, EIsDriveSync, drvSyncBuf);
245 bDrvSync = drvSyncBuf();
248 //-- 3. find out primary extension name if it is present; we will need to add it againt when mounting the FS
249 //-- other extensions (non-primary) are not supported yet
250 nRes = aFs.ExtensionName(primaryExtName, aDrive, 0);
253 primaryExtName.SetLength(0);
256 //-- 3.1 check if the drive has non-primary extensions, fail in this case, because this FS can't be mounted back normally
257 nRes = aFs.ExtensionName(primaryExtName, aDrive, 1);
260 LogPrint(_L("Non-primary extensions are not supported!\n"));
264 Log(_L("# DoDismountOrginalFS FS:%S, Prim ext:%S, synch:%d\n"), &fsName, &primaryExtName, bDrvSync);
266 //-- create FS descriptor and dismount the FS
267 CFileSystemDescriptor* pFsDesc = NULL;
269 TRAP(nRes, pFsDesc = CFileSystemDescriptor::NewL(fsName, primaryExtName, bDrvSync));
271 return NULL; //-- OOM ?
273 nRes = aFs.DismountFileSystem(fsName, aDrive);
278 Log(_L("# DoDismountOrginalFS Dismounting Err:%d\n"), nRes);
284 //-----------------------------------------------------------------------------
286 Tries to restore the original FS on the drive using the FS descriptor provided
287 @return standard error code.
289 static TInt DoRestoreFS(RFs& aFs, TInt aDrive, CFileSystemDescriptor* apFsDesc)
293 Log(_L("# DoRestoreFS drv:%d\n"), aDrive);
295 //-- 1. check that there is no FS installed
298 nRes = aFs.FileSystemName(fsName, aDrive);
300 {//-- probably no file system installed at all
301 Log(_L("# This drive already has FS intalled:%S \n"), &fsName);
302 return KErrAlreadyExists;
306 TPtrC ptrN (apFsDesc->FsName());
307 TPtrC ptrExt(apFsDesc->PrimaryExtName());
308 Log(_L("# Mounting FS:%S, Prim ext:%S, synch:%d\n"), &ptrN, &ptrExt, apFsDesc->DriveIsSynch());
310 if(ptrExt.Length() >0)
311 {//-- there is a primary extension to be mounted
312 nRes = aFs.AddExtension(ptrExt);
313 if(nRes != KErrNone && nRes != KErrAlreadyExists)
318 nRes = aFs.MountFileSystem(ptrN, ptrExt, aDrive, apFsDesc->DriveIsSynch());
322 nRes = aFs.MountFileSystem(ptrN, aDrive, apFsDesc->DriveIsSynch());
327 Log(_L("# Mount failed! code:%d\n"),nRes);
334 //-----------------------------------------------------------------------------
336 Dismount the original FS from the drive and mount MsFS instead
338 static void MountMsFs(TInt driveNumber)
340 TInt x = console->WhereX();
341 TInt y = console->WhereY();
343 //-- 1. try dismounting the original FS
344 CFileSystemDescriptor* fsDesc = DoDismountOrginalFS(fs, driveNumber);
345 unmountedFsList[driveNumber] = fsDesc;
347 console->SetPos(0, 10);
351 TPtrC ptrN(fsDesc->FsName());
352 LogPrint(_L("drv:%d FS:%S Dismounted OK"),driveNumber, &ptrN);
356 LogPrint(_L("drv:%d Dismount FS Failed!"),driveNumber);
359 console->ClearToEndOfLine();
361 //-- 2. try to mount the "MSFS"
363 error = fs.MountFileSystem(KMsFs, driveNumber);
364 console->SetPos(0, 11);
365 LogPrint(_L("MSFS Mount: %S (%d)"), (error?&KError:&KOk), error);
366 console->ClearToEndOfLine();
369 msfsMountedList[driveNumber] = ETrue;
371 // restore console position
372 console->SetPos(x,y);
375 //-----------------------------------------------------------------------------
377 Dismount MsFS and mount the original FS
379 static TInt RestoreMount(TInt driveNumber)
383 TInt x = console->WhereX();
384 TInt y = console->WhereY();
386 //-- 1. try dismounting the "MSFS"
387 if (msfsMountedList[driveNumber])
389 err = fs.DismountFileSystem(KMsFs, driveNumber);
390 console->SetPos(0, 11);
391 LogPrint(_L("MSFS Dismount:%S (%d)"), (err?&KError:&KOk), err);
392 console->ClearToEndOfLine();
396 msfsMountedList[driveNumber] = EFalse;
399 //-- 2. try to mount the original FS back
400 CFileSystemDescriptor* fsDesc = unmountedFsList[driveNumber];
403 err = DoRestoreFS(fs, driveNumber, fsDesc);
405 TPtrC ptrN(fsDesc->FsName());
406 console->SetPos(0, 10);
407 LogPrint(_L("%S Mount: %S (%d)"), &ptrN, (err?&KError:&KOk), err);
408 console->ClearToEndOfLine();
411 unmountedFsList[driveNumber] = NULL;
415 // restore console position
416 console->SetPos(x,y);
420 //////////////////////////////////////////////////////////////////////////////
423 // An active object that tracks changes to the KUsbMsDriveState properties
425 //////////////////////////////////////////////////////////////////////////////
427 CPropertyWatch* CPropertyWatch::NewLC(TUsbMsDriveState_Subkey aSubkey, PropertyHandlers::THandler aHandler)
429 CPropertyWatch* me=new(ELeave) CPropertyWatch(aHandler);
430 CleanupStack::PushL(me);
431 me->ConstructL(aSubkey);
435 CPropertyWatch::CPropertyWatch(PropertyHandlers::THandler aHandler)
436 : CActive(0), iHandler(aHandler)
439 void CPropertyWatch::ConstructL(TUsbMsDriveState_Subkey aSubkey)
441 User::LeaveIfError(iProperty.Attach(KUsbMsDriveState_Category, aSubkey));
442 CActiveScheduler::Add(this);
443 // initial subscription and process current property value
447 CPropertyWatch::~CPropertyWatch()
453 void CPropertyWatch::DoCancel()
458 void CPropertyWatch::RunL()
460 // resubscribe before processing new value to prevent missing updates
461 iProperty.Subscribe(iStatus);
467 //////////////////////////////////////////////////////////////////////////////
471 //////////////////////////////////////////////////////////////////////////////
473 CUsbWatch* CUsbWatch::NewLC(RUsb& aUsb)
475 CUsbWatch* me=new(ELeave) CUsbWatch(aUsb);
476 CleanupStack::PushL(me);
481 CUsbWatch::CUsbWatch(RUsb& aUsb)
485 iUsbDeviceState(EUsbDeviceStateUndefined),
486 iWasConfigured(EFalse)
489 void CUsbWatch::ConstructL()
491 CActiveScheduler::Add(this);
495 CUsbWatch::~CUsbWatch()
498 // iUsb.DeviceStateNotificationCancel();
499 iUsb.AlternateDeviceStatusNotifyCancel();
502 void CUsbWatch::DoCancel()
504 // iUsb.DeviceStateNotificationCancel();
505 iUsb.AlternateDeviceStatusNotifyCancel();
508 static TBool IsDriveConnected(TInt driveStatusIndex)
510 TInt driveStatus = PropertyHandlers::allDrivesStatus[2*driveStatusIndex+1];
511 return driveStatus >= EUsbMsDriveState_Connected ? ETrue : EFalse;
514 static TChar DriveNumberToLetter(TInt driveNumber)
516 TChar driveLetter = '?';
517 fs.DriveToChar(driveNumber, driveLetter);
521 static TBool IsDriveInMountList(TUint driveLetter)
523 TUint16 driveLetter16 = static_cast<TUint16>(driveLetter);
524 return(!mountList.Length() || KErrNotFound != mountList.Find(&driveLetter16, 1));
527 void CUsbWatch::RunL()
529 // RDebug::Print(_L(">> CUsbWatch[%d] %d"), iUsbDeviceState, iWasConfigured);
531 // const TUint stateMask = 0xFF;
532 // iUsb.DeviceStateNotification(stateMask, iUsbDeviceState, iStatus);
533 iUsb.AlternateDeviceStatusNotify(iStatus, iUsbDeviceState);
536 //RDebug::Print(_L("CUsbWatch DeviceStateNotification: iUsbDeviceState=%d"), iUsbDeviceState);
538 // If the cable is disconnected, unmount all the connected drives.
539 if(iWasConfigured && iUsbDeviceState == EUsbDeviceStateUndefined)
541 for(TInt i=0; i<PropertyHandlers::allDrivesStatus.Length()/2; i++)
543 if(IsDriveConnected(i))
545 //RDebug::Print(_L("CUsbWatch calling RestoreMount"));
546 RestoreMount(PropertyHandlers::allDrivesStatus[2*i]);
549 iWasConfigured = EFalse;
552 // If cable is connected, mount all drives in the auto-mount list. This is
553 // done for performance, since if this is not done here, mounting will
554 // happen later after each drive enters the Connecting state.
555 if (iUsbDeviceState == EUsbDeviceStateConfigured)
557 for (TInt i=0; i<PropertyHandlers::allDrivesStatus.Length()/2; i++)
559 TInt driveNumber = PropertyHandlers::allDrivesStatus[2*i];
560 if (!IsDriveConnected(i) && IsDriveInMountList(DriveNumberToLetter(driveNumber)))
562 //RDebug::Print(_L("CUsbWatch calling MountMsFs"));
563 MountMsFs(driveNumber);
566 iWasConfigured = ETrue;
570 //////////////////////////////////////////////////////////////////////////////
574 //////////////////////////////////////////////////////////////////////////////
576 TBuf8<16> PropertyHandlers::allDrivesStatus;
577 TUsbMsBytesTransferred PropertyHandlers::iKBytesRead;
578 TUsbMsBytesTransferred PropertyHandlers::iKBytesWritten;
579 TInt PropertyHandlers::iMediaError;
581 void PropertyHandlers::Read(RProperty& aProperty)
583 Transferred(aProperty, iKBytesRead);
586 void PropertyHandlers::Written(RProperty& aProperty)
588 Transferred(aProperty, iKBytesWritten);
591 void PropertyHandlers::Transferred(RProperty& aProperty, TUsbMsBytesTransferred& aReadOrWritten)
593 console->SetPos(0,1);
594 console->Printf(_L("KB R/W: "));
595 TInt err = aProperty.Get(aReadOrWritten);
598 for(TInt i = 0; i < allDrivesStatus.Length()/2; i++)
600 console->Printf(KBytesTransferredFmt,
601 (char)DriveNumberToLetter(allDrivesStatus[2*i]), iKBytesRead[i], iKBytesWritten[i]);
603 console->ClearToEndOfLine();
607 console->Printf(KErrFmt, err);
611 void PropertyHandlers::DriveStatus(RProperty& aProperty)
613 // RDebug::Print(_L(">> PropertyHandlers::DriveStatus"));
614 TInt err = aProperty.Get(allDrivesStatus);
615 console->SetPos(0,0);
618 console->Printf(_L("Status: "));
619 for(TInt i = 0; i < allDrivesStatus.Length()/2; i++)
621 TInt driveNumber = allDrivesStatus[2*i];
622 TInt driveStatus = allDrivesStatus[2*i+1];
623 TChar driveLetter = DriveNumberToLetter(driveNumber);
625 // RDebug::Print(_L("%c:%d "), (char)driveLetter, driveStatus);
629 case EUsbMsDriveState_Disconnected:
631 LogPrint(_L("%c:%d:Disconnected "), (char)driveLetter, driveStatus);
634 case EUsbMsDriveState_Connecting:
636 LogPrint(_L("%c:%d:Connecting "), (char)driveLetter, driveStatus);
639 case EUsbMsDriveState_Connected:
641 LogPrint(_L("%c:%d:Connected "), (char)driveLetter, driveStatus);
644 case EUsbMsDriveState_Disconnecting:
646 LogPrint(_L("%c:%d:Disconnecting"), (char)driveLetter, driveStatus);
649 case EUsbMsDriveState_Active:
651 LogPrint(_L("%c:%d:Active "), (char)driveLetter, driveStatus);
654 case EUsbMsDriveState_Locked:
656 LogPrint(_L("%c:%d:Locked "), (char)driveLetter, driveStatus);
659 case EUsbMsDriveState_MediaNotPresent:
661 LogPrint(_L("%c:%d:Not Present "), (char)driveLetter, driveStatus);
664 case EUsbMsDriveState_Removed:
666 LogPrint(_L("%c:%d:Removed "), (char)driveLetter, driveStatus);
669 case EUsbMsDriveState_Error:
671 LogPrint(_L("%c:%d:Error "), (char)driveLetter, driveStatus);
676 LogPrint(_L("%c:%d:Unknown "), (char)driveLetter, driveStatus);
681 if(IsDriveInMountList(driveLetter))
683 if (driveStatus == EUsbMsDriveState_Connecting)
685 MountMsFs(driveNumber);
687 else if (driveStatus == EUsbMsDriveState_Disconnected)
689 RestoreMount(driveNumber);
693 //RDebug::Print(_L("PropertyHandlers::DriveStatus: nothing to do"));
698 //RDebug::Print(_L("PropertyHandlers::DriveStatus: %c: is not in mountList\n"), driveLetter);
704 LogPrint(KErrFmt, err);
707 //RDebug::Print(_L("<< PropertyHandlers::DriveStatus"));
710 void PropertyHandlers::MediaError(RProperty& aProperty)
712 TInt err = aProperty.Get(iMediaError);
715 // RDebug::Printf("RProperty::Get returned %d", err);
719 //RDebug::Printf("PropertyHandlers::MediaError %x", iMediaError);
721 TInt x = console->WhereX();
722 TInt y = console->WhereY();
724 LogPrint(_L("Media Error %x"), iMediaError);
725 // restore console position
726 console->SetPos(x,y);
729 //////////////////////////////////////////////////////////////////////////////
731 // CMessageKeyProcessor
733 //////////////////////////////////////////////////////////////////////////////
734 CMessageKeyProcessor::CMessageKeyProcessor(CConsoleBase* aConsole)
735 : CActive(CActive::EPriorityUserInput), iConsole(aConsole)
739 CMessageKeyProcessor* CMessageKeyProcessor::NewLC(CConsoleBase* aConsole)
741 CMessageKeyProcessor* self=new (ELeave) CMessageKeyProcessor(aConsole);
742 CleanupStack::PushL(self);
747 CMessageKeyProcessor* CMessageKeyProcessor::NewL(CConsoleBase* aConsole)
749 CMessageKeyProcessor* self = NewLC(aConsole);
754 void CMessageKeyProcessor::ConstructL()
756 // Add to active scheduler
757 CActiveScheduler::Add(this);
761 void CMessageKeyProcessor::MakePassword(TMediaPassword &aPassword)
763 // Create password with same format as eshell and S60
764 TBuf<3> password(KDefPwd);
766 // fill aPassword with contents of password, not converting to ASCII
767 const TInt byteLen = password.Length() * 2;
768 aPassword.Copy(reinterpret_cast<const TUint8 *>(password.Ptr()), byteLen);
771 CMessageKeyProcessor::~CMessageKeyProcessor()
773 // Make sure we're cancelled
777 void CMessageKeyProcessor::DoCancel()
779 iConsole->ReadCancel();
782 void CMessageKeyProcessor::RunL()
784 // Handle completed request
785 ProcessKeyPress(TChar(iConsole->KeyCode()));
788 void CMessageKeyProcessor::RequestCharacter()
790 // A request is issued to the CConsoleBase to accept a
791 // character from the keyboard.
792 iConsole->Read(iStatus);
796 void CMessageKeyProcessor::ProcessKeyPress(TChar aChar)
799 TInt error = KErrNone;
808 for(TInt j=0; j<KMaxDrives; j++)
810 err = RestoreMount(j);
814 // Mount is busy/locked and can not be restored.
822 CActiveScheduler::Stop();
831 iTraceEnable = !iTraceEnable;
832 if (iTraceEnable) // 0x44008401
833 User::SetDebugMask(KHARDWARE|KDLL|KSCRATCH|KPOWER|KMEMTRACE);
835 User::SetDebugMask(0);
840 if(++selectedDriveIndex >= PropertyHandlers::allDrivesStatus.Length()/2)
842 selectedDriveIndex = 0;
844 ShowDriveSelection();
848 if(PropertyHandlers::allDrivesStatus.Length())
850 MountMsFs(PropertyHandlers::allDrivesStatus[selectedDriveIndex*2]);
855 if(PropertyHandlers::allDrivesStatus.Length())
857 RestoreMount(PropertyHandlers::allDrivesStatus[selectedDriveIndex*2]);
863 // lock unprotected drive
864 TMediaPassword password;
865 MakePassword(password);
870 error = fs.LockDrive(PropertyHandlers::allDrivesStatus[selectedDriveIndex*2],
871 nul, password, ETrue);
872 console->SetPos(0,9);
873 LogPrint(_L("LockDrive %S (%d)"), (error?&KError:&KOk), error);
879 // lock password protected drive
880 TMediaPassword password;
881 MakePassword(password);
882 error = fs.LockDrive(PropertyHandlers::allDrivesStatus[selectedDriveIndex*2],
883 password, password, ETrue);
884 console->SetPos(0,9);
885 LogPrint(_L("LockDrive %S (%d)"), (error?&KError:&KOk), error);
891 TMediaPassword password;
892 MakePassword(password);
893 error = fs.UnlockDrive(PropertyHandlers::allDrivesStatus[selectedDriveIndex*2],
896 LogPrint(_L("UnlockDrive %S (%d)"), (error?&KError:&KOk), error);
902 TMediaPassword password;
903 MakePassword(password);
904 error = fs.ClearPassword(PropertyHandlers::allDrivesStatus[selectedDriveIndex*2],
907 LogPrint(_L("ClearPassword %S (%d)"), (error?&KError:&KOk), error);
917 //////////////////////////////////////////////////////////////////////////////
919 // Application entry point
921 //////////////////////////////////////////////////////////////////////////////
922 static void RunAppL()
925 TInt error = KErrUnknown;
927 //RDebug::Print(_L("USBMSAPP: Creating console\n"));
928 console = Console::NewL(KTxtApp,TSize(KConsFullScreen,KConsFullScreen));
929 CleanupStack::PushL(console);
931 console->SetPos(0,2);
932 console->Printf(_L("========================================"));
934 // Command line: list of drive letters to auto-mount (all if not specified)
935 User::CommandLine(mountList);
936 mountList.UpperCase();
938 CActiveScheduler* sched = new(ELeave) CActiveScheduler;
939 CleanupStack::PushL(sched);
940 CActiveScheduler::Install(sched);
943 CleanupClosePushL(fs);
945 _LIT(KMountAllDefault,"(all)");
946 console->SetPos(0,3);
947 LogPrint(_L("Drives to auto-mount: %S"), (mountList.Length() ? &mountList : &KMountAllDefault));
949 // Add MS file system
950 error = fs.AddFileSystem(KMsFsy);
951 if(error != KErrNone && error != KErrAlreadyExists)
953 //RDebug::Print(_L("AddFileSystem failed, err=%d\n"), error);
956 console->SetPos(0,4);
957 LogPrint(_L("MSFS file system:\tAdded OK\n"));
961 // Load the logical device
962 _LIT(KDriverFileName,"EUSBC.LDD");
963 error = User::LoadLogicalDevice(KDriverFileName);
964 if (error != KErrAlreadyExists)
965 User::LeaveIfError(error);
968 User::LeaveIfError(error);
970 _LIT(KOtgdiLddFilename, "otgdi");
971 // Check for OTG support
972 TBuf8<KUsbDescSize_Otg> otg_desc;
973 error = usb.GetOtgDescriptor(otg_desc);
974 if (!(error == KErrNotSupported || error == KErrNone))
976 LogPrint(_L("Error %d while fetching OTG descriptor"), error);
981 // On an OTG device we have to start the OTG driver, otherwise the Client
982 // stack will remain disabled forever.
983 if (error == KErrNotSupported)
985 CleanupClosePushL(usb);
989 error = User::LoadLogicalDevice(KOtgdiLddFilename);
990 if (error != KErrNone)
992 LogPrint(_L("Error %d on loading OTG LDD"), error);
997 RUsbOtgDriver iOtgPort;
999 error = iOtgPort.Open();
1000 if (error != KErrNone)
1002 LogPrint(_L("Error %d on opening OTG port"), error);
1006 error = iOtgPort.StartStacks();
1007 if (error != KErrNone)
1009 LogPrint(_L("Error %d on starting USB stack"), error);
1014 CleanupClosePushL(usb);
1016 // RDebug::Print(_L("USBMSAPP: Create active objects\n"));
1017 CMessageKeyProcessor::NewLC(console);
1018 CPropertyWatch::NewLC(EUsbMsDriveState_KBytesRead, PropertyHandlers::Read);
1019 CPropertyWatch::NewLC(EUsbMsDriveState_KBytesWritten, PropertyHandlers::Written);
1020 CPropertyWatch::NewLC(EUsbMsDriveState_DriveStatus, PropertyHandlers::DriveStatus);
1021 CPropertyWatch::NewLC(EUsbMsDriveState_MediaError, PropertyHandlers::MediaError);
1022 CUsbWatch::NewLC(usb);
1023 CPeriodUpdate::NewLC();
1025 RUsbMassStorage UsbMs;
1026 TBuf<8> t_vendorId(_L("vendor"));
1027 TBuf<16> t_productId(_L("product"));
1028 TBuf<4> t_productRev(_L("1.00"));
1030 TMassStorageConfig msConfig;
1031 msConfig.iVendorId.Copy(t_vendorId);
1032 msConfig.iProductId.Copy(t_productId);
1033 msConfig.iProductRev.Copy(t_productRev);
1035 // console->Printf(_L("Connect to Mass Storage"));
1036 error = UsbMs.Connect();
1037 User::LeaveIfError(error);
1039 // console->Printf(_L("Start Mass Storage"));
1040 error = UsbMs.Start(msConfig);
1041 User::LeaveIfError(error);
1043 TBuf8<KUsbDescSize_Device> deviceDescriptor;
1044 error = usb.GetDeviceDescriptor(deviceDescriptor);
1045 User::LeaveIfError(error);
1047 const TInt KUsbSpecOffset = 2;
1048 const TInt KUsbDeviceClassOffset = 4;
1049 const TInt KUsbVendorIdOffset = 8;
1050 const TInt KUsbProductIdOffset = 10;
1051 const TInt KUsbDevReleaseOffset = 12;
1052 //Change the USB spec number to 2.00
1053 deviceDescriptor[KUsbSpecOffset] = 0x00;
1054 deviceDescriptor[KUsbSpecOffset+1] = 0x02;
1055 //Change the Device Class, Device SubClass and Device Protocol
1056 deviceDescriptor[KUsbDeviceClassOffset] = 0x00;
1057 deviceDescriptor[KUsbDeviceClassOffset+1] = 0x00;
1058 deviceDescriptor[KUsbDeviceClassOffset+2] = 0x00;
1059 //Change the device vendor ID (VID) to 0x0E22 (Symbian)
1060 deviceDescriptor[KUsbVendorIdOffset] = 0x22; // little endian
1061 deviceDescriptor[KUsbVendorIdOffset+1] = 0x0E;
1062 //Change the device product ID (PID) to 0x1111
1063 deviceDescriptor[KUsbProductIdOffset] = 0x12;
1064 deviceDescriptor[KUsbProductIdOffset+1] = 0x11;
1065 //Change the device release number to 3.05
1066 deviceDescriptor[KUsbDevReleaseOffset] = 0x05;
1067 deviceDescriptor[KUsbDevReleaseOffset+1] = 0x03;
1068 error = usb.SetDeviceDescriptor(deviceDescriptor);
1069 User::LeaveIfError(error);
1071 // Remove possible Remote-Wakup support in Configuration descriptor,
1072 // so that we can use the MSC device also easily for Chapter9 testing.
1073 TBuf8<KUsbDescSize_Config> configDescriptor;
1074 error = usb.GetConfigurationDescriptor(configDescriptor);
1075 User::LeaveIfError(error);
1076 const TInt KConfDesc_AttribOffset = 7;
1077 configDescriptor[KConfDesc_AttribOffset] &= ~KUsbDevAttr_RemoteWakeup;
1078 error = usb.SetConfigurationDescriptor(configDescriptor);
1079 User::LeaveIfError(error);
1081 _LIT16(productID_L, "Symbian USB Mass Storage Device (Base)");
1082 TBuf16<KUsbStringDescStringMaxSize / 2> productID(productID_L);
1083 error = usb.SetProductStringDescriptor(productID);
1084 User::LeaveIfError(error);
1086 TRequestStatus enum_status;
1087 console->SetPos(0,5);
1088 LogPrint(_L("Re-enumerating...\n"));
1089 usb.ReEnumerate(enum_status);
1090 User::LeaveIfError(error);
1091 console->SetPos(0,5);
1092 User::WaitForRequest(enum_status);
1093 if(enum_status.Int() == KErrNone)
1094 LogPrint(_L("Re-enumeration Done\n"));
1096 LogPrint(_L("Re-enumeration not successfully done\n"));
1099 console->SetPos(0,14);
1100 TBuf<3>password(KDefPwd);
1101 LogPrint(_L("Password: %S"), &password);
1103 ShowDriveSelection();
1105 console->SetPos(0,17);
1107 _LIT(KMsgTitleB,"Menu: q=quit d=chg drv\n m=mount u=unmount\n l=lock i=lock n=unlock\n c=clr pwd");
1110 //RDebug::Print(_L("USBMSAPP: Start CActiveScheduler\n"));
1112 console->Printf(KMsgTitleB);
1114 CActiveScheduler::Start();
1116 error = UsbMs.Stop();
1117 User::LeaveIfError(error);
1119 error = fs.RemoveFileSystem(KMsFs);
1120 User::LeaveIfError(error);
1122 CleanupStack::PopAndDestroy(11);
1124 iOtgPort.StopStacks();
1126 error = User::FreeLogicalDevice(RUsbOtgDriver::Name());
1127 User::LeaveIfError(error);
1129 error = User::FreeLogicalDevice(_L("USBC"));
1130 User::LeaveIfError(error);
1134 GLDEF_C TInt E32Main()
1137 CTrapCleanup* cleanup=CTrapCleanup::New();
1139 msfsMountedList.Reset();
1140 unmountedFsList.Reset();
1143 TRAPD(error,RunAppL());
1144 __ASSERT_ALWAYS(!error, User::Panic(KTxtApp, error));
1152 //-----------------------------------------------------------------------------
1154 CFileSystemDescriptor::~CFileSystemDescriptor()
1157 iPrimaryExtName.Close();
1160 //-----------------------------------------------------------------------------
1161 CFileSystemDescriptor* CFileSystemDescriptor::NewL(const TDesC& aFsName, const TDesC& aPrimaryExtName, TBool aDrvSynch)
1163 CFileSystemDescriptor* pSelf = new (ELeave) CFileSystemDescriptor;
1165 CleanupStack::PushL(pSelf);
1167 pSelf->iFsName.CreateMaxL(aFsName.Length());
1168 pSelf->iFsName.Copy(aFsName);
1170 pSelf->iPrimaryExtName.CreateMaxL(aPrimaryExtName.Length());
1171 pSelf->iPrimaryExtName.Copy(aPrimaryExtName);
1173 pSelf->iDriveSynch = aDrvSynch;
1175 CleanupStack::Pop();