|
1 // Copyright (c) 2008-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 /** |
|
17 @file |
|
18 @internalTechnology |
|
19 */ |
|
20 |
|
21 #include <e32std.h> |
|
22 #include <f32file.h> |
|
23 |
|
24 #include "rusbhostmsdevice.h" |
|
25 #include "debug.h" |
|
26 #include "msgservice.h" |
|
27 |
|
28 _LIT(KFileSystem, "FAT"); |
|
29 |
|
30 TVersion RUsbHostMsDevice::Version() const |
|
31 { |
|
32 __FNLOG("RUsbHostMsDevice::Version"); |
|
33 return(TVersion(KUsbHostMsSrvMajorVersionNumber, |
|
34 KUsbHostMsSrvMinorVersionNumber, |
|
35 KUsbHostMsSrvBuildVersionNumber)); |
|
36 } |
|
37 |
|
38 |
|
39 TInt RUsbHostMsDevice::StartServer() |
|
40 { |
|
41 __FNLOG("RUsbHostMsDevice::StartServer"); |
|
42 TInt r; |
|
43 RProcess server; |
|
44 |
|
45 const TUid KServerUid3={0x10286A83}; |
|
46 const TUidType serverUid(KNullUid,KNullUid,KServerUid3); |
|
47 |
|
48 // Create the server process |
|
49 if((r=server.Create(KUsbHostMsServerName,KNullDesC,serverUid)) != KErrNone) |
|
50 { |
|
51 __PRINT1(_L("Server process create = %d\n"), r); |
|
52 return r; |
|
53 } |
|
54 |
|
55 // Create the rendezvous request with the server process |
|
56 TRequestStatus stat; |
|
57 server.Rendezvous(stat); |
|
58 if (stat!=KRequestPending) |
|
59 { |
|
60 server.Kill(0); // If the outstanding request is not pending then kill the server |
|
61 } |
|
62 else |
|
63 { |
|
64 server.SetPriority(EPriorityHigh); |
|
65 server.Resume(); // start the server |
|
66 } |
|
67 |
|
68 // Test whether the process has ended and if it has ended, return how it ended. |
|
69 User::WaitForRequest(stat); |
|
70 r=(server.ExitType()==EExitPanic) ? KErrGeneral : stat.Int(); |
|
71 |
|
72 server.Close(); |
|
73 return r; |
|
74 } |
|
75 |
|
76 EXPORT_C RUsbHostMsDevice::RUsbHostMsDevice() |
|
77 { |
|
78 // Intentionally left blank |
|
79 } |
|
80 |
|
81 |
|
82 /** |
|
83 @internalAll |
|
84 @prototype |
|
85 |
|
86 Add the Mass Storage device to the MSC server. This API is asynchronous, upon |
|
87 completion one could find the number of logical units present in the added |
|
88 device by calling GetNumLun API. Calling the Remove API before completing this |
|
89 asynchronous API will complete the pending request notification with KErrCancel. |
|
90 |
|
91 @param aConfig [In] A constant reference object to |
|
92 THostMassStorageConfig containing the confiquration values of |
|
93 the massstorage device requested to add to the MSC |
|
94 @param aStatus [In] A reference to TRequestStatus to be used for asynchronous |
|
95 request completion |
|
96 */ |
|
97 EXPORT_C void RUsbHostMsDevice::Add(const THostMassStorageConfig& aConfig, TRequestStatus& aStatus) |
|
98 { |
|
99 __FNLOG("RUsbHostMsDevice::Add"); |
|
100 TInt err = KErrNone; |
|
101 |
|
102 err = CreateSession(KUsbHostMsServerName, Version(), 128, EIpcSession_GlobalSharable); |
|
103 |
|
104 // Being a transient server, the first session creation would fail with if |
|
105 // the server is not running |
|
106 if(err != KErrNone) |
|
107 { |
|
108 // Find whether the session creation failed because server was not |
|
109 // running |
|
110 if (err==KErrNotFound || err==KErrServerTerminated) |
|
111 { |
|
112 // Start the server |
|
113 err = StartServer(); |
|
114 if(err == KErrNone) |
|
115 { |
|
116 // Try session creation again |
|
117 err = CreateSession(KUsbHostMsServerName, Version(), 128, EIpcSession_GlobalSharable); |
|
118 } |
|
119 } |
|
120 } |
|
121 |
|
122 TRequestStatus* statusPtr = &aStatus; |
|
123 if(err == KErrNone) |
|
124 { |
|
125 // Create a session handle that can be passed via IPC to another process |
|
126 // (also being shared by other threads in the current process) |
|
127 err = ShareProtected(); |
|
128 if(err == KErrNone) |
|
129 { |
|
130 // synchronous call to register the interface |
|
131 TPckg<THostMassStorageConfig> pckg(aConfig); |
|
132 err = SendReceive(EUsbHostMsRegisterInterface, TIpcArgs(&pckg)); |
|
133 if(err != KErrNone) |
|
134 { |
|
135 User::RequestComplete(statusPtr, err); |
|
136 } |
|
137 else |
|
138 { |
|
139 // Asynchronous call to initialise the interface |
|
140 SendReceive(EUsbHostMsInitialiseInterface, TIpcArgs(NULL), aStatus); |
|
141 } |
|
142 } |
|
143 else |
|
144 { |
|
145 Close(); // Close the session handle |
|
146 __PRINT1(_L("Could not create a sharable session handle %d\n"), err); |
|
147 User::RequestComplete(statusPtr, err); |
|
148 } |
|
149 } |
|
150 else |
|
151 { |
|
152 // Check whether the error is in starting the server or in creating the |
|
153 // session |
|
154 __PRINT1(_L("Creating server/session failed with %d\n"), err); |
|
155 User::RequestComplete(statusPtr, err); |
|
156 } |
|
157 } |
|
158 |
|
159 |
|
160 /** |
|
161 @internalAll |
|
162 @prototype |
|
163 |
|
164 Remove the Mass Storage device from the MSC server. |
|
165 */ |
|
166 EXPORT_C void RUsbHostMsDevice::Remove() |
|
167 { |
|
168 // Note: Here, at present we use only the interface token. But we still take |
|
169 // THostMassStorageConfig as parameter for future needs |
|
170 __FNLOG("RUsbHostMsDevice::Remove"); |
|
171 _LIT(KUsbHostMsClientPanicCat, "usbhostmsclient"); |
|
172 |
|
173 TInt r = SendReceive(EUsbHostMsUnRegisterInterface); |
|
174 |
|
175 r = SendReceive(EUsbHostMsFinalCleanup); |
|
176 if(r != KErrNone) |
|
177 { |
|
178 User::Panic(KUsbHostMsClientPanicCat ,KErrCouldNotDisconnect); |
|
179 } |
|
180 Close(); // Close the session handle |
|
181 } |
|
182 |
|
183 |
|
184 /** |
|
185 @internalAll |
|
186 @prototype |
|
187 |
|
188 Get the number of logical units suppoted by the device. |
|
189 |
|
190 @param aNumLuns [Out] Outputs the number of logical units found in the |
|
191 added Mass Storage device. A value of 'n' represents there are |
|
192 'n' LUNs present in the device, where "n > 0" |
|
193 |
|
194 @return TInt |
|
195 */ |
|
196 EXPORT_C TInt RUsbHostMsDevice::GetNumLun(TUint32& aNumLuns) |
|
197 { |
|
198 __FNLOG("RUsbHostMsDevice::GetNumLun"); |
|
199 TPckg<TUint32> pckg(aNumLuns); |
|
200 return SendReceive(EUsbHostMsGetNumLun,TIpcArgs(&pckg)); |
|
201 } |
|
202 |
|
203 |
|
204 EXPORT_C TInt RUsbHostMsDevice::MountLun(TUint32 aLunId, TInt aDriveNum) |
|
205 { |
|
206 __FNLOG("RUsbHostMsDevice::MountLun"); |
|
207 RFs TheFs; |
|
208 TInt r = TheFs.Connect(); |
|
209 if(r == KErrNone) |
|
210 { |
|
211 TPckgBuf<TMassStorageUnitInfo> unitPkg; |
|
212 unitPkg().iLunID = aLunId; |
|
213 |
|
214 r = TheFs.MountProxyDrive(aDriveNum, _L("usbhostms"), &unitPkg, *this); |
|
215 if(r >= KErrNone) |
|
216 { |
|
217 r = TheFs.MountFileSystem(KFileSystem, aDriveNum); |
|
218 |
|
219 if(r != KErrNone && r != KErrNotReady && r != KErrCorrupt) |
|
220 { |
|
221 TheFs.DismountFileSystem(KFileSystem, aDriveNum); |
|
222 TheFs.DismountProxyDrive(aDriveNum); |
|
223 } |
|
224 } |
|
225 TheFs.Close(); |
|
226 } |
|
227 return r; |
|
228 } |
|
229 |
|
230 EXPORT_C TInt RUsbHostMsDevice::DismountLun(TInt aDriveNum) |
|
231 { |
|
232 __FNLOG("RUsbHostMsDevice::DismountLun"); |
|
233 RFs TheFs; |
|
234 TInt r; |
|
235 r = TheFs.Connect(); |
|
236 if(r == KErrNone) |
|
237 { |
|
238 r = TheFs.DismountFileSystem(KFileSystem, aDriveNum); |
|
239 if(r != KErrNone) |
|
240 { |
|
241 // dismount failed - attempt a forced dismount |
|
242 TRequestStatus stat; |
|
243 TheFs.NotifyDismount(aDriveNum, stat, EFsDismountForceDismount); |
|
244 User::WaitForRequest(stat); |
|
245 r = stat.Int(); |
|
246 } |
|
247 if(r == KErrNone) |
|
248 { |
|
249 r = TheFs.DismountProxyDrive(aDriveNum); |
|
250 } |
|
251 TheFs.Close(); |
|
252 } |
|
253 return r; |
|
254 } |