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 |
}
|