os/kernelhwsrv/kerneltest/f32test/smassstorage/src/t_ms_mountstart.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// Component test of registration and deregistration
sl@0
    15
// 1. Test registering MS FS
sl@0
    16
// Test actions:
sl@0
    17
// a. Load MS Server/File system and start it. 
sl@0
    18
// b. Select a drive, say, Y, format it using FAT FS
sl@0
    19
// c. Read and store the boot sector of Y
sl@0
    20
// d. Unmount FAT FS from Y
sl@0
    21
// e. Mount MS FS on Y
sl@0
    22
// f. Read the boot sector of Y by passing SCSI command through TestLdd 
sl@0
    23
// g. Compare the two boot sectors, which are obtained under FAT MS and MS FS repectively
sl@0
    24
// h. Try to read Y (assuming it's a removable media) using RFs API.
sl@0
    25
// Expected results:
sl@0
    26
// This test should be run for different drives.
sl@0
    27
// Mounting non-removable media (step b) should fail.
sl@0
    28
// For removable media: steps from c to g should complete successfully
sl@0
    29
// Read boot sector should be the same as the saved. 
sl@0
    30
// Step h should fail (KErrNotSupported).
sl@0
    31
// 2. Test deregistering MS FS
sl@0
    32
// Test actions:
sl@0
    33
// a. Try to unmount MS FS from Y while SCSI is writing to it
sl@0
    34
// b. Wait for access completion.
sl@0
    35
// c. Unmount MS FS from Y. 	
sl@0
    36
// d. Try to read from Y using RFs API. 
sl@0
    37
// e. Remount FAT FS on Y.
sl@0
    38
// f. Issue UnitReady and Read SCSI command through test LDD. 
sl@0
    39
// g. Try to read from Y using RFs API.
sl@0
    40
// h. Unmount FAT FS from Y and mount MS FS on it
sl@0
    41
// Expected results:
sl@0
    42
// Deregister request (step a) should return an appropriate error code when media is in use. 
sl@0
    43
// Next deregistering (step c) should be successful. 
sl@0
    44
// Attempt (step d) should fail. 
sl@0
    45
// SCSI commands (step f) should report error when MS FS is unmounted. 
sl@0
    46
// File server read request (step g) should be successful when FAT FS is mounted  
sl@0
    47
// 
sl@0
    48
//
sl@0
    49
sl@0
    50
/**
sl@0
    51
 @file
sl@0
    52
 @internalTechnology
sl@0
    53
*/
sl@0
    54
sl@0
    55
#include <f32file.h>
sl@0
    56
#include <e32test.h>
sl@0
    57
#include <e32std.h>
sl@0
    58
#include <e32std_private.h>
sl@0
    59
#include <e32svr.h>
sl@0
    60
#include <hal.h>
sl@0
    61
#include <massstorage.h>
sl@0
    62
#include "t_ms_main.h"
sl@0
    63
#include "testusbc.h"
sl@0
    64
sl@0
    65
#define CBW_LENGTH          31
sl@0
    66
#define CSW_LENGTH          13
sl@0
    67
#define SCSI_READ_LEN       10
sl@0
    68
#define SCSI_WRITE_LEN      10
sl@0
    69
#define SCSI_UNIT_READY_LEN 6
sl@0
    70
#define SCSI_MED_RMVL_LEN   6
sl@0
    71
#define BOOTSECTOR_SIZE     512
sl@0
    72
sl@0
    73
_LIT(KMsFsyName, "MassStorageFileSystem");
sl@0
    74
sl@0
    75
const TUint KMBRFirstPartitionSectorOffset = 0x1BE + 8;
sl@0
    76
const TUint KBootRecordSignature = 0xAA55;
sl@0
    77
sl@0
    78
LOCAL_D TChar driveLetter[2];
sl@0
    79
LOCAL_D TInt nonRemovalDrvNo;
sl@0
    80
LOCAL_D TInt removalDrvNo;
sl@0
    81
LOCAL_D TUint8 testLun(0);                // Use MMC card for testing
sl@0
    82
sl@0
    83
#define LOG_AND_TEST(a, e) {if (a!=e) {test.Printf(_L("lvalue %d, rvalue%d\n\r"), a,e); test(EFalse);}}
sl@0
    84
LOCAL_C void ParseCommandArguments()
sl@0
    85
//
sl@0
    86
// Parses the command line arguments
sl@0
    87
// We expect 3 parameters:
sl@0
    88
//	- Drive letter for non-removable drive
sl@0
    89
//	- Drive letter for removable drive
sl@0
    90
//	- LUN for removable drive (0-7)
sl@0
    91
//
sl@0
    92
	{
sl@0
    93
	TBuf<0x100> cmd;
sl@0
    94
	User::CommandLine(cmd);
sl@0
    95
	TLex lex(cmd);
sl@0
    96
	TPtrC token;
sl@0
    97
	TBool cmdOk= ETrue;
sl@0
    98
	for (int i = 0; i < 3; i++)  //
sl@0
    99
		{
sl@0
   100
		token.Set(lex.NextToken());
sl@0
   101
		if (token.Length() != 0)
sl@0
   102
			{
sl@0
   103
			if (i <2)
sl@0
   104
				{
sl@0
   105
				driveLetter[i] = token[0];
sl@0
   106
				driveLetter[i].UpperCase();
sl@0
   107
				test.Printf(_L("CmdLine Param=%S\r\n"),&token);
sl@0
   108
				}
sl@0
   109
			else
sl@0
   110
				{
sl@0
   111
				TChar cLun = token[0];
sl@0
   112
				TInt lun = TInt(cLun) - 0x30;
sl@0
   113
				if (lun>=0 && lun <8)
sl@0
   114
					{
sl@0
   115
					testLun = TUint8(lun);
sl@0
   116
					}
sl@0
   117
				else
sl@0
   118
					{
sl@0
   119
					cmdOk= EFalse;
sl@0
   120
					}
sl@0
   121
				}
sl@0
   122
			}
sl@0
   123
		else 
sl@0
   124
			{
sl@0
   125
			cmdOk= EFalse;
sl@0
   126
			break;
sl@0
   127
			}
sl@0
   128
		}
sl@0
   129
		
sl@0
   130
sl@0
   131
		if (!cmdOk) 
sl@0
   132
			{
sl@0
   133
			test.Printf(_L("No or not enough command line arguments - using default arguments\r\n"));
sl@0
   134
			// code drive letters based on platform
sl@0
   135
			TInt uid;
sl@0
   136
			TInt r=HAL::Get(HAL::EMachineUid,uid);
sl@0
   137
			LOG_AND_TEST(r,KErrNone);
sl@0
   138
    	
sl@0
   139
			switch(uid)
sl@0
   140
	   			{
sl@0
   141
	   			case HAL::EMachineUid_Lubbock:
sl@0
   142
	   				driveLetter[0] = 'C';
sl@0
   143
	   				driveLetter[1] = 'F';
sl@0
   144
	   				test.Printf(_L("Test is running on Lubbock\r\n"));
sl@0
   145
					testLun = 2;
sl@0
   146
  					break;
sl@0
   147
	   			case HAL::EMachineUid_Win32Emulator:
sl@0
   148
	   				driveLetter[0] = 'Y';
sl@0
   149
	   				driveLetter[1] = 'X';
sl@0
   150
	   				test.Printf(_L("Test is running on Win32 Emulator\r\n"));
sl@0
   151
					testLun = 1;
sl@0
   152
	   				break;
sl@0
   153
	   			case HAL::EMachineUid_OmapH4:
sl@0
   154
	   				driveLetter[0] = 'C';
sl@0
   155
	   				driveLetter[1] = 'D';
sl@0
   156
	   				test.Printf(_L("Test is running on H4 board\r\n"));
sl@0
   157
					testLun = 0;
sl@0
   158
	   				break;
sl@0
   159
	   			default:
sl@0
   160
					// Assume it's a H2 board for now as no relevant Enum is found
sl@0
   161
	   				driveLetter[0] = 'C';
sl@0
   162
	   				driveLetter[1] = 'D';
sl@0
   163
	   				test.Printf(_L("Test is running on H2 board\r\n"));	
sl@0
   164
	   				testLun = 0;				
sl@0
   165
	   				break;
sl@0
   166
	   			}
sl@0
   167
	   			
sl@0
   168
				test.Printf(_L("Parameters used for test:\r\n\tfixed drive\t\t%c\r\n\tremovable drive\t\t%c\r\n\tLUN\t\t\t%d\r\n"), 
sl@0
   169
		        		    (TUint) driveLetter[0], (TUint) driveLetter[1], testLun);
sl@0
   170
			}	   		
sl@0
   171
	}
