|
1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // CMassStorageFileSystem implementation. |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 @internalTechnology |
|
21 */ |
|
22 |
|
23 #include <f32file.h> |
|
24 #include "cmassstoragefilesystem.h" |
|
25 #include "cmassstoragemountcb.h" |
|
26 #include "massstoragedebug.h" |
|
27 #include "massstorage.h" |
|
28 |
|
29 _LIT(KMsFsyName, "MassStorageFileSystem"); |
|
30 _LIT(KMsThreadName, "MassStorageThread"); |
|
31 _LIT(KMsDeadThreadName, "MassStorageDeadThread"); |
|
32 _LIT(KMsFsysSemName, "MassStorageSemaphore"); |
|
33 LOCAL_D const TInt KMsFsyMajorVersionNumber=1; |
|
34 LOCAL_D const TInt KMsFsyMinorVersionNumber=0; |
|
35 |
|
36 CMassStorageFileSystem::CMassStorageFileSystem() |
|
37 { |
|
38 } |
|
39 |
|
40 CMassStorageFileSystem::~CMassStorageFileSystem() |
|
41 { |
|
42 //Kill the controller thread if it exists |
|
43 delete iMassStorageController; |
|
44 delete iMediaChanged; |
|
45 RThread thread; |
|
46 TInt err = thread.Open(KMsThreadName); |
|
47 if (err == KErrNone) |
|
48 { |
|
49 thread.Kill(1); //Parameter is irrelevant |
|
50 } |
|
51 thread.Close(); |
|
52 iMsDrives.Close(); |
|
53 } |
|
54 |
|
55 CMassStorageFileSystem* CMassStorageFileSystem::NewL() |
|
56 { |
|
57 CMassStorageFileSystem* self = new (ELeave) CMassStorageFileSystem(); |
|
58 CleanupStack::PushL(self); |
|
59 self->ConstructL(); |
|
60 CleanupStack::Pop(self); |
|
61 return self; |
|
62 } |
|
63 |
|
64 void CMassStorageFileSystem::ConstructL() |
|
65 { |
|
66 iMediaChanged = new(ELeave) CArrayFixFlat<TBool>(KMaxDrives); |
|
67 } |
|
68 |
|
69 /** |
|
70 Set the file system version and name |
|
71 |
|
72 @return Any of the standard Symbian error codes. |
|
73 */ |
|
74 TInt CMassStorageFileSystem::Install() |
|
75 { |
|
76 __PRINT(_L("CMassStorageFileSystem::Install In\n")); |
|
77 iVersion=TVersion(KMsFsyMajorVersionNumber, KMsFsyMinorVersionNumber, KF32BuildVersionNumber); |
|
78 TInt err = SetName(&KMsFsyName); |
|
79 __PRINT(_L("CMassStorageFileSystem::Install Out\n")); |
|
80 return err; |
|
81 } |
|
82 |
|
83 TInt CMassStorageFileSystem::Remove() |
|
84 { |
|
85 __PRINT(_L("CMassStorageFileSystem::Remove In\n")); |
|
86 TInt err = KErrNone; |
|
87 if (iInstalled) |
|
88 { |
|
89 // Try connecting to the server to send a shutdown message. |
|
90 // - If the class controller has a session in use, this will return KErrInUse |
|
91 RUsbMassStorage usbMs; |
|
92 err = usbMs.Connect(); |
|
93 if(err == KErrNone) |
|
94 { |
|
95 err = usbMs.Shutdown(); |
|
96 usbMs.Close(); |
|
97 |
|
98 if(err == KErrNone) |
|
99 { |
|
100 User::WaitForRequest(iThreadStat); |
|
101 err = iThreadStat.Int(); |
|
102 } |
|
103 else |
|
104 { |
|
105 __PRINT1(_L("CMassStorageFileSystem::Remove Shutdown Error %d\n"),err); |
|
106 } |
|
107 } |
|
108 else |
|
109 { |
|
110 __PRINT1(_L("CMassStorageFileSystem::Remove Connect Error %d\n"),err); |
|
111 } |
|
112 } |
|
113 __PRINT(_L("CMassStorageFileSystem::Remove Out\n")); |
|
114 return(err); |
|
115 } |
|
116 |
|
117 /** |
|
118 Creates a new Mass Storage mount object. |
|
119 |
|
120 @return A new CMassStorageMountCB |
|
121 @leave KErrNotReady if the Mass Storage controller is not running. |
|
122 */ |
|
123 CMountCB* CMassStorageFileSystem::NewMountL() const |
|
124 { |
|
125 if (!iRunning) |
|
126 { |
|
127 User::Leave(KErrNotReady); |
|
128 } |
|
129 return CMassStorageMountCB::NewL(iMsDrives); |
|
130 } |
|
131 |
|
132 /** |
|
133 Sets the media attributes and type in the aInfo parameter to those of the specified drive. |
|
134 |
|
135 @param anInfo TDriveInfo object to store the drive information. |
|
136 @param aDriveNumber The number of the drive to get the information from. |
|
137 */ |
|
138 void CMassStorageFileSystem::DriveInfo(TDriveInfo& aInfo, TInt aDriveNumber) const |
|
139 { |
|
140 __PRINT(_L("CMassStorageFileSystem::DriveInfo In\n")); |
|
141 TLocalDriveCapsV2Buf caps; |
|
142 if (!IsValidLocalDriveMapping(aDriveNumber)) |
|
143 { |
|
144 return; |
|
145 } |
|
146 (void)GetLocalDrive(aDriveNumber).Caps(caps); |
|
147 // error ignored as Caps always returns valid Media and Drive attributes |
|
148 aInfo.iMediaAtt=caps().iMediaAtt; |
|
149 aInfo.iType = ::EMediaNotPresent; // Media is not available to the file system |
|
150 aInfo.iDriveAtt=caps().iDriveAtt; |
|
151 __PRINT(_L("CMassStorageFileSystem::DriveInfo Out\n")); |
|
152 } |
|
153 |
|
154 /** |
|
155 Returns a reference to the Mass Storage controller. |
|
156 |
|
157 @return Reference to the Mass Storage controller. |
|
158 */ |
|
159 CUsbMassStorageController& CMassStorageFileSystem::Controller() |
|
160 { |
|
161 return *iMassStorageController; |
|
162 } |
|
163 |
|
164 /** |
|
165 Fill iMsDrives with a mapping of lun->drive number for supported mass storage drives |
|
166 |
|
167 */ |
|
168 TInt CMassStorageFileSystem::EnumerateMsDrivesL() |
|
169 { |
|
170 __PRINT(_L("CMassStorageFileSystem::EnumerateMsDrives In\n")); |
|
171 iMsDrives.Reset(); |
|
172 TInt driveCount = 0; |
|
173 |
|
174 TLocalDriveCapsV2Buf caps; |
|
175 for (TInt i = EDriveC; i < KMaxDrives; i++) |
|
176 { |
|
177 caps.FillZ(); |
|
178 |
|
179 if (IsValidLocalDriveMapping(i)) |
|
180 { |
|
181 TInt err = GetLocalDrive(i).Caps(caps); |
|
182 TInt locDrvNum = DriveNumberToLocalDriveNumber(i); |
|
183 __PRINT2(_L("Caps: err=%d, att=%d\n"), err, caps().iDriveAtt); |
|
184 |
|
185 TBool isRemovable = err==KErrNotReady || (caps().iDriveAtt & KDriveAttRemovable); |
|
186 __PRINT2(_L("EnumerateMsDrives: Drive %c: is %sremovable\n"), |
|
187 'A'+i-EDriveA, |
|
188 isRemovable?_S(""):_S("NOT ")); |
|
189 |
|
190 if (isRemovable) |
|
191 { |
|
192 // |
|
193 // STF: Connect to the local drive here. This gives us the media changed flag, and |
|
194 // our own TBusLocalDrive object for use by the proxy drive and controller. |
|
195 // |
|
196 TBool& mediaChanged = (*iMediaChanged).ExtendL(); |
|
197 mediaChanged = EFalse; |
|
198 TBusLocalDrive* localDrive = new(ELeave) TBusLocalDrive; |
|
199 iLocalDriveForMediaFlag.Append(*localDrive); |
|
200 |
|
201 TInt err=iLocalDriveForMediaFlag[driveCount].Connect(locDrvNum, mediaChanged); |
|
202 if(err == KErrNone) |
|
203 { |
|
204 iMsDrives.Append(i); |
|
205 } |
|
206 driveCount++; |
|
207 } |
|
208 } |
|
209 } |
|
210 |
|
211 __PRINT1(_L("CMassStorageFileSystem::EnumerateMsDrives Out, %d MS drives found\n"), driveCount); |
|
212 return driveCount; |
|
213 } |
|
214 |
|
215 TBool CMassStorageFileSystem::IsExtensionSupported() const |
|
216 { |
|
217 return ETrue; |
|
218 } |
|
219 |
|
220 /** |
|
221 Creates a TrapCleanup and ActiveScheduler and initializes the Mass Storage controller. |
|
222 Start the ActiveScheduler. |
|
223 |
|
224 @return Any of the standard Symbian error codes. |
|
225 */ |
|
226 TInt CMassStorageFileSystem::InitThread() |
|
227 { |
|
228 __PRINT(_L("CMassStorageFileSystem::InitThread In\n")); |
|
229 |
|
230 //Give the thread a name so we can kill it later |
|
231 User::RenameThread(KMsThreadName); |
|
232 |
|
233 CTrapCleanup* cleanup = CTrapCleanup::New(); |
|
234 if (cleanup == NULL) |
|
235 { |
|
236 return KErrNoMemory; |
|
237 } |
|
238 |
|
239 TRAPD(err, InitThreadL()); |
|
240 |
|
241 delete cleanup; |
|
242 |
|
243 __PRINT1(_L("CMassStorageFileSystem::InitThread Out, error=%d\n"), err); |
|
244 return err; |
|
245 } |
|
246 |
|
247 TInt CMassStorageFileSystem::InitThreadL() |
|
248 { |
|
249 __PRINT(_L("CMassStorageFileSystem::InitThreadL In\n")); |
|
250 |
|
251 RSemaphore gSemThreadReady; |
|
252 |
|
253 TInt ret = gSemThreadReady.OpenGlobal(KMsFsysSemName); |
|
254 |
|
255 if (ret != KErrNone && ret != KErrAlreadyExists) |
|
256 { |
|
257 User::Leave(ret); |
|
258 } |
|
259 |
|
260 // Determine which drives are available for Mass Storage. |
|
261 // (this also creates a local TBusLocalDrive for use by the drive controller) |
|
262 EnumerateMsDrivesL(); |
|
263 |
|
264 CActiveScheduler* sched = new CActiveScheduler; |
|
265 if (sched == NULL) |
|
266 { |
|
267 gSemThreadReady.Signal(); |
|
268 User::Leave(KErrNoMemory); |
|
269 } |
|
270 CleanupStack::PushL(sched); |
|
271 CActiveScheduler::Install(sched); |
|
272 |
|
273 iMassStorageController = new CUsbMassStorageController; |
|
274 if (iMassStorageController == NULL) |
|
275 { |
|
276 gSemThreadReady.Signal(); |
|
277 User::Leave(KErrNoMemory); |
|
278 } |
|
279 |
|
280 __PRINT(_L("CMassStorageFileSystem::InitThread: Creating Mass Storage Controller\n")); |
|
281 TRAPD(err, iMassStorageController->CreateL(iMsDrives)); |
|
282 if (err != KErrNone) |
|
283 { |
|
284 gSemThreadReady.Signal(); |
|
285 CActiveScheduler::Install(NULL); |
|
286 User::Leave(err); |
|
287 } |
|
288 |
|
289 CleanupStack::Pop(sched); |
|
290 |
|
291 iRunning = ETrue; |
|
292 gSemThreadReady.Signal(); |
|
293 gSemThreadReady.Close(); |
|
294 CActiveScheduler::Start(); |
|
295 |
|
296 //========= stop thread ================ |
|
297 delete iMassStorageController; |
|
298 iMassStorageController = NULL; |
|
299 TInt i=0; |
|
300 for (;i<iLocalDriveForMediaFlag.Count();i++) |
|
301 { |
|
302 iLocalDriveForMediaFlag[i].Disconnect(); |
|
303 } |
|
304 iLocalDriveForMediaFlag.Reset(); |
|
305 (*iMediaChanged).Reset(); |
|
306 delete sched; |
|
307 iRunning = EFalse; |
|
308 |
|
309 __PRINT(_L("CMassStorageFileSystem::InitThread Out\n")); |
|
310 return KErrNone; |
|
311 } |
|
312 |
|
313 /** |
|
314 Not supported in Mass Storage file system. |
|
315 |
|
316 @leave KErrNotReady |
|
317 */ |
|
318 CFileCB* CMassStorageFileSystem::NewFileL() const |
|
319 { |
|
320 __PRINT(_L("CMassStorageFileSystem::NewFileL In\n")); |
|
321 User::Leave(KErrNotReady); |
|
322 return NULL; |
|
323 } |
|
324 |
|
325 /** |
|
326 Not supported in Mass Storage file system. |
|
327 |
|
328 @leave KErrNotReady |
|
329 */ |
|
330 CDirCB* CMassStorageFileSystem::NewDirL() const |
|
331 { |
|
332 User::Leave(KErrNotReady); |
|
333 return NULL; |
|
334 } |
|
335 |
|
336 /** |
|
337 Not supported in Mass Storage file system. |
|
338 |
|
339 @leave KErrNotReady |
|
340 */ |
|
341 CFormatCB* CMassStorageFileSystem::NewFormatL() const |
|
342 { |
|
343 User::Leave(KErrNotReady); |
|
344 return NULL; |
|
345 } |
|
346 |
|
347 /** |
|
348 Not supported in Mass Storage file system. |
|
349 |
|
350 @return KErrNotSupported |
|
351 */ |
|
352 TInt CMassStorageFileSystem::DefaultPath(TDes& /*aPath*/) const |
|
353 { |
|
354 return KErrNotSupported; |
|
355 } |
|
356 |
|
357 /** |
|
358 Not supported in Mass Storage file system. |
|
359 |
|
360 @return KErrNotSupported |
|
361 */ |
|
362 TInt CMassStorageFileSystem::DriveList(TDriveList& /*aList*/) const |
|
363 { |
|
364 return KErrNotSupported; |
|
365 } |
|
366 |
|
367 /** |
|
368 Thread entry point. |
|
369 */ |
|
370 LOCAL_C TInt MsInitThreadFn(TAny* aPtr) |
|
371 { |
|
372 User::SetCritical(User::ESystemCritical); |
|
373 ((CMassStorageFileSystem*)aPtr)->InitThread(); |
|
374 //Rename the thread so we can create a new one with the same original name later |
|
375 User::RenameThread(KMsDeadThreadName); |
|
376 return KErrNone; |
|
377 } |
|
378 |
|
379 /** |
|
380 Standard entry point for file systems. |
|
381 Creates a new file system object and starts a new thread for the Mass Storage controller. |
|
382 */ |
|
383 extern "C" EXPORT_C CFileSystem* CreateFileSystem() |
|
384 { |
|
385 __PRINT(_L("CMassStorageFileSystem::CreateFileSystem In\n")); |
|
386 RSemaphore gSemThreadReady; |
|
387 TInt err = gSemThreadReady.CreateGlobal(KMsFsysSemName, 0); |
|
388 if (err != KErrNone) |
|
389 { |
|
390 __PRINT1(_L("CMassStorageFileSystem::CreateFileSystem Out Semaphore Error %d\n"),err); |
|
391 return NULL; |
|
392 } |
|
393 |
|
394 CFileSystem* msFsys = NULL; |
|
395 TRAP(err, msFsys = CMassStorageFileSystem::NewL()); |
|
396 if (err != KErrNone) |
|
397 { |
|
398 __PRINT1(_L("CMassStorageFileSystem::CreateFileSystem Out MSFS Error %d\n"),err); |
|
399 gSemThreadReady.Close(); |
|
400 return NULL; |
|
401 } |
|
402 |
|
403 RThread msThread; |
|
404 __PRINT(_L("CMassStorageFileSystem::CreateFileSystem: Creating Mass Storage thread\n")); |
|
405 err = msThread.Create(KMsThreadName, MsInitThreadFn, KDefaultStackSize, NULL, msFsys); |
|
406 if (err != KErrNone) |
|
407 { |
|
408 __PRINT1(_L("CMassStorageFileSystem::CreateFileSystem Out Thread Error %d\n"),err); |
|
409 gSemThreadReady.Close(); |
|
410 return msFsys; |
|
411 } |
|
412 ((CMassStorageFileSystem*)msFsys)->iInstalled=ETrue; |
|
413 |
|
414 |
|
415 msThread.Logon(((CMassStorageFileSystem*)msFsys)->iThreadStat); |
|
416 msThread.Resume(); |
|
417 gSemThreadReady.Wait(); |
|
418 gSemThreadReady.Close(); |
|
419 msThread.Close(); |
|
420 |
|
421 __PRINT(_L("CMassStorageFileSystem::CreateFileSystem Out Clean\n")); |
|
422 |
|
423 return msFsys; |
|
424 } |
|
425 |