|
1 // Copyright (c) 2002-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 // |
|
15 |
|
16 #include "sf_std.h" |
|
17 #include "e32cmn.h" |
|
18 |
|
19 #ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION |
|
20 #include "sf_notifier.h" |
|
21 #endif |
|
22 |
|
23 GLREF_C CProxyDriveFactory* GetExtension(const TDesC& aName); |
|
24 GLREF_C CExtProxyDriveFactory* GetProxyDriveFactory(const TDesC& aName); |
|
25 |
|
26 TBusLocalDrive LocalDrives::iLocalDrives[KMaxLocalDrives]; |
|
27 TInt LocalDrives::iMapping[KMaxDrives]; |
|
28 TInt LocalDrives::iReverseMapping[KMaxLocalDrives]; |
|
29 TBool LocalDrives::iMappingSet; |
|
30 LocalDrives::TSocketDesc LocalDrives::iSocketDescs[KMaxPBusSockets]; |
|
31 CExtProxyDrive* LocalDrives::iProxyDriveMapping[KMaxProxyDrives]; |
|
32 TBool LocalDrives::iIsMultiSlotDrive[KMaxDrives]; |
|
33 const TInt KInvalidSocketNumber = -1; |
|
34 |
|
35 void LocalDrives::Initialise() |
|
36 // |
|
37 // |
|
38 // |
|
39 { |
|
40 iMappingSet = EFalse; |
|
41 TInt i; |
|
42 Mem::FillZ((TAny*)iProxyDriveMapping,sizeof(CExtProxyDriveFactory*)*KMaxProxyDrives); |
|
43 // initialise mapping from drive number to local drive |
|
44 for(i=0;i<KMaxDrives;i++) |
|
45 { |
|
46 iMapping[i] = KDriveInvalid; |
|
47 iIsMultiSlotDrive[i] = EFalse; |
|
48 } |
|
49 // initialise reverse mapping from local drive to drive. |
|
50 for(i=0;i<KMaxLocalDrives;i++) |
|
51 { |
|
52 iReverseMapping[i] = KDriveInvalid; |
|
53 } |
|
54 // initialise mapping from socket number to drive numbers |
|
55 for(i=0;i<KMaxPBusSockets;++i) |
|
56 { |
|
57 TSocketDesc& socketDesc = iSocketDescs[i]; |
|
58 socketDesc.iMediaType = EInvalidMedia; |
|
59 socketDesc.iControllerRelativeSocket = KInvalidSocketNumber; |
|
60 for(TInt j=0;j<KMaxDrivesPerSocket;++j) |
|
61 socketDesc.iDriveNumbers[j]=KDriveInvalid; |
|
62 } |
|
63 } |
|
64 |
|
65 // Searches for a local socket which matches the media type and |
|
66 // controller relative socket number. |
|
67 // If none is found then this function returns a new socket number. |
|
68 // If no more free sockets available, returns KErrNoMemory |
|
69 TInt LocalDrives::GetLocalSocket(TInt aControllerRelativeSocket, TMediaDevice aMediaType) |
|
70 { |
|
71 TInt i; |
|
72 TSocketDesc* socketDesc = NULL; |
|
73 for (i=0; i<KMaxPBusSockets; i++) |
|
74 { |
|
75 socketDesc = &iSocketDescs[i]; |
|
76 TMediaDevice mediaType = socketDesc->iMediaType; |
|
77 if (mediaType == aMediaType && socketDesc->iControllerRelativeSocket == aControllerRelativeSocket) |
|
78 return i; |
|
79 if (mediaType == EInvalidMedia) // socket unassigned ? |
|
80 break; |
|
81 } |
|
82 if (i == KMaxPBusSockets) |
|
83 return KErrNoMemory; |
|
84 |
|
85 // assign a new local socket for this controller relative socket number & media type |
|
86 socketDesc->iMediaType = aMediaType; |
|
87 socketDesc->iControllerRelativeSocket = aControllerRelativeSocket; |
|
88 |
|
89 return i; |
|
90 } |
|
91 |
|
92 TBusLocalDrive& LocalDrives::GetLocalDrive(TInt aDrive) |
|
93 // |
|
94 // Export localdrives |
|
95 // |
|
96 { |
|
97 __ASSERT_DEBUG(aDrive>=0 && aDrive<KMaxDrives,Fault(EGetLocalDrive1)); |
|
98 __ASSERT_DEBUG(iMapping[aDrive]!=KDriveInvalid && iMapping[aDrive]<KMaxLocalDrives,Fault(EGetLocalDrive2)); |
|
99 return(iLocalDrives[iMapping[aDrive]]); |
|
100 } |
|
101 |
|
102 |
|
103 TInt LocalDrives::GetLocalDriveNumber(TBusLocalDrive* aLocDrv) |
|
104 // |
|
105 // Get the local drive number for the local drive object passed in |
|
106 // |
|
107 { |
|
108 for(TInt i=0;i<KMaxLocalDrives;++i) |
|
109 if(&iLocalDrives[i]==aLocDrv) |
|
110 return(i); |
|
111 return(KDriveInvalid); |
|
112 } |
|
113 |
|
114 |
|
115 |
|
116 CExtProxyDrive* LocalDrives::GetProxyDrive(TInt aDrive) |
|
117 { |
|
118 __ASSERT_DEBUG(aDrive>=0 && aDrive<KMaxDrives,Fault(EGetProxyDriveMapping1)); |
|
119 __ASSERT_DEBUG(iMapping[aDrive]!=KDriveInvalid && iMapping[aDrive]>=KMaxLocalDrives && iMapping[aDrive]<KMaxDrives,Fault(EGetProxyDriveMapping1)); |
|
120 return iProxyDriveMapping[iMapping[aDrive]-KMaxLocalDrives]; |
|
121 } |
|
122 |
|
123 |
|
124 LOCAL_C TBool DriveNumberIsInRange(TInt aDrive) |
|
125 { |
|
126 |
|
127 return((aDrive>=0) && (aDrive<KMaxDrives)); |
|
128 } |
|
129 |
|
130 |
|
131 TBool LocalDrives::IsValidDriveMapping(TInt aDrive) |
|
132 // |
|
133 // Is the drive number to local drive mapping valid? |
|
134 // |
|
135 { |
|
136 |
|
137 __ASSERT_DEBUG(DriveNumberIsInRange(aDrive),Fault(EIsValidDriveMapping)); |
|
138 return(iMapping[aDrive]!=KDriveInvalid); |
|
139 } |
|
140 |
|
141 |
|
142 TInt LocalDrives::DriveNumberToLocalDriveNumber(TInt aDrive) |
|
143 // |
|
144 // Get the mapping from drive number to local drive |
|
145 // |
|
146 { |
|
147 return(iMapping[aDrive]); |
|
148 } |
|
149 |
|
150 |
|
151 TInt LocalDrives::SetDriveMappingL(CFsRequest* aRequest) |
|
152 // |
|
153 // |
|
154 // |
|
155 { |
|
156 |
|
157 __PRINT(_L("LocalDrives::SetDriveMappingL()")); |
|
158 if (iMappingSet) |
|
159 return(KErrAccessDenied); |
|
160 |
|
161 TLocalDriveMappingInfoBuf mBuf; |
|
162 mBuf.FillZ(); |
|
163 aRequest->ReadL(KMsgPtr0,mBuf); |
|
164 TLocalDriveMappingInfo& ldmi=mBuf(); |
|
165 |
|
166 if (ldmi.iOperation==TLocalDriveMappingInfo::ESwapIntMappingAndSet) |
|
167 { |
|
168 // Only the 1st two entries of the mapping table are valid - holding the drive numbers to be swapped |
|
169 TInt r=KErrNone; |
|
170 if (DriveNumberIsInRange(ldmi.iDriveMapping[0]) && DriveNumberIsInRange(ldmi.iDriveMapping[1])) |
|
171 r=SwapDriveMapping(ldmi.iDriveMapping[0],ldmi.iDriveMapping[1]); |
|
172 iMappingSet=ETrue; |
|
173 return(r); |
|
174 } |
|
175 |
|
176 // That just leaves EWriteMappingsAndSet and EWriteMappingsNoSet |
|
177 for (TInt i=0;i<KMaxLocalDrives;++i) |
|
178 { |
|
179 TInt driveLetter=ldmi.iDriveMapping[i]; |
|
180 if(driveLetter==KDriveInvalid) |
|
181 continue; |
|
182 if ( !DriveNumberIsInRange(driveLetter)) |
|
183 { |
|
184 // invalid mapping list passed in, clear all mappings set up |
|
185 for(TInt j=0;j<KMaxDrives;j++) |
|
186 iMapping[j] = KDriveInvalid; |
|
187 return(KErrArgument); |
|
188 } |
|
189 __PRINT2(_L("drive letter %d -> local drive %d"),driveLetter,i); |
|
190 |
|
191 // If this mapping (letter -> localdrive) is already set then |
|
192 // this must be a multislot device. Save this mapping as an |
|
193 // alternative mapping (by storing it in iReverseMapping) |
|
194 if(iMapping[driveLetter] != KDriveInvalid) |
|
195 { |
|
196 iIsMultiSlotDrive[driveLetter] = ETrue; |
|
197 } |
|
198 // first time we've seen this drive letter |
|
199 iMapping[driveLetter]=i; |
|
200 // following mapping is used when we want to swap back again. |
|
201 iReverseMapping[i]=driveLetter; |
|
202 } |
|
203 |
|
204 InitDriveMapping(); |
|
205 if (ldmi.iOperation==TLocalDriveMappingInfo::EWriteMappingsAndSet) |
|
206 iMappingSet=ETrue; |
|
207 return(KErrNone); |
|
208 } |
|
209 |
|
210 // Changes here must be reflected in SwapDriveMapping() |
|
211 void LocalDrives::InitDriveMapping() |
|
212 { |
|
213 __PRINT(_L("InitDriveMapping()")); |
|
214 TDriveInfoV1Buf driveInfo; |
|
215 TInt r=UserHal::DriveInfo(driveInfo); |
|
216 __ASSERT_ALWAYS(r==KErrNone,Fault(EInitDriveMappingDriveInfo)); |
|
217 |
|
218 // initialise the local drives |
|
219 TInt i; |
|
220 for(i=0;i<KMaxLocalDrives;++i) |
|
221 { |
|
222 TInt driveNo = iReverseMapping[i]; |
|
223 if(driveNo!=KDriveInvalid) |
|
224 { |
|
225 r=iLocalDrives[i].Connect(i,TheDrives[driveNo].iChanged); |
|
226 __ASSERT_ALWAYS(r==KErrNone,Fault(EInitConnectLocalDrive)); |
|
227 __PRINT2(_L("connect to locdrv %d using drive %d"),i,driveNo); |
|
228 //If this is a multislot then we need to set the iChanged to True |
|
229 //So that we are mapped to the correct drive when we're booted. |
|
230 if(iIsMultiSlotDrive[driveNo]) |
|
231 { |
|
232 TheDrives[driveNo].iChanged = ETrue; |
|
233 } |
|
234 if (driveInfo().iDriveName[i].Length()==0) |
|
235 continue; |
|
236 TheDriveNames[driveNo]=driveInfo().iDriveName[i].Alloc(); |
|
237 __ASSERT_ALWAYS(TheDriveNames[driveNo],Fault(EInitCreateDriveName)); |
|
238 } |
|
239 } |
|
240 |
|
241 TInt drivesPerSocket[KMaxPBusSockets]; |
|
242 Mem::FillZ(&drivesPerSocket,KMaxPBusSockets*sizeof(TInt)); |
|
243 TInt nSockets=driveInfo().iTotalSockets; |
|
244 for(i=0;i<KMaxLocalDrives;++i) |
|
245 { |
|
246 TInt socket; |
|
247 if(iLocalDrives[i].Handle()==0 || !iLocalDrives[i].IsRemovable(socket)) |
|
248 { |
|
249 TInt driveNo = iReverseMapping[i]; |
|
250 // Non-removable drive so shouldn't be listed as a Multislot drive |
|
251 // Drives such as composite drives may have been |
|
252 // set to true as the drive letter had been encountered before. |
|
253 // make sure those drives are set to false here. |
|
254 iIsMultiSlotDrive[driveNo]=EFalse; |
|
255 continue; |
|
256 } |
|
257 __ASSERT_ALWAYS(socket>=0 && socket<nSockets,Fault(EInitDriveMappingSocketNo)); |
|
258 TInt drv=GetDriveFromLocalDrive(i); |
|
259 // get local socket number |
|
260 TMediaDevice mediaDevice = iLocalDrives[i].MediaDevice(); |
|
261 TInt localSocket = LocalDrives::GetLocalSocket(socket, mediaDevice); |
|
262 __ASSERT_ALWAYS(localSocket>=0 && localSocket<KMaxPBusSockets,Fault(EInitDriveMappingSocketNo)); |
|
263 __PRINT4(_L("InitDriveMapping(), i = %d, , mediaDevice = %d, socket = %d, localSocket = %d"), |
|
264 i, mediaDevice, socket, localSocket); |
|
265 __PRINT2(_L("drv = %d (%C:)"), drv, 'A' + drv); |
|
266 |
|
267 TSocketDesc& socketDesc = iSocketDescs[localSocket]; |
|
268 if(drv!=KDriveInvalid) |
|
269 { |
|
270 TInt& count = drivesPerSocket[localSocket]; |
|
271 // setup up socket to drive mapping |
|
272 __ASSERT_ALWAYS(count < KMaxDrivesPerSocket,Fault(ETooManyDrivesPerSocket)); |
|
273 socketDesc.iDriveNumbers[count]=drv; |
|
274 if(count==0) |
|
275 { |
|
276 // setup media change notifier if this is first local drive found on socket |
|
277 CNotifyMediaChange* pN=new CNotifyMediaChange(&iLocalDrives[i],localSocket); |
|
278 __ASSERT_ALWAYS(pN!=NULL,Fault(EInitCreateMediaChangeNotifier)); |
|
279 __PRINT2(_L("created CNotifyMediaChange media 0x%x using local drive %d"), localSocket,i); |
|
280 socketDesc.iMediaChanges = pN; |
|
281 CActiveSchedulerFs::Add(pN); |
|
282 pN->RunL(); |
|
283 } |
|
284 ++count; |
|
285 } |
|
286 } |
|
287 } |
|
288 |
|
289 TInt LocalDrives::InitProxyDrive(CFsRequest* aRequest) |
|
290 { |
|
291 __PRINT(_L("LocalDrives::InitProxyDrive")); |
|
292 |
|
293 TInt drive = aRequest->Message().Int0() ; |
|
294 |
|
295 if (drive < 0 || drive >= KMaxDrives) |
|
296 return KErrArgument; |
|
297 |
|
298 if (drive!=EDriveZ && iMapping[drive]!=KDriveInvalid) |
|
299 return KErrInUse; // Z is special case for composite |
|
300 |
|
301 TFullName extname; |
|
302 aRequest->ReadL(KMsgPtr1,extname); |
|
303 |
|
304 // leave info thing for now |
|
305 CExtProxyDriveFactory* pF = GetProxyDriveFactory(extname); |
|
306 if (!pF) |
|
307 return KErrArgument; // that extension has not been added |
|
308 FsThreadManager::LockDrive(drive); |
|
309 // find a free mapping to place this drive into |
|
310 TInt i; |
|
311 for (i=0; i <KMaxProxyDrives; i++) |
|
312 { |
|
313 if (!iProxyDriveMapping[i]) |
|
314 break; |
|
315 } |
|
316 FsThreadManager::UnlockDrive(drive); |
|
317 if (i==KMaxProxyDrives) |
|
318 return KErrInUse; // there are no free proxy drives left |
|
319 |
|
320 // Create the actual proxy drive... |
|
321 CProxyDrive* pD = NULL; |
|
322 TInt r = pF->CreateProxyDrive(pD, NULL); |
|
323 __ASSERT_ALWAYS(r == KErrNone, User::Panic(_L("CreateProxyDrive Error"), r)); |
|
324 __ASSERT_ALWAYS(pD != NULL, User::Panic(_L("CreateProxyDrive returned NULL"), -999)); |
|
325 |
|
326 iMapping[drive] = i+KMaxLocalDrives; |
|
327 |
|
328 aRequest->SetDrive(&TheDrives[drive]); |
|
329 aRequest->SetScratchValue((TUint)pD); |
|
330 |
|
331 return KErrNone; |
|
332 } |
|
333 |
|
334 TInt LocalDrives::MountProxyDrive(CFsRequest* aRequest) |
|
335 { |
|
336 CExtProxyDrive* pProxyDrive = (CExtProxyDrive*)aRequest->ScratchValue(); |
|
337 __ASSERT_ALWAYS(pProxyDrive != NULL, User::Panic(_L("MountProxyDrive has NULL proxy extension class"), -999)); |
|
338 |
|
339 TInt driveNumber = aRequest->Drive()->DriveNumber(); |
|
340 |
|
341 |
|
342 TInt proxyDriveNo = iMapping[driveNumber] - KMaxLocalDrives; |
|
343 FsThreadManager::LockDrive(driveNumber); |
|
344 iProxyDriveMapping[proxyDriveNo] = pProxyDrive; |
|
345 pProxyDrive->SetDriveNumber(driveNumber); |
|
346 FsThreadManager::UnlockDrive(driveNumber); |
|
347 // |
|
348 // Pass initialisation information onto the extension to allow it to initialise |
|
349 // |
|
350 TInt err = pProxyDrive->SetInfo(aRequest->Message(), |
|
351 (TAny*)aRequest->Message().Ptr2(), |
|
352 (TAny*)aRequest->Message().Ptr3()); |
|
353 if (err != KErrNone) |
|
354 { |
|
355 // |
|
356 // If we fail to initialise the extension, then close the drive (destroying the thread) |
|
357 // and remove the mapping so we can attempt to mount again in the future. |
|
358 // |
|
359 FsThreadManager::LockDrive(driveNumber); |
|
360 FsThreadManager::CloseDrive(driveNumber); |
|
361 ClearProxyDriveMapping(driveNumber); |
|
362 FsThreadManager::UnlockDrive(driveNumber); |
|
363 return err; |
|
364 } |
|
365 |
|
366 return(iMapping[driveNumber]); |
|
367 } |
|
368 |
|
369 TBool LocalDrives::IsProxyDrive(TInt aDrive) |
|
370 { |
|
371 __ASSERT_ALWAYS(aDrive>=0 && aDrive<KMaxDrives,Fault(EIsProxyDrive)); |
|
372 return (iMapping[aDrive] >= KMaxLocalDrives); |
|
373 } |
|
374 |
|
375 TBool LocalDrives::IsProxyDriveInUse(CExtProxyDriveFactory* aDevice) |
|
376 { |
|
377 for (TInt i=0; i < KMaxProxyDrives; i++) |
|
378 if (iProxyDriveMapping[i] && (iProxyDriveMapping[i]->FactoryP() == aDevice)) |
|
379 return(ETrue); |
|
380 |
|
381 return(EFalse); |
|
382 } |
|
383 |
|
384 void LocalDrives::ClearProxyDriveMapping(TInt aDrive) |
|
385 { |
|
386 __ASSERT_ALWAYS(aDrive>=0 && aDrive<KMaxDrives,Fault(EClearProxyDriveMapping1)); |
|
387 __ASSERT_DEBUG(iMapping[aDrive]>= KMaxLocalDrives && iProxyDriveMapping[iMapping[aDrive]-KMaxLocalDrives],Fault(EClearProxyDriveMapping2)); |
|
388 TInt idx = iMapping[aDrive]-KMaxLocalDrives; |
|
389 delete iProxyDriveMapping[idx]; |
|
390 iProxyDriveMapping[idx] = NULL; |
|
391 iMapping[aDrive] = KDriveInvalid; |
|
392 } |
|
393 |
|
394 TInt LocalDrives::SetupMediaChange(TInt aDrive) |
|
395 { |
|
396 CExtProxyDrive* pProxyDrive = LocalDrives::GetProxyDrive(aDrive); |
|
397 __ASSERT_ALWAYS(pProxyDrive != NULL,User::Panic(_L("SetupMediaChange - pProxyDrive == NULL"), ESetupMediaChange)); |
|
398 |
|
399 return pProxyDrive->SetupMediaChange(); |
|
400 } |
|
401 |
|
402 void LocalDrives::NotifyChangeCancel(TInt aDrive) |
|
403 { |
|
404 CExtProxyDrive* pProxyDrive = LocalDrives::GetProxyDrive(aDrive); |
|
405 __ASSERT_ALWAYS(pProxyDrive != NULL,User::Panic(_L("NotifyChangeCancel - pProxyDrive == NULL"), ECancelNotifyChange)); |
|
406 |
|
407 pProxyDrive->NotifyChangeCancel(); |
|
408 } |
|
409 |
|
410 TInt LocalDrives::SwapDriveMapping(TInt aFirstDrive,TInt aSecondDrive) |
|
411 { |
|
412 |
|
413 __PRINT(_L("SwapDriveMapping()")); |
|
414 TInt firstLocalDrv=iMapping[aFirstDrive]; |
|
415 TInt secondLocalDrv=iMapping[aSecondDrive]; |
|
416 |
|
417 // First, check this swap doesn't affect removable drives |
|
418 TInt socket; |
|
419 if (iLocalDrives[firstLocalDrv].Handle()!=0 && iLocalDrives[firstLocalDrv].IsRemovable(socket)) |
|
420 return(KErrAccessDenied); |
|
421 if (iLocalDrives[secondLocalDrv].Handle()!=0 && iLocalDrives[secondLocalDrv].IsRemovable(socket)) |
|
422 return(KErrAccessDenied); |
|
423 |
|
424 // Now swap the mappings over |
|
425 iMapping[aFirstDrive]=secondLocalDrv; |
|
426 iMapping[aSecondDrive]=firstLocalDrv; |
|
427 |
|
428 iReverseMapping[firstLocalDrv]=aSecondDrive; |
|
429 iReverseMapping[secondLocalDrv]=aFirstDrive; |
|
430 |
|
431 // Finally, swap the drive names over |
|
432 HBufC* drvName=TheDriveNames[aSecondDrive]; |
|
433 TheDriveNames[aSecondDrive]=TheDriveNames[aFirstDrive]; |
|
434 TheDriveNames[aFirstDrive]=drvName; |
|
435 return(KErrNone); |
|
436 } |
|
437 |
|
438 void LocalDrives::CompleteNotifications(TInt aSocket) |
|
439 // |
|
440 // |
|
441 // |
|
442 { |
|
443 __ASSERT_DEBUG(aSocket>=0 && aSocket<KMaxPBusSockets && iSocketDescs[aSocket].iDriveNumbers[0]!=KDriveInvalid,Fault(ECompleteNotifSocketNo)); |
|
444 TInt i=0; |
|
445 |
|
446 // In a data-paging environment, the local media subsytem will only update the TDrive::iChanged flag |
|
447 // for drives which have a CNotifyMediaChange object, i.e. for drives which call TBusLocalDrive::NotifyChange(). |
|
448 // Since we only create ONE CNotifyMediaChange object for each socket (no matter how many partitions/local drives |
|
449 // are associated with that socket), we need to propagate the TDrive::iChanged flag to all drives on the socket. |
|
450 TBool changedFlag = TheDrives[iSocketDescs[aSocket].iDriveNumbers[0]].IsChanged(); |
|
451 |
|
452 while(i<KMaxDrivesPerSocket && iSocketDescs[aSocket].iDriveNumbers[i]!=KDriveInvalid) |
|
453 { |
|
454 TheDrives[iSocketDescs[aSocket].iDriveNumbers[i]].SetChanged(changedFlag); |
|
455 CompleteDriveNotifications(iSocketDescs[aSocket].iDriveNumbers[i++]); |
|
456 } |
|
457 } |
|
458 |
|
459 void LocalDrives::CompleteDriveNotifications(TInt aDrive) |
|
460 // |
|
461 // |
|
462 // |
|
463 { |
|
464 // If the drive is hung, then don't complete any disk change |
|
465 // notifications until the request causing the hang completes |
|
466 if(FsThreadManager::IsDriveHung(aDrive)) |
|
467 FsThreadManager::SetMediaChangePending(aDrive); |
|
468 else |
|
469 { |
|
470 FsNotify::DiskChange(aDrive); |
|
471 |
|
472 #ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION |
|
473 if(FsNotificationManager::IsInitialised()) |
|
474 { |
|
475 __PRINT3(_L("LocalDrives::CompleteDriveNotifications() Initialised=%d, Count=%d, Drive=%d"),FsNotificationManager::IsInitialised(),FsNotificationManager::Count(), aDrive); |
|
476 TBuf<2> driveDes; |
|
477 driveDes.Append((TChar)aDrive+(TChar)'A'); |
|
478 driveDes.Append((TChar)':'); |
|
479 FsNotificationManager::HandleChange(NULL,driveDes,TFsNotification::EMediaChange); |
|
480 } |
|
481 #endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION |
|
482 |
|
483 //If this is a multislot device we should update mappings here. |
|
484 TheDrives[aDrive].MultiSlotDriveCheck(); |
|
485 } |
|
486 } |
|
487 |
|
488 TInt LocalDrives::GetDriveFromLocalDrive(TInt aLocDrv) |
|
489 // |
|
490 // |
|
491 // |
|
492 { |
|
493 return iReverseMapping[aLocDrv]; |
|
494 } |
|
495 |
|
496 |
|
497 CNotifyMediaChange::CNotifyMediaChange(RLocalDrive* aDrive,TInt aSocketNo) |
|
498 // |
|
499 // Constructor |
|
500 // |
|
501 : CActive(EPriorityHigh), iDrive(aDrive), iSocket(aSocketNo) |
|
502 {} |
|
503 |
|
504 void CNotifyMediaChange::RunL() |
|
505 // |
|
506 // Notification that a card has been mounted/removed |
|
507 // |
|
508 { |
|
509 LocalDrives::CompleteNotifications(iSocket); |
|
510 iDrive->NotifyChange(&iStatus); |
|
511 SetActive(); |
|
512 } |
|
513 |
|
514 |
|
515 CExtNotifyMediaChange::CExtNotifyMediaChange(CExtProxyDrive* aDrive) |
|
516 // |
|
517 // Constructor |
|
518 // |
|
519 : CActive(EPriorityHigh), |
|
520 iDrive(aDrive), |
|
521 iPtr((TUint8*)&TheDrives[aDrive->DriveNumber()].iChanged,sizeof(TBool)) |
|
522 { |
|
523 } |
|
524 |
|
525 |
|
526 CExtNotifyMediaChange* CExtNotifyMediaChange::NewL(CExtProxyDrive* aDrive) |
|
527 { |
|
528 CExtNotifyMediaChange* pSelf = new(ELeave) CExtNotifyMediaChange(aDrive); |
|
529 |
|
530 CleanupStack::PushL(pSelf); |
|
531 pSelf->ConstructL(); |
|
532 CleanupStack::Pop(); |
|
533 |
|
534 return pSelf; |
|
535 } |
|
536 |
|
537 void CExtNotifyMediaChange::ConstructL() |
|
538 { |
|
539 CActiveSchedulerFs::Add(this); |
|
540 |
|
541 TRAPD(err, RunL()); |
|
542 if(err != KErrNone) |
|
543 Deque(); |
|
544 |
|
545 User::LeaveIfError(err); |
|
546 } |
|
547 |
|
548 CExtNotifyMediaChange::~CExtNotifyMediaChange() |
|
549 { |
|
550 Cancel(); |
|
551 } |
|
552 |
|
553 void CExtNotifyMediaChange::RequestL() |
|
554 { |
|
555 if (!IsActive()) |
|
556 { |
|
557 User::LeaveIfError(iDrive->NotifyChange(iPtr, &iStatus)); |
|
558 SetActive(); |
|
559 } |
|
560 } |
|
561 |
|
562 void CExtNotifyMediaChange::DoCancel() |
|
563 { |
|
564 iDrive->NotifyChangeCancel(); |
|
565 } |
|
566 |
|
567 void CExtNotifyMediaChange::RunL() |
|
568 { |
|
569 if(iStatus==KErrDisconnected || iStatus==KErrCancel) |
|
570 return; |
|
571 |
|
572 TInt driveNum = iDrive->DriveNumber(); |
|
573 LocalDrives::CompleteDriveNotifications(driveNum); |
|
574 |
|
575 /* NOTE: We need SetChanged here though the iChanged variable is set in the MSC, since the cache is not getting cleared |
|
576 (inside the CompleteDriveNotifications call) during the initial first notification */ |
|
577 TheDrives[driveNum].SetChanged(ETrue); |
|
578 |
|
579 if(iStatus != KErrNotSupported) |
|
580 { |
|
581 RequestL(); |
|
582 } |
|
583 } |
|
584 |
|
585 |
|
586 |