sl@0
   172
sl@0
   173
LOCAL_C void fillInt(TUint8* dest, TInt source)
sl@0
   174
    // 
sl@0
   175
    // Copy an int. Little endian
sl@0
   176
    //
sl@0
   177
    {
sl@0
   178
    for (TInt i = 0; i < 4; i++)
sl@0
   179
        {
sl@0
   180
        *dest++ = TUint8((source >> i*8) & 0xFF);
sl@0
   181
        }
sl@0
   182
    }
sl@0
   183
sl@0
   184
LOCAL_C TInt extractInt(const TUint8* aBuf)
sl@0
   185
    //
sl@0
   186
    // Extract an integer from a buffer. Assume little endian
sl@0
   187
    //
sl@0
   188
    {
sl@0
   189
    return aBuf[0] + (aBuf[1] << 8) + (aBuf[2] << 16) + (aBuf[3] << 24);
sl@0
   190
    }
sl@0
   191
sl@0
   192
LOCAL_C void createReadCmd(TDes8& aRead10Buf, TInt aLogicalBlkAddr, TInt aTotalBlocks)
sl@0
   193
    // 
sl@0
   194
    // Prepare SCSI read(10) command
sl@0
   195
    //
sl@0
   196
    {
sl@0
   197
    // Zero out the whole buffer
sl@0
   198
    aRead10Buf.FillZ(SCSI_READ_LEN);
sl@0
   199
    // operation code
sl@0
   200
    aRead10Buf[0] = 0x28;    
sl@0
   201
    // Fill in logical block address. Big endian
sl@0
   202
    aRead10Buf[2] = TUint8((aLogicalBlkAddr >> 24) & 0xFF);
sl@0
   203
    aRead10Buf[3] = TUint8((aLogicalBlkAddr >> 16) & 0xFF);
sl@0
   204
    aRead10Buf[4] = TUint8((aLogicalBlkAddr >> 8) & 0xFF);
sl@0
   205
    aRead10Buf[5] = TUint8(aLogicalBlkAddr & 0xFF);
sl@0
   206
    
sl@0
   207
    // Data transfer length (# of sectors). Big endian
sl@0
   208
    aRead10Buf[7] = TUint8((aTotalBlocks >> 8) & 0xFF);
sl@0
   209
    aRead10Buf[8] = TUint8((aTotalBlocks & 0xFF));
sl@0
   210
    }
sl@0
   211
sl@0
   212
LOCAL_C void createCBW(TDes8& aCbw, TInt aDCBWTag, TInt aDataTransferLen, TUint8 aInOutFlag, TUint8 aCBLength, TDes8& aCBWCB)
sl@0
   213
    // 
sl@0
   214
    // aCbw:            stores CBW
sl@0
   215
    // aDCBWTag:        a command block tag sent by the host. Used to associates a CSW
sl@0
   216
    //                  with corresponding CBW
sl@0
   217
    // aDataTranferLen: the number of bytes the host expects to transfer
sl@0
   218
    // aInOutFlag:      value for bmCBWFlags field, indicating the direction of transfer
sl@0
   219
    // aCBLengh:        valid length of CBWCB field in bytes
sl@0
   220
    // aCBWCB			the actual command to be wrapped
sl@0
   221
    {
sl@0
   222
    // Zero out aCbw
sl@0
   223
    aCbw.FillZ(CBW_LENGTH);
sl@0
   224
sl@0
   225
    // dCBWSignature field, the value comes from spec
sl@0
   226
    TInt dCBWSignature = 0x43425355;
sl@0
   227
    fillInt(&aCbw[0], dCBWSignature);
sl@0
   228
    // dCBWTag field
sl@0
   229
    fillInt(&aCbw[4], aDCBWTag);
sl@0
   230
    // dCBWDataTransferLength field
sl@0
   231
    fillInt(&aCbw[8], aDataTransferLen);
sl@0
   232
    // bmCBWFlags field
sl@0
   233
    aCbw[12] = aInOutFlag;
sl@0
   234
	aCbw[13] = testLun;
sl@0
   235
    // bCBWCBLength field
sl@0
   236
    aCbw[14] = aCBLength;          
sl@0
   237
sl@0
   238
    // CBWCB field
sl@0
   239
    for (TInt i = 0; i < aCBLength; ++i)
sl@0
   240
    	{
sl@0
   241
    	aCbw[15 + i] = aCBWCB[i];
sl@0
   242
    	}
sl@0
   243
    }
sl@0
   244
sl@0
   245
LOCAL_C void doComponentTest()
sl@0
   246
    //
sl@0
   247
    // Do the component test
sl@0
   248
    //
