|
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 <e32base.h> |
|
22 #include <d32usbdi.h> |
|
23 |
|
24 #include <d32usbtransfers.h> |
|
25 #include "msctypes.h" |
|
26 #include "shared.h" |
|
27 #include "msgservice.h" |
|
28 #include "botmsctypes.h" |
|
29 #include "mprotocol.h" |
|
30 #include "mtransport.h" |
|
31 #include "cbulkonlytransport.h" |
|
32 #include "cusbhostmslogicalunit.h" |
|
33 #include "cusbhostmsdevice.h" |
|
34 #include "cusbmssuspendresume.h" |
|
35 |
|
36 #include "msdebug.h" |
|
37 #include "debug.h" |
|
38 |
|
39 |
|
40 CUsbHostMsDevice* CUsbHostMsDevice::NewL(THostMassStorageConfig& aConfig) |
|
41 { |
|
42 __MSFNSLOG |
|
43 CUsbHostMsDevice* r = new (ELeave) CUsbHostMsDevice(aConfig); |
|
44 CleanupStack::PushL(r); |
|
45 r->ConstructL(); |
|
46 CleanupStack::Pop(); |
|
47 return r; |
|
48 } |
|
49 |
|
50 void CUsbHostMsDevice::ConstructL() |
|
51 { |
|
52 __MSFNLOG |
|
53 iTimer = CPeriodic::NewL(CActive::EPriorityStandard); |
|
54 iTimerRunning = EFalse; |
|
55 } |
|
56 |
|
57 |
|
58 CUsbHostMsDevice::CUsbHostMsDevice(THostMassStorageConfig& aConfig) |
|
59 : iConfig(aConfig), |
|
60 iState(EReady) |
|
61 { |
|
62 __MSFNLOG |
|
63 } |
|
64 |
|
65 |
|
66 CUsbHostMsDevice::~CUsbHostMsDevice() |
|
67 { |
|
68 __MSFNLOG |
|
69 delete iTransport; |
|
70 delete iDeviceSuspendResume; |
|
71 if (iTimer && iTimerRunning) |
|
72 { |
|
73 iTimer->Cancel(); |
|
74 } |
|
75 delete iTimer; |
|
76 } |
|
77 |
|
78 |
|
79 MTransport* CUsbHostMsDevice::InitialiseTransportL(TTransportType aTransportId) |
|
80 { |
|
81 __MSFNLOG |
|
82 switch(aTransportId) |
|
83 { |
|
84 case BulkOnlyTransport: |
|
85 return CBulkOnlyTransport::NewL(iConfig.iInterfaceToken); |
|
86 default: |
|
87 // Panic; |
|
88 __HOSTPRINT(_L("Unsupported Transport class requested")); |
|
89 User::Leave(KErrNotSupported); |
|
90 return NULL; |
|
91 } |
|
92 } |
|
93 |
|
94 void CUsbHostMsDevice::InitialiseL(const RMessage2& aMessage) |
|
95 { |
|
96 __MSFNLOG |
|
97 iTransport = InitialiseTransportL((TTransportType) iConfig.iTransportId); |
|
98 TRAPD(r, iDeviceSuspendResume = CUsbMsIfaceSuspendResume::NewL(iTransport, this)); |
|
99 if(r != KErrNone) |
|
100 { |
|
101 delete iTransport; |
|
102 User::Leave(r); |
|
103 } |
|
104 iTransport->GetMaxLun(&iMaxLun, aMessage); |
|
105 } |
|
106 |
|
107 |
|
108 void CUsbHostMsDevice::UnInitialiseL() |
|
109 { |
|
110 __MSFNLOG |
|
111 StopTimer(); |
|
112 iLuList.RemoveAllLuL(); |
|
113 } |
|
114 |
|
115 |
|
116 TInt CUsbHostMsDevice::AddLunL(TLun aLun) |
|
117 { |
|
118 __MSFNLOG |
|
119 TInt r = KErrNone; |
|
120 StartTimer(); |
|
121 CUsbHostMsLogicalUnit* lu = CUsbHostMsLogicalUnit::NewL(aLun); |
|
122 CleanupStack::PushL(lu); |
|
123 |
|
124 TRAP(r, lu->InitialiseProtocolL(aLun, iConfig, *iTransport)); |
|
125 |
|
126 if (r == KErrNone) |
|
127 { |
|
128 TRAP(r, iLuList.AddLuL(lu)); |
|
129 } |
|
130 |
|
131 if (r != KErrNone) |
|
132 { |
|
133 CleanupStack::PopAndDestroy(lu); |
|
134 } |
|
135 else |
|
136 { |
|
137 CleanupStack::Pop(lu); |
|
138 } |
|
139 return r; |
|
140 } |
|
141 |
|
142 |
|
143 void CUsbHostMsDevice::RemoveLunL(TLun aLun) |
|
144 { |
|
145 __MSFNLOG |
|
146 if(iLuList.Count() <= 1) |
|
147 StopTimer(); |
|
148 iLuList.RemoveLuL(aLun); |
|
149 } |
|
150 |
|
151 |
|
152 void CUsbHostMsDevice::InitLunL(TLun aLun) |
|
153 { |
|
154 __MSFNLOG |
|
155 SetLunL(aLun); |
|
156 iLuList.GetLuL(aLun).InitL(); |
|
157 } |
|
158 |
|
159 |
|
160 void CUsbHostMsDevice::SuspendLunL(TLun aLun) |
|
161 { |
|
162 __MSFNLOG |
|
163 iLuList.GetLuL(aLun).ReadyToSuspend(); |
|
164 |
|
165 // check whether all the luns are suspended, if so then request usb |
|
166 // interface suspension to the transport layer |
|
167 for (TInt i = 0; i < iLuList.Count(); i++) |
|
168 { |
|
169 CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i); |
|
170 if (!lu.IsReadyToSuspend() && lu.IsConnected()) |
|
171 return; |
|
172 } |
|
173 |
|
174 for (TInt i = 0; i < iLuList.Count(); i++) |
|
175 { |
|
176 CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i); |
|
177 SetLunL(lu.Lun()); |
|
178 lu.SuspendL(); |
|
179 } |
|
180 |
|
181 StopTimer(); |
|
182 iDeviceSuspendResume->Suspend(); |
|
183 iState = ESuspended; |
|
184 } |
|
185 |
|
186 |
|
187 void CUsbHostMsDevice::Resume(TRequestStatus& aStatus) |
|
188 { |
|
189 __MSFNLOG |
|
190 if (iState == ESuspended) |
|
191 { |
|
192 StartTimer(); |
|
193 iDeviceSuspendResume->Resume(aStatus); |
|
194 } |
|
195 } |
|
196 |
|
197 |
|
198 TLun CUsbHostMsDevice::GetAndSetLunL(const RMessage2& aMessage) |
|
199 { |
|
200 __MSFNLOG |
|
201 // Subssessions need a positive value to store in the handles. We represent Luns as LunId+1 |
|
202 // We represent LunId in MSC from 0 to MaxLun-1 as represented in BOT so subtract 1 from the Id |
|
203 // received from RMessage |
|
204 |
|
205 TInt lun = aMessage.Int3() - 1; |
|
206 if (lun < 0) |
|
207 { |
|
208 User::Leave(KErrArgument); |
|
209 } |
|
210 SetLunL(static_cast<TLun>(lun)); |
|
211 return static_cast<TLun>(lun); |
|
212 } |
|
213 |
|
214 |
|
215 CUsbHostMsLogicalUnit& CUsbHostMsDevice::GetLuL(TInt aLunNum) const |
|
216 { |
|
217 return iLuList.GetLuL(aLunNum); |
|
218 } |
|
219 |
|
220 void CUsbHostMsDevice::SetLunL(TLun aLun) |
|
221 { |
|
222 __MSFNLOG |
|
223 if (aLun <= iMaxLun) |
|
224 { |
|
225 __HOSTPRINT1(_L("SetLun %d"), aLun); |
|
226 iTransport->SetLun(aLun); |
|
227 CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(aLun); |
|
228 if (lu.IsReadyToSuspend()) |
|
229 { |
|
230 lu.CancelReadyToSuspend(); |
|
231 } |
|
232 } |
|
233 } |
|
234 |
|
235 /** |
|
236 Starts timer to periodically check LUN. If the timer is not yet running then |
|
237 start it. |
|
238 */ |
|
239 void CUsbHostMsDevice::StartTimer() |
|
240 { |
|
241 __MSFNLOG |
|
242 if (!iTimerRunning) |
|
243 { |
|
244 // Period of the LUN Ready check |
|
245 const TTimeIntervalMicroSeconds32 KInterval = iConfig.iStatusPollingInterval * 1000 * 1000; |
|
246 TCallBack callback(TimerCallback, this); |
|
247 __HOSTPRINT(_L("Starting timer")); |
|
248 iTimer->Start(KInterval, KInterval, callback); |
|
249 iTimerRunning = ETrue; |
|
250 } |
|
251 } |
|
252 |
|
253 |
|
254 /** |
|
255 Ensure that the Timer is stopped |
|
256 */ |
|
257 void CUsbHostMsDevice::StopTimer() |
|
258 { |
|
259 __MSFNLOG |
|
260 if (iTimer && iTimerRunning) |
|
261 { |
|
262 __HOSTPRINT(_L("Stopping timer")); |
|
263 if (iTimer->IsActive()) |
|
264 { |
|
265 iTimer->Cancel(); |
|
266 } |
|
267 iTimerRunning = EFalse; |
|
268 } |
|
269 } |
|
270 |
|
271 /** |
|
272 A static wrapper for the DoLunReadyCheckEvent member function for use as a timer |
|
273 callback function. |
|
274 |
|
275 @param obj 'this' pointer |
|
276 @return not used in CPeriodic callback (see TCallback) |
|
277 */ |
|
278 TInt CUsbHostMsDevice::TimerCallback(TAny* obj) |
|
279 { |
|
280 __MSFNSLOG |
|
281 CUsbHostMsDevice* device = static_cast<CUsbHostMsDevice*>(obj); |
|
282 TRAPD(err, device->DoLunReadyCheckEventL()); |
|
283 return err; |
|
284 } |
|
285 |
|
286 void CUsbHostMsDevice::DoLunReadyCheckEventL() |
|
287 { |
|
288 __MSFNLOG |
|
289 TInt err; |
|
290 for (TInt i = 0; i < iLuList.Count(); i++) |
|
291 { |
|
292 CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i); |
|
293 SetLunL(lu.Lun()); |
|
294 TRAP(err, lu.DoLunReadyCheckL()); |
|
295 } |
|
296 } |
|
297 |
|
298 void CUsbHostMsDevice::DoHandleRemoteWakeupL() |
|
299 { |
|
300 __MSFNLOG |
|
301 DoResumeLogicalUnitsL(); |
|
302 DoLunReadyCheckEventL(); // For remote wakeup we do not wait for timer to expire |
|
303 |
|
304 // check whether all the luns are suspended, if so then request usb |
|
305 // interface suspension to the transport layer |
|
306 for (TInt i = 0; i < iLuList.Count(); i++) |
|
307 { |
|
308 CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i); |
|
309 // Has any of the logical units have got its state changed? |
|
310 if ( (lu.IsReadyToSuspend() && !lu.IsConnected()) || |
|
311 (!lu.IsReadyToSuspend() && lu.IsConnected()) ) |
|
312 { |
|
313 StartTimer(); // Now start the timer |
|
314 return; |
|
315 } |
|
316 } |
|
317 |
|
318 for (TInt i = 0; i < iLuList.Count(); i++) |
|
319 { |
|
320 CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i); |
|
321 SetLunL(lu.Lun()); |
|
322 lu.SuspendL(); |
|
323 } |
|
324 |
|
325 iDeviceSuspendResume->Suspend(); |
|
326 iState = ESuspended; |
|
327 } |
|
328 |
|
329 void CUsbHostMsDevice::DoResumeLogicalUnitsL() |
|
330 { |
|
331 __MSFNLOG |
|
332 for (TInt i = 0; i < iLuList.Count(); i++) |
|
333 { |
|
334 CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i); |
|
335 SetLunL(lu.Lun()); |
|
336 lu.ResumeL(); |
|
337 } |
|
338 } |
|
339 |
|
340 void CUsbHostMsDevice::ResumeCompletedL() |
|
341 { |
|
342 __MSFNLOG |
|
343 iState = EReady; |
|
344 DoResumeLogicalUnitsL(); |
|
345 } |