sl@0
   249
	{
sl@0
   250
	__UHEAP_MARK;	
sl@0
   251
sl@0
   252
    TInt ret;
sl@0
   253
    test.Next(_L("Start MountStart test. Be sure MMC card is inserted."));
sl@0
   254
sl@0
   255
    // Connect to the server
sl@0
   256
    RFs fs;
sl@0
   257
    LOG_AND_TEST(KErrNone,  fs.Connect());
sl@0
   258
    
sl@0
   259
    // Convert drive letters to their numerical equivalent
sl@0
   260
	ret = fs.CharToDrive(driveLetter[0],nonRemovalDrvNo);
sl@0
   261
	LOG_AND_TEST(ret, KErrNone);
sl@0
   262
	ret = fs.CharToDrive(driveLetter[1],removalDrvNo);
sl@0
   263
	LOG_AND_TEST(ret,  KErrNone);	
sl@0
   264
sl@0
   265
sl@0
   266
	// Load the logical device
sl@0
   267
	_LIT(KDriverFileName,"TESTUSBC.LDD");
sl@0
   268
	ret = User::LoadLogicalDevice(KDriverFileName);
sl@0
   269
	test(ret == KErrNone || ret == KErrAlreadyExists);
sl@0
   270
sl@0
   271
    // Add MS file system
sl@0
   272
	_LIT(KMsFs, "MSFS.FSY");
sl@0
   273
	ret = fs.AddFileSystem(KMsFs);
sl@0
   274
	test(ret == KErrNone || ret == KErrAlreadyExists);
sl@0
   275
	
sl@0
   276
	// DEF080979: RFs::AddFileSystem, wrong error code when re-adding 
sl@0
   277
	// the mass storage file system. Confirm that RFs::AddFileSystem 
sl@0
   278
	// returns the correct error code if the file system already exists. 
sl@0
   279
	// Also confirm that the mass storage file system is usable after such
sl@0
   280
	// a failed attempt to re-add the file system.
sl@0
   281
	ret = fs.AddFileSystem(KMsFs);
sl@0
   282
	test(ret == KErrAlreadyExists);
sl@0
   283
sl@0
   284
    // Start Ms file system
sl@0
   285
    RUsbMassStorage usbMs;
sl@0
   286
sl@0
   287
    TMassStorageConfig config;
sl@0
   288
    
sl@0
   289
    config.iVendorId.Copy(_L("vendorId"));
sl@0
   290
    config.iProductId.Copy(_L("productId"));
sl@0
   291
    config.iProductRev.Copy(_L("rev"));
sl@0
   292
sl@0
   293
sl@0
   294
	ret = usbMs.Connect();
sl@0
   295
    LOG_AND_TEST(KErrNone, ret);
sl@0
   296
  
sl@0
   297
    // Start usb mass storage device
sl@0
   298
    LOG_AND_TEST(KErrNone , usbMs.Start(config));
sl@0
   299
sl@0
   300
	TBuf<128> fsName;
sl@0
   301
		
sl@0
   302
#if defined(__WINS__)  //we have no "free" non-removable drive at hardware to run this,
sl@0
   303
			  
sl@0
   304
    // Get the file system name on non-removable drive
sl@0
   305
sl@0
   306
	LOG_AND_TEST(KErrNone ,fs.FileSystemName(fsName, nonRemovalDrvNo));
sl@0
   307
sl@0
   308
    // Mount MS FS on to non-removable drive. This should fail
sl@0
   309
    test(KErrNone != fs.MountFileSystem(KMsFsyName, nonRemovalDrvNo));
sl@0
   310
sl@0
   311
    // Unmount MS FS from non-removable drive
sl@0
   312
	LOG_AND_TEST(KErrNone, fs.DismountFileSystem(KMsFsyName, nonRemovalDrvNo));
sl@0
   313
sl@0
   314
    // Mount FAT FS on to drive (restoring)
sl@0
   315
    LOG_AND_TEST(KErrNone,  fs.MountFileSystem(fsName, nonRemovalDrvNo));
sl@0
   316
#endif //WINS
sl@0
   317
sl@0
   318
    // Format removable drive using FAT FS
sl@0
   319
    RFormat format;
sl@0
   320
    
sl@0
   321
    TBuf<2> removalDrive;
sl@0
   322
    removalDrive.Append(driveLetter[1]);
sl@0
   323
    removalDrive.Append(':');
sl@0
   324
    TInt tracksRemaining;
sl@0
   325
    test.Next(_L("Start MMC card formatting"));
sl@0
   326
    LOG_AND_TEST(KErrNone, format.Open(fs, removalDrive, EHighDensity || EQuickFormat, tracksRemaining));
sl@0
   327
    while (tracksRemaining)
sl@0
   328
        {
sl@0
   329
        test.Printf(_L("."));
sl@0
   330
        LOG_AND_TEST(KErrNone,  format.Next(tracksRemaining));
sl@0
   331
        }
sl@0
   332
    format.Close();
sl@0
   333
  	test.Printf(_L("\nDone!\n"));
sl@0
   334
    // Get the boot sector info using FAT FS and save it for later comparison
sl@0
   335
    TBuf8<512> fatBootSector;
sl@0
   336
    RRawDisk fatDiskF;
sl@0
   337
    LOG_AND_TEST(KErrNone, fatDiskF.Open(fs, removalDrvNo));
sl@0
   338
    LOG_AND_TEST(KErrNone, fatDiskF.Read(0, fatBootSector));
sl@0
   339
	fatDiskF.Close();    
sl@0
   340
sl@0
   341
	LOG_AND_TEST(KErrNone, fs.FileSystemName(fsName, removalDrvNo)); 
sl@0
   342
sl@0
   343
	// Set up sessions for dismount API tests
sl@0
   344
sl@0
   345
	const TInt KNumClients = 10;
sl@0
   346
    RFs clientFs[KNumClients];
sl@0
   347
    RFs dismountFs1;
sl@0
   348
	TRequestStatus trsClientNotify[KNumClients];
sl@0
   349
	TRequestStatus trsClientComplete;
sl@0
   350
	TRequestStatus trsClientComplete1;
sl@0
   351
sl@0
   352
	LOG_AND_TEST(KErrNone, dismountFs1.Connect());
sl@0
   353
sl@0
   354
	TInt i = 0;
sl@0
   355
	for(i=0; i< KNumClients; i++)
sl@0
   356
		{
sl@0
   357
		LOG_AND_TEST(KErrNone, clientFs[i].Connect());
sl@0
   358
		}
sl@0
   359
sl@0
   360
	// Test invalid mode argument to RFs::NotifyDismount
sl@0
   361
sl@0
   362
    test.Next(_L("Test invalid mode argument to RFs::NotifyDismount"));
sl@0
   363
	for(i=0; i< KNumClients; i++)
sl@0
   364
		{
sl@0
   365
   		clientFs[i].NotifyDismount(removalDrvNo, trsClientNotify[i], (TNotifyDismountMode)0xFEEDFACE);
sl@0
   366
		test(trsClientNotify[i] == KErrArgument);
sl@0
   367
		}
sl@0
   368
sl@0
   369
	// Register for notification of pending media removal and check status
sl@0
   370
sl@0
   371
    test.Next(_L("Register for notification of pending media removal and check status"));
sl@0
   372
	for(i=0; i< KNumClients; i++)
sl@0
   373
		{
sl@0
   374
   		clientFs[i].NotifyDismount(removalDrvNo, trsClientNotify[i]);
sl@0
   375
		test(trsClientNotify[i] == KRequestPending);
sl@0
   376
		}
sl@0
   377
sl@0
   378
	// Notify clients of pending media removal and check status
sl@0
   379
sl@0
   380
    test.Next(_L("Notify clients of pending media removal and check status"));
sl@0
   381
   	fs.NotifyDismount(removalDrvNo, trsClientComplete, EFsDismountNotifyClients);
sl@0
   382
	test(trsClientComplete == KRequestPending);
sl@0
   383
sl@0
   384
	// Check that client has notification of pending media removal
sl@0
   385
sl@0
   386
    test.Next(_L("Check that client has notification of pending media removal"));
sl@0
   387
	for(i=0; i< KNumClients; i++)
sl@0
   388
		{
sl@0
   389
		test(trsClientNotify[i] == KErrNone);
sl@0
   390
		}
sl@0
   391
sl@0
   392
	// Respond to the dismount using RFs::AllowDismount (only 2 clients)
sl@0
   393
sl@0
   394
	LOG_AND_TEST(KErrNone, clientFs[0].AllowDismount(removalDrvNo));
sl@0
   395
	test(trsClientComplete == KRequestPending);
sl@0
   396
	LOG_AND_TEST(KErrNone, clientFs[1].AllowDismount(removalDrvNo));
sl@0
   397
	test(trsClientComplete == KRequestPending);
sl@0
   398
sl@0
   399
	// Check that file system can't be dismounted as all clients haven't responded
sl@0
   400
sl@0
   401
	test.Next(_L("Check that file system can't be dismounted as all clients haven't responded"));
sl@0
   402
	LOG_AND_TEST(KErrInUse, fs.DismountFileSystem(fsName, removalDrvNo));
sl@0
   403
sl@0
   404
	// Before all clients have completed, cancel the dismount
sl@0
   405
sl@0
   406
	test.Next(_L("Before all clients have completed, cancel the dismount"));
sl@0
   407
	fs.NotifyDismountCancel(trsClientComplete);
sl@0
   408
	test(trsClientComplete == KErrCancel);
sl@0
   409
sl@0
   410
	for(i=2; i< KNumClients; i++)
sl@0
   411
		{
sl@0
   412
		LOG_AND_TEST(KErrNone,     clientFs[i].AllowDismount(removalDrvNo));
sl@0
   413
		LOG_AND_TEST(KErrNotFound, clientFs[i].AllowDismount(removalDrvNo));
sl@0
   414
		test(trsClientComplete == KErrCancel);
sl@0
   415
		}
sl@0
   416
sl@0
   417
	// Check that file system can be dismounted after cancelling async dismount
sl@0
   418
sl@0
   419
	test.Next(_L("Check that file system can be dismounted after cancelling async dismount"));
sl@0
   420
	LOG_AND_TEST(KErrNone, fs.DismountFileSystem(fsName, removalDrvNo));
sl@0
   421
sl@0
   422
	// ...remount FAT
sl@0
   423
sl@0
   424
	test.Next(_L("Mount FAT FS on to the removal drive"));
sl@0
   425
	LOG_AND_TEST(KErrNone, fs.MountFileSystem(fsName, removalDrvNo));
sl@0
   426
sl@0
   427
	for(i=0; i< KNumClients; i++)
sl@0
   428
	    clientFs[i].Close();
sl@0
   429
sl@0
   430
    dismountFs1.Close();
sl@0
   431
sl@0
   432
	//
sl@0
   433
	// Test dismounting while resourses are open
sl@0
   434
	//
sl@0
   435
	
sl@0
   436
	_LIT(KFileName, ":\\foo");
sl@0
   437
	TBuf<7> fileName;
sl@0
   438
	fileName.Append(driveLetter[1]);
sl@0
   439
	fileName.Append(KFileName);
sl@0
   440
sl@0
   441
	RFile file;
sl@0
   442
	test.Next(_L("Attempting to open a file\n\r"));
sl@0
   443
	ret = file.Create(fs, fileName, EFileRead | EFileReadDirectIO | EFileWriteDirectIO);
sl@0
   444
	test(ret == KErrNone || ret == KErrAlreadyExists);
sl@0
   445
	LOG_AND_TEST(KErrNone, file.Write(0,_L8("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")));
sl@0
   446
	file.Close();
sl@0
   447
sl@0
   448
	TBuf<7> dirName;
sl@0
   449
	dirName.Append(driveLetter[1]);
sl@0
   450
	dirName.Append(KFileName);
sl@0
   451
sl@0
   452
	RDir dir;
sl@0
   453
	TEntry dirEntry;
sl@0
   454
	test.Next(_L("Attempting to open a directory\n\r"));
sl@0
   455
    LOG_AND_TEST(KErrNone, dir.Open(fs, dirName, KEntryAttNormal));
sl@0
   456
    LOG_AND_TEST(KErrNone, dir.Read(dirEntry));
sl@0
   457
	dir.Close();
sl@0
   458
sl@0
   459
	fs.Close();
sl@0
   460
sl@0
   461
	TInt pass;
sl@0
   462
	for(pass=0; pass<5; pass++)
sl@0
   463
	{
sl@0
   464
		LOG_AND_TEST(KErrNone, fs.Connect());
sl@0
   465
		LOG_AND_TEST(KErrNone, dismountFs1.Connect());
sl@0
   466
sl@0
   467
		TInt i = 0;
sl@0
   468
		for(i=0; i< KNumClients; i++)
sl@0
   469
			{
sl@0
   470
			LOG_AND_TEST(KErrNone, clientFs[i].Connect());
sl@0
   471
			}
sl@0
   472
sl@0
   473
		// Open a file on the removable drive
sl@0
   474
		
sl@0
   475
		RFile file;
sl@0
   476
		LOG_AND_TEST(KErrNone, file.Open(fs, fileName, EFileRead | EFileReadDirectIO | EFileWriteDirectIO));
sl@0
   477
		TBuf8<0x40> buf1;
sl@0
   478
		LOG_AND_TEST(KErrNone, file.Read(0, buf1));
sl@0
   479
		LOG_AND_TEST(36, buf1.Length());
sl@0
   480
		test(buf1 == _L8("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"));
sl@0
   481
sl@0
   482
		// Unmount FAT FS from the removable drive - this should fail with a file open
sl@0
   483
		
sl@0
   484
		LOG_AND_TEST(KErrInUse, fs.DismountFileSystem(fsName, removalDrvNo));
sl@0
   485
sl@0
   486
		// Open a directory  on the removable drive
sl@0
   487
sl@0
   488
		test.Next(_L("Attempting to open a directory\n\r"));
sl@0
   489
		LOG_AND_TEST(KErrNone, dir.Open(fs, dirName, KEntryAttNormal));
sl@0
   490
		LOG_AND_TEST(KErrNone, dir.Read(dirEntry));
sl@0
   491
sl@0
   492
		// Check simple client dismount notification and cancel (before issuing a dismount request)
sl@0
   493
sl@0
   494
		test.Next(_L("Register for notification of pending media removal and check status"));
sl@0
   495
		for(i=0; i< KNumClients; i++)
sl@0
   496
			{
sl@0
   497
   			clientFs[i].NotifyDismount(removalDrvNo, trsClientNotify[i]);
sl@0
   498
			test(trsClientNotify[i] == KRequestPending);
sl@0
   499
			}
sl@0
   500
sl@0
   501
		test.Next(_L("Cancel notification of pending media removal and check status"));
sl@0
   502
		for(i=0; i< KNumClients; i++)
sl@0
   503
			{
sl@0
   504
	   		clientFs[i].NotifyDismountCancel(trsClientNotify[i]);
sl@0
   505
			test(trsClientNotify[i] == KErrCancel);
sl@0
   506
			}
sl@0
   507
sl@0
   508
		// Check issuing and cancelling a dismount request while clients are responding
sl@0
   509
sl@0
   510
		test.Next(_L("Register for notification of pending media removal (again) and check status"));
sl@0
   511
		for(i=0; i< KNumClients; i++)
sl@0
   512
			{
sl@0
   513
   			clientFs[i].NotifyDismount(removalDrvNo, trsClientNotify[i]);
sl@0
   514
			test(trsClientNotify[i] == KRequestPending);
sl@0
   515
			}
sl@0
   516
sl@0
   517
		test.Next(_L("Notify clients of pending media removal and check status"));
sl@0
   518
   		fs.NotifyDismount(removalDrvNo, trsClientComplete, EFsDismountNotifyClients);
sl@0
   519
		test(trsClientComplete == KRequestPending);
sl@0
   520
sl@0
   521
		test.Next(_L("Check that client has notification of pending media removal"));
sl@0
   522
		for(i=0; i< KNumClients; i++)
sl@0
   523
			{
sl@0
   524
			test(trsClientNotify[i] == KErrNone);
sl@0
   525
			}
sl@0
   526
sl@0
   527
		LOG_AND_TEST(KErrNone, clientFs[0].AllowDismount(removalDrvNo));
sl@0
   528
		test(trsClientComplete == KRequestPending);
sl@0
   529
		LOG_AND_TEST(KErrNone, clientFs[1].AllowDismount(removalDrvNo));
sl@0
   530
		test(trsClientComplete == KRequestPending);
sl@0
   531
		test.Next(_L("Before all clients have completed, cancel the dismount"));
sl@0
   532
		fs.NotifyDismountCancel(trsClientComplete);
sl@0
   533
		test(trsClientComplete == KErrCancel);
sl@0
   534
		
sl@0
   535
		for(i=2; i< KNumClients; i++)
sl@0
   536
			{
sl@0
   537
			LOG_AND_TEST(KErrNone, clientFs[i].AllowDismount(removalDrvNo));
sl@0
   538
			test(trsClientComplete == KErrCancel);
sl@0
   539
			}
sl@0
   540
sl@0
   541
		// Check dismounting, responding, cancelling and forced remounting
sl@0
   542
sl@0
   543
		test.Next(_L("Register for notification of pending media removal (again) and check status"));
sl@0
   544
		for(i=0; i< KNumClients; i++)
sl@0
   545
			{
sl@0
   546
   			clientFs[i].NotifyDismount(removalDrvNo, trsClientNotify[i]);
sl@0
   547
			test(trsClientNotify[i] == KRequestPending);
sl@0
   548
			}
sl@0
   549
sl@0
   550
		test.Next(_L("Notify clients of pending media removal and check status"));
sl@0
   551
   		fs.NotifyDismount(removalDrvNo, trsClientComplete, EFsDismountNotifyClients);
sl@0
   552
		test(trsClientComplete == KRequestPending);
sl@0
   553
sl@0
   554
		test.Next(_L("Check that client has notification of pending media removal"));
sl@0
   555
		for(i=0; i< KNumClients; i++)
sl@0
   556
			{
sl@0
   557
			test(trsClientNotify[i] == KErrNone);
sl@0
   558
			}
sl@0
   559
sl@0
   560
		test.Next(_L("Notify clients of pending media removal with another session and check status"));
sl@0
   561
   		fs.NotifyDismount(removalDrvNo, trsClientComplete1, EFsDismountNotifyClients);
sl@0
   562
		test(trsClientComplete1 == KErrInUse);
sl@0
   563
sl@0
   564
		TInt expectedAllowDismountRet = KErrNone;
sl@0
   565
		TInt expectedCompletionCode = KRequestPending;
sl@0
   566
		if(pass & 0x01)
sl@0
   567
			{
sl@0
   568
			test.Next(_L("No response from clients - Force a dismount"));
sl@0
   569
			test.Next(_L("...cancelling original request"));
sl@0
   570
	   		fs.NotifyDismountCancel(trsClientComplete);
sl@0
   571
			test(trsClientComplete == KErrCancel);
sl@0
   572
			test.Next(_L("...issuing a forced dismount request"));
sl@0
   573
	   		fs.NotifyDismount(removalDrvNo, trsClientComplete, EFsDismountForceDismount);
sl@0
   574
			test(trsClientComplete == KErrNone);
sl@0
   575
			expectedAllowDismountRet = KErrNotReady;
sl@0
   576
			expectedCompletionCode = KErrNone;
sl@0
   577
			}
sl@0
   578
sl@0
   579
		test.Next(_L("Allow dismount and check response"));
sl@0
   580
		for(i=0; i < KNumClients; i++)
sl@0
   581
			{
sl@0
   582
			LOG_AND_TEST(expectedAllowDismountRet, clientFs[i].AllowDismount(removalDrvNo));
sl@0
   583
			if(i == KNumClients-1)
sl@0
   584
				test(trsClientComplete == KErrNone);
sl@0
   585
			else
sl@0
   586
				test(trsClientComplete == expectedCompletionCode);
sl@0
   587
			}
sl@0
   588
sl@0
   589
		// The last test should have dismounted the file system
sl@0
   590
sl@0
   591
		LOG_AND_TEST(KErrNotReady, file.Read(0,buf1));
sl@0
   592
		LOG_AND_TEST(KErrNotReady, dir.Read(dirEntry));
sl@0
   593
sl@0
   594
		test.Next(_L("FAT File System should now be dismounted from the drive"));
sl@0
   595
		LOG_AND_TEST(KErrNotReady, fs.DismountFileSystem(fsName, removalDrvNo));
sl@0
   596
sl@0
   597
		test.Next(_L("Mount MS FS on to the removable drive"));
sl@0
   598
		LOG_AND_TEST(KErrNone, fs.MountFileSystem(KMsFsyName, removalDrvNo));
sl@0
   599
sl@0
   600
		LOG_AND_TEST(KErrDisMounted, file.Read(0,buf1));
sl@0
   601
		LOG_AND_TEST(KErrDisMounted, dir.Read(dirEntry));
sl@0
   602
sl@0
   603
		test.Next(_L("Dismount MSFS normally"));
sl@0
   604
		LOG_AND_TEST(KErrNone, fs.DismountFileSystem(KMsFsyName, removalDrvNo));
sl@0
   605
sl@0
   606
		test.Next(_L("Mount FAT FS on to the removal drive"));
sl@0
   607
		LOG_AND_TEST(KErrNone, fs.MountFileSystem(fsName, removalDrvNo));
sl@0
   608
sl@0
   609
		LOG_AND_TEST(KErrNone, file.Read(0,buf1));
sl@0
   610
		LOG_AND_TEST(KErrEof, dir.Read(dirEntry));	// drive freshly formatted, so only root dir exists
sl@0
   611
sl@0
   612
		// Test multiple notifiers on a single session
sl@0
   613
sl@0
   614
		test.Next(_L("Register several notifiers for a single session and check status"));
sl@0
   615
		for(i=0; i< KNumClients; i++)
sl@0
   616
			{
sl@0
   617
   			clientFs[0].NotifyDismount(removalDrvNo, trsClientNotify[i]);
sl@0
   618
			test(trsClientNotify[i] == KRequestPending);
sl@0
   619
			}
sl@0
   620
sl@0
   621
		test.Next(_L("Notify clients and verify all requests signalled"));
sl@0
   622
   		fs.NotifyDismount(removalDrvNo, trsClientComplete, EFsDismountNotifyClients);
sl@0
   623
sl@0
   624
		test.Next(_L("Allow dismount 3 times from same session"));
sl@0
   625
		for(i=0; i< KNumClients; i++)
sl@0
   626
			{
sl@0
   627
			test(trsClientComplete == KRequestPending);
sl@0
   628
			test(trsClientNotify[i] == KErrNone);
sl@0
   629
			LOG_AND_TEST(KErrNone, clientFs[0].AllowDismount(removalDrvNo));
sl@0
   630
			}
sl@0
   631
sl@0
   632
		test.Next(_L("Verify that file system has been dismounted"));
sl@0
   633
		test(trsClientComplete == KErrNone);
sl@0
   634
sl@0
   635
		test.Next(_L("Mount FAT FS on to the removal drive"));
sl@0
   636
		LOG_AND_TEST(KErrNone, fs.MountFileSystem(fsName, removalDrvNo));
sl@0
   637
sl@0
   638
		// Test multiple notifiers on different drives
sl@0
   639
sl@0
   640
		const TInt KNumDrives = 1;
sl@0
   641
sl@0
   642
		test.Next(_L("Register several notifiers for different drives and check status"));
sl@0
   643
		for(i=0; i < KNumDrives; i++)
sl@0
   644
			{
sl@0
   645
   			clientFs[0].NotifyDismount(removalDrvNo + i, trsClientNotify[i]);
sl@0
   646
			test(trsClientNotify[i] == KRequestPending);
sl@0
   647
			}
sl@0
   648
sl@0
   649
		test.Next(_L("Notify clients and verify all requests signalled"));
sl@0
   650
   		fs.NotifyDismount(removalDrvNo, trsClientComplete, EFsDismountNotifyClients);
sl@0
   651
		test(trsClientComplete == KRequestPending);
sl@0
   652
sl@0
   653
		test(trsClientNotify[0] == KErrNone);
sl@0
   654
		LOG_AND_TEST(KErrNone, clientFs[0].AllowDismount(removalDrvNo));
sl@0
   655
		for(i=1; i< KNumDrives; i++)
sl@0
   656
			{
sl@0
   657
			test(trsClientNotify[i] == KRequestPending);
sl@0
   658
			}
sl@0
   659
sl@0
   660
		test.Next(_L("Verify that file system has been dismounted"));
sl@0
   661
		test(trsClientComplete == KErrNone);
sl@0
   662
sl@0
   663
		test.Next(_L("Check that file can be closed when filesystem is dismounted"));
sl@0
   664
		file.Close();
sl@0
   665
		dir.Close();
sl@0
   666
sl@0
   667
		test.Next(_L("Mount FAT FS on to the removal drive"));
sl@0
   668
		LOG_AND_TEST(KErrNone, fs.MountFileSystem(fsName, removalDrvNo));
sl@0
   669
sl@0
   670
		test.Next(_L("Cancel all outstanding notifiers for this session"));
sl@0
   671
   		clientFs[0].NotifyDismountCancel();
sl@0
   672
		for(i=1; i< KNumDrives; i++)
sl@0
   673
			{
sl@0
   674
			test(trsClientNotify[i] == KErrCancel);
sl@0
   675
			}
sl@0
   676
sl@0
   677
		// Test session disconnect
sl@0
   678
		test.Next(_L("Register for notification of pending media removal (again) and check status"));
sl@0
   679
		for(i=0; i< KNumClients; i++)
sl@0
   680
			{
sl@0
   681
   			clientFs[i].NotifyDismount(removalDrvNo, trsClientNotify[i]);
sl@0
   682
			test(trsClientNotify[i] == KRequestPending);
sl@0
   683
			}
sl@0
   684
sl@0
   685
		test.Next(_L("Close client sessions with outstanding notifiers"));
sl@0
   686
		for(i=0; i< KNumClients; i++)
sl@0
   687
			clientFs[i].Close();
sl@0
   688
sl@0
   689
		// Since all clients have been closed, the next stage should result in a dismount
sl@0
   690
		test.Next(_L("Notify clients of pending media removal and check status"));
sl@0
   691
		fs.NotifyDismount(removalDrvNo, trsClientComplete, EFsDismountNotifyClients);
sl@0
   692
		test(trsClientComplete == KErrNone);
sl@0
   693
sl@0
   694
		test.Next(_L("Mount FAT FS on to the removal drive"));
sl@0
   695
		LOG_AND_TEST(KErrNone, fs.MountFileSystem(fsName, removalDrvNo));
sl@0
   696
sl@0
   697
		TRequestStatus trs1;
sl@0
   698
		dismountFs1.NotifyDismount(removalDrvNo, trs1);
sl@0
   699
		test(trs1 == KRequestPending);
sl@0
   700
sl@0
   701
   		fs.NotifyDismount(removalDrvNo, trsClientComplete, EFsDismountNotifyClients);
sl@0
   702
		test(trsClientComplete == KRequestPending);
sl@0
   703
sl@0
   704
		fs.Close();
sl@0
   705
		dismountFs1.Close();
sl@0
   706
	}
sl@0
   707
sl@0
   708
	// Check that files/directories can't be opened on Mass Storage
sl@0
   709
	
sl@0
   710
	LOG_AND_TEST(KErrNone, fs.Connect());
sl@0
   711
sl@0
   712
	test.Next(_L("Dismount FAT File System"));
sl@0
   713
	LOG_AND_TEST(KErrNone, fs.DismountFileSystem(fsName, removalDrvNo));
sl@0
   714
sl@0
   715
	test.Next(_L("Mount MS FS on to the removable drive"));
sl@0
   716
	LOG_AND_TEST(KErrNone, fs.MountFileSystem(KMsFsyName, removalDrvNo));
sl@0
   717
sl@0
   718
	test.Next(_L("Attempting to open a file\n\r"));
sl@0
   719
	LOG_AND_TEST(KErrNotReady, file.Open(fs, fileName, EFileRead));
sl@0
   720
sl@0
   721
	test.Next(_L("Attempting to open a directory\n\r"));
sl@0
   722
    LOG_AND_TEST(KErrNotReady, dir.Open(fs, fileName, KEntryAttNormal));
sl@0
   723
sl@0
   724
	// Test fix for DEF058681 - Mass Storage reports VolumeName incorrectly.
sl@0
   725
	// Before the fix, CMassStorageMountCB::MountL() did not set the volume
sl@0
   726
	// name, resulting in a panic when attempting to copy a null descriptor.
sl@0
   727
	// Note that the volume name is still not returned client-side, since
sl@0
   728
	// CMassStorageMountCB::VolumeL() returns KErrNotReady
sl@0
   729
	TVolumeInfo volInfo;
sl@0
   730
	ret = fs.Volume(volInfo, removalDrvNo);
sl@0
   731
	LOG_AND_TEST(ret, KErrNotReady);
sl@0
   732
	LOG_AND_TEST(volInfo.iName.Length(), 0);
sl@0
   733
sl@0
   734
	// -------------------------------------------------
sl@0
   735
   
sl@0
   736
    // Get the boot sector info using MS FS and save it for later comparison
sl@0
   737
    TBuf8<CBW_LENGTH> cbwBuf; 
sl@0
   738
    TInt dCBWTag = 1234567;    // arbitrary, any number would do for this test.
sl@0
   739
 
sl@0
   740
    RDevTestUsbcClient usbcClient;
sl@0
   741
sl@0
   742
    // Open a session to LDD
sl@0
   743
    test.Next(_L("Open LDD"));
sl@0
   744
    LOG_AND_TEST(KErrNone, usbcClient.Open(0));
sl@0
   745
sl@0
   746
	// Build SCSI command test unit ready
sl@0
   747
    TBuf8<SCSI_UNIT_READY_LEN> unitReadyBuf;
sl@0
   748
    // Zero out the buf
sl@0
   749
    unitReadyBuf.FillZ(SCSI_UNIT_READY_LEN);
sl@0
   750
sl@0
   751
    createCBW(cbwBuf, dCBWTag, 0, 0, SCSI_UNIT_READY_LEN, unitReadyBuf);
sl@0
   752
sl@0
   753
    // Send test unit ready command
sl@0
   754
    test.Next(_L("Sending CBW with 'Unit Ready' cmd"));
sl@0
   755
	TRequestStatus status;
sl@0
   756
    usbcClient.HostWrite(status, EEndpoint1, cbwBuf, CBW_LENGTH); 
sl@0
   757
    User::WaitForRequest(status);
sl@0
   758
    LOG_AND_TEST(KErrNone,  status.Int());
sl@0
   759
sl@0
   760
    // Read CSW
sl@0
   761
	test.Next(_L("Reading CSW"));
sl@0
   762
    TBuf8<CSW_LENGTH> cswBuf;
sl@0
   763
    usbcClient.HostRead(status, EEndpoint2, cswBuf, CSW_LENGTH);
sl@0
   764
    User::WaitForRequest(status);
sl@0
   765
    LOG_AND_TEST(KErrNone,  status.Int());
sl@0
   766
sl@0
   767
    // Check dCSWTag
sl@0
   768
    TInt recvedCBWTag = extractInt(&cswBuf[4]);
sl@0
   769
    LOG_AND_TEST(dCBWTag,  recvedCBWTag);
sl@0
   770
     
sl@0
   771
    // Check bCSWStatus
sl@0
   772
    TInt bCSWStatus = cswBuf[CSW_LENGTH - 1];
sl@0
   773
    test.Printf(_L("CSW status: %d\n"), bCSWStatus);
sl@0
   774
    LOG_AND_TEST(bCSWStatus,  1);
sl@0
   775
sl@0
   776
	//============================================
sl@0
   777
sl@0
   778
	// Create a CBW for SCSI read (10) command to read the boot sector via MS FS 
sl@0
   779
    TBuf8<SCSI_READ_LEN> readBuf;  
sl@0
   780
    // 0: starting sector; 1: total blocks    
sl@0
   781
    createReadCmd(readBuf, 0, 1); 
sl@0
   782
    
sl@0
   783
    // 0x80: data-in to the host; 10: read (10) command length
sl@0
   784
    createCBW(cbwBuf, ++dCBWTag, BOOTSECTOR_SIZE, 0x80, 10, readBuf);
sl@0
   785
    
sl@0
   786
sl@0
   787
	// Send CBW to the LDD
sl@0
   788
    test.Next(_L("Send CBW with 'Read' Command"));
sl@0
   789
    usbcClient.HostWrite(status, EEndpoint1, cbwBuf, CBW_LENGTH);
sl@0
   790
    User::WaitForRequest(status);
sl@0
   791
    LOG_AND_TEST(KErrNone, status.Int());
sl@0
   792
sl@0
   793
sl@0
   794
	
sl@0
   795
	test.Next(_L("Reading bootsector data"));
sl@0
   796
    // Read the boot sector 
sl@0
   797
    TBuf8<BOOTSECTOR_SIZE> msBootSector;
sl@0
   798
    usbcClient.HostRead(status, EEndpoint2, msBootSector, BOOTSECTOR_SIZE); 
sl@0
   799
    User::WaitForRequest(status);
sl@0
   800
    LOG_AND_TEST(KErrNone, status.Int());
sl@0
   801
sl@0
   802
    // Read CSW
sl@0
   803
    test.Next(_L("Reading CSW"));
sl@0
   804
    usbcClient.HostRead(status, EEndpoint2, cswBuf, CSW_LENGTH);
sl@0
   805
    User::WaitForRequest(status);
sl@0
   806
    LOG_AND_TEST(KErrNone, status.Int());
sl@0
   807
sl@0
   808
    // Check dCBWTag
sl@0
   809
    recvedCBWTag = extractInt(&cswBuf[4]);
sl@0
   810
    LOG_AND_TEST(dCBWTag,  recvedCBWTag);
sl@0
   811
     
sl@0
   812
    // Check bCSWStatus
sl@0
   813
    bCSWStatus = cswBuf[CSW_LENGTH - 1];
sl@0
   814
    test.Printf(_L("CSW status: %d\n"), bCSWStatus);
sl@0
   815
    
sl@0
   816
    LOG_AND_TEST(bCSWStatus,  0);
sl@0
   817
sl@0
   818
    // Compare FAT FS boot sector with MS FS boot sector
sl@0
   819
    // When accessing the medium through USB, it is accessed raw. That means 
sl@0
   820
    // we have to find the boot record (BPB), which may be in sector 0 if the 
sl@0
   821
    // medium has no MBR or elsewhere if it is has a MBR. (Details of the 
sl@0
   822
    // identification can be found in the FAT32 specification)
sl@0
   823
    TUint16 signature;
sl@0
   824
    
sl@0
   825
    signature = (TUint16) (msBootSector[KMBRSignatureOffset] | 
sl@0
   826
                msBootSector[KMBRSignatureOffset + 1] << 8);
sl@0
   827
                
sl@0
   828
	LOG_AND_TEST(signature, KBootRecordSignature);
sl@0
   829
	
sl@0
   830
	if(((msBootSector[0] == 0xEB && msBootSector[2] == 0x90) || (msBootSector[0] == 0xE9)) && 
sl@0
   831
		(msBootSector[16] >= 1) && ((msBootSector[21] == 0xF0) || (msBootSector[21] >= 0xF8)))
sl@0
   832
		{
sl@0
   833
		test.Printf(_L("BPB identified in sector 0.\r\n"));			
sl@0
   834
		}
sl@0
   835
	else
sl@0
   836
		{	
sl@0
   837
		test.Printf(_L("Assume sector 0 to be MBR - attempting to locate BPB\r\n"));
sl@0
   838
		// Read the offset to the first partition to find the boot record...
sl@0
   839
		// 32bit int stored as little endian
sl@0
   840
		TUint32 bootSectorLocation;
sl@0
   841
		bootSectorLocation = msBootSector[KMBRFirstPartitionSectorOffset]           | 
sl@0
   842
							 msBootSector[KMBRFirstPartitionSectorOffset + 1] << 8  |
sl@0
   843
							 msBootSector[KMBRFirstPartitionSectorOffset + 2] << 16 |
sl@0
   844
							 msBootSector[KMBRFirstPartitionSectorOffset + 3] << 24;
sl@0
   845
		
sl@0
   846
		test.Printf(_L("Reading Boot Sector from offset %d\r\n"), bootSectorLocation);
sl@0
   847
sl@0
   848
		// Create a CBW for SCSI read (10) command to read the boot sector via MS FS 
sl@0
   849
		TBuf8<SCSI_READ_LEN> readBuf;  
sl@0
   850
		// 0: starting sector; 1: total blocks    
sl@0
   851
		createReadCmd(readBuf, bootSectorLocation, 1); 
sl@0
   852
		
sl@0
   853
		// 0x80: data-in to the host; 10: read (10) command length
sl@0
   854
		createCBW(cbwBuf, ++dCBWTag, BOOTSECTOR_SIZE, 0x80, 10, readBuf);
sl@0
   855
sl@0
   856
		// Send CBW to the LDD
sl@0
   857
		test.Next(_L("Send CBW with 'Read' Command"));
sl@0
   858
		usbcClient.HostWrite(status, EEndpoint1, cbwBuf, CBW_LENGTH);
sl@0
   859
		User::WaitForRequest(status);
sl@0
   860
		LOG_AND_TEST(KErrNone, status.Int());
sl@0
   861
		
sl@0
   862
		// Read the boot sector 
sl@0
   863
		usbcClient.HostRead(status, EEndpoint2, msBootSector, BOOTSECTOR_SIZE); 
sl@0
   864
		User::WaitForRequest(status);
sl@0
   865
		LOG_AND_TEST(KErrNone, status.Int());
sl@0
   866
		
sl@0
   867
		// Read CSW
sl@0
   868
		test.Next(_L("Reading CSW"));
sl@0
   869
		usbcClient.HostRead(status, EEndpoint2, cswBuf, CSW_LENGTH);
sl@0
   870
		User::WaitForRequest(status);
sl@0
   871
		LOG_AND_TEST(KErrNone, status.Int());
sl@0
   872
		
sl@0
   873
		// Check dCBWTag
sl@0
   874
		recvedCBWTag = extractInt(&cswBuf[4]);
sl@0
   875
		LOG_AND_TEST(dCBWTag,  recvedCBWTag);
sl@0
   876
		 
sl@0
   877
		// Check bCSWStatus
sl@0
   878
		bCSWStatus = cswBuf[CSW_LENGTH - 1];
sl@0
   879
		test.Printf(_L("CSW status: %d\n"), bCSWStatus);
sl@0
   880
		
sl@0
   881
		LOG_AND_TEST(bCSWStatus,  0);
sl@0
   882
		}
sl@0
   883
    
sl@0
   884
    test (0 == fatBootSector.Compare(msBootSector));
sl@0
   885
    
sl@0
   886
    //
sl@0
   887
    // Create a CBW to prevent medium removal
sl@0
   888
    // 
sl@0
   889
    TBuf8<SCSI_MED_RMVL_LEN> tBuf; 
sl@0
   890
    // Zero out the buf
sl@0
   891
    tBuf.FillZ(SCSI_MED_RMVL_LEN);
sl@0
   892
    tBuf[0] = 0x1E;
sl@0
   893
    tBuf[4] = 1;        // prevent medium removal 
sl@0
   894
sl@0
   895
    cbwBuf.FillZ(CBW_LENGTH);
sl@0
   896
    createCBW(cbwBuf, ++dCBWTag, 0, 0, SCSI_MED_RMVL_LEN, tBuf);
sl@0
   897
sl@0
   898
    // Send prevent medium removal command
sl@0
   899
    test.Next(_L("Sending CBW with 'Prevent media removal' cmd"));
sl@0
   900
    usbcClient.HostWrite(status, EEndpoint1, cbwBuf, CBW_LENGTH); 
sl@0
   901
    User::WaitForRequest(status);
sl@0
   902
    LOG_AND_TEST(KErrNone,  status.Int());
sl@0
   903
sl@0
   904
    // Read CSW
sl@0
   905
    test.Next(_L("Reading CSW"));
sl@0
   906
    usbcClient.HostRead(status, EEndpoint2, cswBuf, CSW_LENGTH);
sl@0
   907
    User::WaitForRequest(status);
sl@0
   908
    LOG_AND_TEST(KErrNone, status.Int());
sl@0
   909
sl@0
   910
    // Check dCSWTag
sl@0
   911
    recvedCBWTag = extractInt(&cswBuf[4]);
sl@0
   912
    LOG_AND_TEST(dCBWTag,  recvedCBWTag);
sl@0
   913
     
sl@0
   914
    // Check bCSWStatus
sl@0
   915
    bCSWStatus = cswBuf[CSW_LENGTH - 1];
sl@0
   916
    test.Printf(_L("CSW status: %d\n"), bCSWStatus);
sl@0
   917
    
sl@0
   918
	if(bCSWStatus ==  0)
sl@0
   919
		{
sl@0
   920
    
sl@0
   921
		// Try to unmount MS FS. This should fail as medium removal is disallowed
sl@0
   922
		test.Next(_L("Dismounting MSFS"));
sl@0
   923
		test(KErrNone != fs.DismountFileSystem(KMsFsyName, removalDrvNo));
sl@0
   924
		
sl@0
   925
		// 
sl@0
   926
		// Create a CBW to allow medium removal
sl@0
   927
		//
sl@0
   928
		// Zero out the buf
sl@0
   929
		tBuf.FillZ(SCSI_MED_RMVL_LEN);
sl@0
   930
		tBuf[0] = 0x1E;
sl@0
   931
		tBuf[4] = 0;        // allow medium removal 
sl@0
   932
sl@0
   933
		createCBW(cbwBuf, ++dCBWTag, 0, 0, SCSI_MED_RMVL_LEN, tBuf);
sl@0
   934
sl@0
   935
		// Send allow medium removal command
sl@0
   936
		test.Next(_L("Sending CBW with 'Allow media removal' cmd"));
sl@0
   937
		usbcClient.HostWrite(status, EEndpoint1, cbwBuf, CBW_LENGTH); 
sl@0
   938
		User::WaitForRequest(status);
sl@0
   939
		LOG_AND_TEST(KErrNone, status.Int());
sl@0
   940
sl@0
   941
		// Read CSW
sl@0
   942
		test.Next(_L("Reading CSW"));
sl@0
   943
		usbcClient.HostRead(status, EEndpoint2, cswBuf, CSW_LENGTH);
sl@0
   944
		User::WaitForRequest(status);
sl@0
   945
		LOG_AND_TEST(KErrNone, status.Int());
sl@0
   946
sl@0
   947
		// Check dCSWTag
sl@0
   948
		recvedCBWTag = extractInt(&cswBuf[4]);
sl@0
   949
		LOG_AND_TEST(dCBWTag, recvedCBWTag);
sl@0
   950
     
sl@0
   951
		// Check bCSWStatus
sl@0
   952
		bCSWStatus = cswBuf[CSW_LENGTH - 1];
sl@0
   953
		test.Printf(_L("CSW status: %d\n"), bCSWStatus);
sl@0
   954
		LOG_AND_TEST(bCSWStatus,  0);
sl@0
   955
sl@0
   956
		}
sl@0
   957
    else
sl@0
   958
		test.Printf(_L("Prevent Media Removal command not supported, skipping appropriate tests"));
sl@0
   959
sl@0
   960
sl@0
   961
    // Try to unmount MS FS again. This time it should succeed
sl@0
   962
	LOG_AND_TEST(KErrNone, fs.DismountFileSystem(KMsFsyName, removalDrvNo));
sl@0
   963
sl@0
   964
    // Read the boot sector while MS FS is unmounted, this should fail
sl@0
   965
    test(KErrNone != fatDiskF.Open(fs, removalDrvNo));
sl@0
   966
    fatDiskF.Close();    
sl@0
   967
    
sl@0
   968
    // Mount FAT FS on to the removal drive
sl@0
   969
    LOG_AND_TEST(KErrNone, fs.MountFileSystem(fsName, removalDrvNo));
sl@0
   970
sl@0
   971
	// Additional step for DEF079149: File server crash when re-adding 
sl@0
   972
	// MSFS.FSY. Before the fix was applied this call to RFs::AddFileSystem 
sl@0
   973
	// would cause a crash.
sl@0
   974
	LOG_AND_TEST(KErrAlreadyExists,fs.AddFileSystem(KMsFs));
sl@0
   975
sl@0
   976
    // Read the boot sector after FAT MS is mounted on to the removal drive
sl@0
   977
    LOG_AND_TEST(KErrNone,  fatDiskF.Open(fs, removalDrvNo));
sl@0
   978
    LOG_AND_TEST(KErrNone,  fatDiskF.Read(0, fatBootSector));
sl@0
   979
    fatDiskF.Close();
sl@0
   980
sl@0
   981
    createCBW(cbwBuf, ++dCBWTag, 0, 0, SCSI_UNIT_READY_LEN, unitReadyBuf);
sl@0
   982
sl@0
   983
    // Send test unit ready command
sl@0
   984
    test.Next(_L("Sending CBW with 'Unit Ready' cmd"));
sl@0
   985
    usbcClient.HostWrite(status, EEndpoint1, cbwBuf, CBW_LENGTH); 
sl@0
   986
    User::WaitForRequest(status);
sl@0
   987
    LOG_AND_TEST(KErrNone,  status.Int());
sl@0
   988
sl@0
   989
    // Read CSW
sl@0
   990
    usbcClient.HostRead(status, EEndpoint2, cswBuf, CSW_LENGTH);
sl@0
   991
    User::WaitForRequest(status);
sl@0
   992
    LOG_AND_TEST(KErrNone,  status.Int());
sl@0
   993
sl@0
   994
    // Check dCSWTag
sl@0
   995
    recvedCBWTag = extractInt(&cswBuf[4]);
sl@0
   996
    LOG_AND_TEST(dCBWTag,  recvedCBWTag);
sl@0
   997
     
sl@0
   998
    // Check bCSWStatus
sl@0
   999
    bCSWStatus = cswBuf[CSW_LENGTH - 1];
sl@0
  1000
    test.Printf(_L("CSW status: %d\n"), bCSWStatus);
sl@0
  1001
    LOG_AND_TEST(bCSWStatus,  1);
sl@0
  1002
 
sl@0
  1003
    // 
sl@0
  1004
    // Read MS FS using SCSI read command, this should fail as
sl@0
  1005
    // FAT FS is mounted instead
sl@0
  1006
    //
sl@0
  1007
    
sl@0
  1008
    // 0x80: data-in to the host; 10: read (10) command length
sl@0
  1009
sl@0
  1010
    createCBW(cbwBuf, ++dCBWTag, BOOTSECTOR_SIZE, 0x80, 10, readBuf);
sl@0
  1011
sl@0
  1012
    // Send CBW to the LDD
sl@0
  1013
    test.Next(_L("SEnding CBW with 'Read'"));
sl@0
  1014
    usbcClient.HostWrite(status, EEndpoint1, cbwBuf, CBW_LENGTH);
sl@0
  1015
    User::WaitForRequest(status);
sl@0
  1016
    LOG_AND_TEST(KErrNone,  status.Int());
sl@0
  1017
sl@0
  1018
    // Read the sector 
sl@0
  1019
    usbcClient.HostRead(status, EEndpoint2, msBootSector, BOOTSECTOR_SIZE); 
sl@0
  1020
    User::WaitForRequest(status);
sl@0
  1021
    LOG_AND_TEST(KErrNone,  status.Int());
sl@0
  1022
sl@0
  1023
sl@0
  1024
    // Read CSW
sl@0
  1025
    usbcClient.HostRead(status, EEndpoint2, cswBuf, CSW_LENGTH);
sl@0
  1026
    User::WaitForRequest(status);
sl@0
  1027
    LOG_AND_TEST(KErrNone,  status.Int());
sl@0
  1028
sl@0
  1029
    // Check dCSWTag
sl@0
  1030
    recvedCBWTag = extractInt(&cswBuf[4]);
sl@0
  1031
    LOG_AND_TEST(dCBWTag , recvedCBWTag);
sl@0
  1032
     
sl@0
  1033
    // Check bCSWStatus
sl@0
  1034
    bCSWStatus = cswBuf[CSW_LENGTH - 1];
sl@0
  1035
    test.Printf(_L("CSW status: %d\n"), bCSWStatus);
sl@0
  1036
    test(bCSWStatus != 0);
sl@0
  1037
    
sl@0
  1038
   
sl@0
  1039
    // Read FAT FS using RFs API
sl@0
  1040
    LOG_AND_TEST(KErrNone,  fatDiskF.Open(fs, removalDrvNo));
sl@0
  1041
    LOG_AND_TEST(KErrNone,  fatDiskF.Read(0, fatBootSector));
sl@0
  1042
    fatDiskF.Close();    
sl@0
  1043
    
sl@0
  1044
    // Stop usb mass storage device
sl@0
  1045
    LOG_AND_TEST(KErrNone,  usbMs.Stop());
sl@0
  1046
    usbMs.Close();
sl@0
  1047
	User::After(1000000);
sl@0
  1048
    
sl@0
  1049
    ret = fs.RemoveFileSystem(KMsFsyName);
sl@0
  1050
	fs.Close();
sl@0
  1051
	
sl@0
  1052
	usbcClient.Close();
sl@0
  1053
	ret = User::FreeLogicalDevice(_L("USBC"));
sl@0
  1054
	LOG_AND_TEST(ret,  KErrNone);
sl@0
  1055
sl@0
  1056
	test.Printf(_L("Exiting test\r\n"));	
sl@0
  1057
	__UHEAP_MARKEND;
sl@0
  1058
	}
sl@0
  1059
	
sl@0
  1060
sl@0
  1061
sl@0
  1062
GLDEF_C void CallTestsL()
sl@0
  1063
//
sl@0
  1064
// Do all tests
sl@0
  1065
//
sl@0
  1066
	{
sl@0
  1067
    // Parse the CommandLine arguments: removal drive and non-removal drive
sl@0
  1068
    ParseCommandArguments();
sl@0
  1069
sl@0
  1070
    // Run test
sl@0
  1071
	test.Start( _L("Test mountstart") );
sl@0
  1072
    doComponentTest();
sl@0
  1073
    test.End();
sl@0
  1074
    }