19 /** |
19 /** |
20 @file |
20 @file |
21 @internalTechnology |
21 @internalTechnology |
22 */ |
22 */ |
23 |
23 |
|
24 #include <e32std.h> |
|
25 #include "mtransport.h" |
|
26 #include "mprotocol.h" |
|
27 #include "mldddevicestatenotification.h" |
|
28 #include "tbulkmm.h" |
|
29 |
|
30 #include "drivemanager.h" |
|
31 #include "cusbmassstoragecontroller.h" |
|
32 |
24 #include "cbulkonlytransport.h" |
33 #include "cbulkonlytransport.h" |
25 #include "cbulkonlytransportusbcldd.h" |
34 #include "cbulkonlytransportusbcldd.h" |
26 #include "usbmsshared.h" |
35 #include "smassstorage.h" |
27 #include "massstoragedebug.h" |
36 |
28 #include "cusbmassstorageserver.h" |
37 #include "OstTraceDefinitions.h" |
|
38 #ifdef OST_TRACE_COMPILER_IN_USE |
|
39 #include "cbulkonlytransportusbclddTraces.h" |
|
40 #endif |
|
41 |
|
42 |
29 |
43 |
30 #define InEndpoint EEndpoint1 |
44 #define InEndpoint EEndpoint1 |
31 #define OutEndpoint EEndpoint2 |
45 #define OutEndpoint EEndpoint2 |
32 |
46 |
33 //This value defined in USB Mass Storage Bulk Only Transrt spec and not supposed to be changed |
47 //This value defined in USB Mass Storage Bulk Only Transrt spec and not supposed to be changed |
34 LOCAL_D const TInt KRequiredNumberOfEndpoints = 2; // in addition to endpoint 0. |
48 static const TInt KRequiredNumberOfEndpoints = 2; // in addition to endpoint 0. |
35 |
49 |
36 LOCAL_D const TInt KUsbNumInterfacesOffset = 4; |
50 static const TInt KUsbNumInterfacesOffset = 4; |
37 |
51 |
38 //////////////////////////////////// |
52 //////////////////////////////////// |
39 /** |
53 /** |
40 Called by CBulkOnlyTransportUsbcLdd to create an instance of CControlInterfaceUsbcLdd |
54 Called by CBulkOnlyTransportUsbcLdd to create an instance of CControlInterfaceUsbcLdd |
41 |
55 |
42 @param aParent reference to the CBulkOnlyTransportUsbcLdd |
56 @param aParent reference to the CBulkOnlyTransportUsbcLdd |
43 */ |
57 */ |
44 |
58 |
45 |
59 |
46 CControlInterfaceUsbcLdd* CControlInterfaceUsbcLdd::NewL(CBulkOnlyTransportUsbcLdd& aParent) |
60 CControlInterfaceUsbcLdd* CControlInterfaceUsbcLdd::NewL(CBulkOnlyTransportUsbcLdd& aParent) |
47 { |
61 { |
48 CControlInterfaceUsbcLdd* self = new(ELeave) CControlInterfaceUsbcLdd(aParent); |
62 CControlInterfaceUsbcLdd* self = new(ELeave) CControlInterfaceUsbcLdd(aParent); |
49 CleanupStack::PushL(self); |
63 CleanupStack::PushL(self); |
50 self->ConstructL(); |
64 self->ConstructL(); |
51 CActiveScheduler::Add(self); |
65 CActiveScheduler::Add(self); |
52 CleanupStack::Pop(); |
66 CleanupStack::Pop(); |
53 return self; |
67 return self; |
54 } |
68 } |
55 |
69 |
56 |
70 |
57 void CControlInterfaceUsbcLdd::ConstructL() |
71 void CControlInterfaceUsbcLdd::ConstructL() |
58 { |
72 { |
59 } |
73 } |
60 |
74 |
61 |
75 |
62 /** |
76 /** |
63 c'tor |
77 c'tor |
64 |
78 |
65 @param aParent reference to the CBulkOnlyTransportUsbcLdd |
79 @param aParent reference to the CBulkOnlyTransportUsbcLdd |
66 */ |
80 */ |
67 CControlInterfaceUsbcLdd::CControlInterfaceUsbcLdd(CBulkOnlyTransportUsbcLdd& aParent) |
81 CControlInterfaceUsbcLdd::CControlInterfaceUsbcLdd(CBulkOnlyTransportUsbcLdd& aParent) |
68 :CActive(EPriorityStandard), |
82 :CActive(EPriorityStandard), |
69 iParent(aParent), |
83 iParent(aParent), |
70 iCurrentState(ENone) |
84 iCurrentState(ENone) |
71 { |
85 { |
72 } |
86 } |
73 |
87 |
74 |
88 |
75 /** |
89 /** |
76 d'tor |
90 d'tor |
77 */ |
91 */ |
78 CControlInterfaceUsbcLdd::~CControlInterfaceUsbcLdd() |
92 CControlInterfaceUsbcLdd::~CControlInterfaceUsbcLdd() |
79 { |
93 { |
80 __FNLOG("CControlInterfaceUsbcLdd::~CControlInterfaceUsbcLdd "); |
94 Cancel(); |
81 Cancel(); |
95 } |
82 } |
|
83 |
96 |
84 |
97 |
85 /** |
98 /** |
86 Called by CBulkOnlyTransport HwStart to start control interface |
99 Called by CBulkOnlyTransport HwStart to start control interface |
87 */ |
100 */ |
88 TInt CControlInterfaceUsbcLdd::Start() |
101 TInt CControlInterfaceUsbcLdd::Start() |
89 { |
102 { |
90 __FNLOG("CControlInterfaceUsbcLdd::Start "); |
103 TInt res = ReadEp0Data(); |
91 TInt res = ReadEp0Data(); |
104 return (res); |
92 return (res); |
105 } |
93 } |
|
94 |
106 |
95 |
107 |
96 /** |
108 /** |
97 Called by desctructor of CBulkOnlyTransportUsbcLdd to stop control interface |
109 Called by desctructor of CBulkOnlyTransportUsbcLdd to stop control interface |
98 */ |
110 */ |
99 void CControlInterfaceUsbcLdd::Stop() |
111 void CControlInterfaceUsbcLdd::Stop() |
100 { |
112 { |
101 __FNLOG("CControlInterfaceUsbcLdd::Stop "); |
113 if (!IsActive()) |
102 if (!IsActive()) |
114 { |
103 { |
115 return; |
104 __PRINT(_L("Not active\n")); |
116 } |
105 return; |
117 iCurrentState = ENone; |
106 } |
118 Cancel(); |
107 |
119 } |
108 __PRINT(_L("\nStopping...\n")); |
|
109 |
|
110 |
|
111 iCurrentState = ENone; |
|
112 |
|
113 Cancel(); |
|
114 } |
|
115 |
120 |
116 |
121 |
117 /** |
122 /** |
118 Cancel outstanding request (if any) |
123 Cancel outstanding request (if any) |
119 */ |
124 */ |
120 void CControlInterfaceUsbcLdd::DoCancel() |
125 void CControlInterfaceUsbcLdd::DoCancel() |
121 { |
126 { |
122 __FNLOG("CControlInterfaceUsbcLdd::DoCancel "); |
127 switch(iCurrentState) |
123 switch(iCurrentState) |
128 { |
124 { |
129 case EReadEp0Data: |
125 case EReadEp0Data: |
130 iParent.Ldd().ReadCancel(EEndpoint0); |
126 iParent.Ldd().ReadCancel(EEndpoint0); |
131 break; |
127 break; |
132 case ESendMaxLun: |
128 case ESendMaxLun: |
133 iParent.Ldd().WriteCancel(EEndpoint0); |
129 iParent.Ldd().WriteCancel(EEndpoint0); |
134 break; |
130 break; |
135 default: |
131 default: |
136 __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceBadState)); |
132 __PRINT(_L("\nWrong state !\n")); |
137 break; |
133 __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceBadState)); |
138 } |
134 } |
139 } |
135 } |
|
136 |
140 |
137 |
141 |
138 /** |
142 /** |
139 Implement CControlInterfaceUsbcLdd state machine |
143 Implement CControlInterfaceUsbcLdd state machine |
140 */ |
144 */ |
141 void CControlInterfaceUsbcLdd::RunL() |
145 void CControlInterfaceUsbcLdd::RunL() |
142 { |
146 { |
143 __FNLOG("CControlInterfaceUsbcLdd::RunL "); |
147 if (iStatus != KErrNone) |
144 if (iStatus != KErrNone) |
148 { |
145 { |
149 OstTrace1(TRACE_SMASSSTORAGE_BOT, CCONTROLINTERFACEUSBCLDD, |
146 __PRINT1(_L("Error %d in RunL\n"), iStatus.Int()); |
150 "ERROR %d in RunL", iStatus.Int()); |
147 |
151 |
148 //read EP0 again |
152 //read EP0 again |
149 ReadEp0Data(); |
153 ReadEp0Data(); |
150 return; |
154 return; |
151 } |
155 } |
152 |
156 |
153 switch (iCurrentState) |
157 switch (iCurrentState) |
154 { |
158 { |
155 case ESendMaxLun: |
159 case ESendMaxLun: |
156 ReadEp0Data(); |
160 ReadEp0Data(); |
157 break; |
161 break; |
158 |
162 |
159 case EReadEp0Data: |
163 case EReadEp0Data: |
160 DecodeEp0Data(); |
164 DecodeEp0Data(); |
161 break; |
165 break; |
162 |
166 |
163 default: |
167 default: |
164 __PRINT(_L(" error: (Shouldn't end up here...)\n")); |
168 __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceBadState)); |
165 __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceBadState)); |
169 break; |
166 break; |
170 } |
167 } |
171 return; |
168 return; |
172 } |
169 } |
|
170 |
173 |
171 |
174 |
172 /** |
175 /** |
173 Post a read request to EEndpoint0 to read request header |
176 Post a read request to EEndpoint0 to read request header |
174 */ |
177 */ |
175 TInt CControlInterfaceUsbcLdd::ReadEp0Data() |
178 TInt CControlInterfaceUsbcLdd::ReadEp0Data() |
176 { |
179 { |
177 __FNLOG("CControlInterfaceUsbcLdd::ReadEp0Data "); |
180 if (IsActive()) |
178 if (IsActive()) |
181 { |
179 { |
182 OstTrace0(TRACE_SMASSSTORAGE_BOT, READEP0DATA, "Still active"); |
180 __PRINT(_L("Still active\n")); |
183 return KErrServerBusy; |
181 return KErrServerBusy; |
184 } |
182 } |
185 iParent.Ldd().Read(iStatus, EEndpoint0, iData, KRequestHdrSize); |
183 iParent.Ldd().Read(iStatus, EEndpoint0, iData, KRequestHdrSize); |
186 |
184 |
187 iCurrentState = EReadEp0Data; |
185 iCurrentState = EReadEp0Data; |
188 |
186 |
189 SetActive(); |
187 SetActive(); |
190 return KErrNone; |
188 return KErrNone; |
191 } |
189 } |
|
190 |
192 |
191 |
193 |
192 /** |
194 /** |
193 Decode request header and do appropriate action - get max LUN info or post a reset request |
195 Decode request header and do appropriate action - get max LUN info or post a reset request |
194 */ |
196 */ |
195 void CControlInterfaceUsbcLdd::DecodeEp0Data() |
197 void CControlInterfaceUsbcLdd::DecodeEp0Data() |
196 { |
198 { |
197 __FNLOG("CControlInterfaceUsbcLdd::DecodeEp0Data "); |
199 if (IsActive()) |
198 if (IsActive()) |
200 { |
199 { |
201 __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceStillActive)); |
200 __PRINT(_L("Still active\n")); |
202 return; |
201 __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsControlInterfaceStillActive)); |
203 } |
202 return; |
204 |
203 } |
205 TInt err = iRequestHeader.Decode(iData); |
204 |
206 |
205 TInt err = iRequestHeader.Decode(iData); |
207 if(err != KErrNone) |
206 |
208 return; |
207 if(err != KErrNone) |
|
208 return; |
|
209 |
209 |
210 switch(iRequestHeader.iRequest) |
210 switch(iRequestHeader.iRequest) |
211 { |
211 { |
212 // |
212 // |
213 // GET MAX LUN (0xFE) |
213 // GET MAX LUN (0xFE) |
214 // |
214 // |
215 case TUsbRequestHdr::EReqGetMaxLun: |
215 case TUsbRequestHdr::EReqGetMaxLun: |
216 { |
216 { |
217 __PRINT1(_L("DecodeEp0Data : 'Get Max LUN' Request MaxLun = %d"),iParent.MaxLun() ); |
217 OstTrace1(TRACE_SMASSSTORAGE_BOT, DECODEEP0DATA, ">>> EP0 GetMaxLun = %d", iParent.MaxLun()); |
218 |
|
219 if ( iRequestHeader.iRequestType != 0xA1 //value from USB MS BOT spec |
218 if ( iRequestHeader.iRequestType != 0xA1 //value from USB MS BOT spec |
220 || iRequestHeader.iIndex > 15 |
219 || iRequestHeader.iIndex > 15 |
221 || iRequestHeader.iValue != 0 |
220 || iRequestHeader.iValue != 0 |
222 || iRequestHeader.iLength != 1) |
221 || iRequestHeader.iLength != 1) |
223 { |
222 { |
224 __PRINT(_L("GetMaxLun command packet check error")); |
223 OstTrace0(TRACE_SMASSSTORAGE_BOT, DECODEEP0DATA1, "ERROR: GetMaxLun command packet check error"); |
225 iParent.Ldd().EndpointZeroRequestError(); |
224 iParent.Ldd().EndpointZeroRequestError(); |
226 break; |
225 break; |
227 } |
226 } |
228 iData.FillZ(1); //Return only 1 byte to host |
227 iData.FillZ(1); //Return only 1 byte to host |
229 iData[0] = static_cast<TUint8>(iParent.MaxLun()); // Supported Units |
228 iData[0] = static_cast<TUint8>(iParent.MaxLun()); // Supported Units |
230 iParent.Ldd().Write(iStatus, EEndpoint0, iData, 1); |
229 iParent.Ldd().Write(iStatus, EEndpoint0, iData, 1); |
231 |
230 |
232 iCurrentState = ESendMaxLun; |
231 iCurrentState = ESendMaxLun; |
233 SetActive(); |
232 SetActive(); |
234 |
233 |
235 return; |
234 return; |
236 } |
235 } |
237 // |
236 // |
238 // RESET (0xFF) |
237 // RESET (0xFF) |
239 // |
238 // |
240 case TUsbRequestHdr::EReqReset: |
239 case TUsbRequestHdr::EReqReset: |
241 { |
240 { |
242 __PRINT(_L("DecodeEp0Data : 'Mass Storage Reset' Request")); |
241 OstTrace0(TRACE_SMASSSTORAGE_BOT, DECODEEP0DATA2, ">>> EP0 BulkOnlyMassStorageReset"); |
243 |
242 |
244 if ( iRequestHeader.iRequestType != 0x21 //value from USB MS BOT spec |
243 if ( iRequestHeader.iRequestType != 0x21 //value from USB MS BOT spec |
245 || iRequestHeader.iIndex > 15 |
244 || iRequestHeader.iIndex > 15 |
246 || iRequestHeader.iValue != 0 |
245 || iRequestHeader.iValue != 0 |
247 || iRequestHeader.iLength != 0) |
246 || iRequestHeader.iLength != 0) |
248 { |
247 { |
249 __PRINT(_L("MSC Reset command packet check error")); |
248 OstTrace0(TRACE_SMASSSTORAGE_BOT, DECODEEP0DATA3, "BulkOnlyMassStorageReset command packet check error"); |
250 iParent.Ldd().EndpointZeroRequestError(); |
249 iParent.Ldd().EndpointZeroRequestError(); |
251 break; |
250 break; |
252 } |
251 } |
253 iParent.HwStop(); |
252 iParent.HwStop(); |
254 iParent.Controller().Reset(); |
253 iParent.Controller().Reset(); |
255 iParent.HwStart(ETrue); |
254 iParent.HwStart(ETrue); |
256 |
255 |
257 err = iParent.Ldd().SendEp0StatusPacket(); |
256 err = iParent.Ldd().SendEp0StatusPacket(); |
258 |
257 |
259 return; |
258 return; |
260 } |
259 } |
261 // |
260 // |
262 // Unknown? |
261 // Unknown? |
263 // |
262 // |
264 default: |
263 default: |
265 { |
264 { |
266 __PRINT(_L("DecodeEp0Data : Unknown Request")); |
265 OstTrace0(TRACE_SMASSSTORAGE_BOT, DECODEEP0DATA4, ">>> EP0 DecodeEp0Data : Unknown Request"); |
267 |
266 } |
268 } |
267 } |
269 } |
268 ReadEp0Data(); //try to get another request |
270 ReadEp0Data(); //try to get another request |
269 } |
271 } |
|
272 |
270 |
273 |
271 |
274 // |
272 // |
275 // --- class CBulkOnlyTransportUsbcLdd --------------------------------------------------------- |
273 // --- class CBulkOnlyTransportUsbcLdd --------------------------------------------------------- |
276 // |
274 // |
277 |
275 |
278 CBulkOnlyTransportUsbcLdd::CBulkOnlyTransportUsbcLdd(TInt aNumDrives,CUsbMassStorageController& aController) |
276 CBulkOnlyTransportUsbcLdd::CBulkOnlyTransportUsbcLdd(TInt aNumDrives,CUsbMassStorageController& aController) |
279 :CBulkOnlyTransport(aNumDrives, aController), |
277 :CBulkOnlyTransport(aNumDrives, aController) |
280 iSwap(ETrue) |
278 { |
281 { |
279 } |
282 __FNLOG("CBulkOnlyTransportUsbcLdd::CBulkOnlyTransportUsbcLdd"); |
|
283 } |
|
284 |
280 |
285 /** |
281 /** |
286 Constructs the CBulkOnlyTransportUsbcLdd object |
282 Constructs the CBulkOnlyTransportUsbcLdd object |
287 */ |
283 */ |
288 void CBulkOnlyTransportUsbcLdd::ConstructL() |
284 void CBulkOnlyTransportUsbcLdd::ConstructL() |
289 { |
285 { |
290 __FNLOG("CBulkOnlyTransportUsbcLdd::ConstructL()"); |
286 iControlInterface = CControlInterfaceUsbcLdd::NewL(*this); |
291 iControlInterface = CControlInterfaceUsbcLdd::NewL(*this); |
287 iDeviceStateNotifier = CActiveDeviceStateNotifierBase::NewL(*this, *this); |
292 iDeviceStateNotifier = CActiveDeviceStateNotifierBase::NewL(*this, *this); |
288 CActiveScheduler::Add(this); |
293 CActiveScheduler::Add(this); |
289 } |
294 } |
|
295 |
290 |
296 CBulkOnlyTransportUsbcLdd::~CBulkOnlyTransportUsbcLdd() |
291 CBulkOnlyTransportUsbcLdd::~CBulkOnlyTransportUsbcLdd() |
297 { |
292 { |
298 __FNLOG("CBulkOnlyTransportUsbcLdd::~CBulkOnlyTransportUsbcLdd"); |
293 if (iInterfaceConfigured) |
299 if (iInterfaceConfigured) |
294 { |
300 { |
295 Stop(); |
301 Stop(); |
296 delete iControlInterface ; |
302 delete iControlInterface ; |
297 delete iDeviceStateNotifier; |
303 delete iDeviceStateNotifier; |
298 } |
304 } |
299 } |
305 } |
|
306 |
300 |
307 RDevUsbcClient& CBulkOnlyTransportUsbcLdd::Ldd() |
301 RDevUsbcClient& CBulkOnlyTransportUsbcLdd::Ldd() |
308 { |
302 { |
309 return iLdd; |
303 return iLdd; |
310 } |
304 } |
311 |
305 |
312 |
306 |
313 /** |
307 /** |
314 Set or unset configuration descriptor for USB MassStorage Bulk Only transport |
308 Set or unset configuration descriptor for USB MassStorage Bulk Only transport |
315 |
309 |
316 @param aUnset indicate whether set or unset descriptor |
310 @param aUnset indicate whether set or unset descriptor |
317 @return KErrNone if operation was completed successfully, errorcode otherwise |
311 @return KErrNone if operation was completed successfully, errorcode otherwise |
318 */ |
312 */ |
319 TInt CBulkOnlyTransportUsbcLdd::SetupConfigurationDescriptor(TBool aUnset) |
313 TInt CBulkOnlyTransportUsbcLdd::SetupConfigurationDescriptor(TBool aUnset) |
320 { |
314 { |
321 __FNLOG("CBulkOnlyTransportUsbcLdd::SetupConfigurationDescriptor"); |
315 TInt ret(KErrNone); |
322 TInt ret(KErrNone); |
316 |
323 |
317 if ((ret = iLdd.Open(0)) != KErrNone) |
324 if ((ret = iLdd.Open(0)) != KErrNone) |
318 return ret; |
325 return ret; |
319 |
326 |
320 TInt configDescriptorSize(0); |
327 TInt configDescriptorSize(0); |
321 iLdd.GetConfigurationDescriptorSize(configDescriptorSize); |
328 iLdd.GetConfigurationDescriptorSize(configDescriptorSize); |
322 if (static_cast<TUint>(configDescriptorSize) != KUsbDescSize_Config) |
329 if (static_cast<TUint>(configDescriptorSize) != KUsbDescSize_Config) |
323 { |
330 { |
324 return KErrCorrupt; |
331 return KErrCorrupt; |
325 } |
332 } |
326 |
333 |
327 TBuf8<KUsbDescSize_Config> configDescriptor; |
334 TBuf8<KUsbDescSize_Config> configDescriptor; |
328 ret = iLdd.GetConfigurationDescriptor(configDescriptor); |
335 ret = iLdd.GetConfigurationDescriptor(configDescriptor); |
329 if (ret != KErrNone) |
336 if (ret != KErrNone) |
330 { |
337 { |
331 return ret; |
338 return ret; |
332 } |
339 } |
333 |
340 |
334 // I beleive that other fields setted up during LDD initialisation |
341 // I beleive that other fields setted up during LDD initialisation |
335 if (aUnset) |
342 if (aUnset) |
336 { |
343 { |
337 --configDescriptor[KUsbNumInterfacesOffset]; |
344 --configDescriptor[KUsbNumInterfacesOffset]; |
338 } |
345 } |
339 else |
346 else |
340 { |
347 { |
341 ++configDescriptor[KUsbNumInterfacesOffset]; |
348 ++configDescriptor[KUsbNumInterfacesOffset]; |
342 } |
349 } |
343 ret = iLdd.SetConfigurationDescriptor(configDescriptor); |
350 ret = iLdd.SetConfigurationDescriptor(configDescriptor); |
344 |
351 |
345 if (aUnset) |
352 if (aUnset) |
346 { |
353 { |
347 iLdd.Close(); |
354 iLdd.Close(); |
348 } |
355 } |
349 return ret; |
356 return ret; |
350 } |
357 } |
|
358 |
351 |
359 /** |
352 /** |
360 Set up interface descriptor |
353 Set up interface descriptor |
361 |
354 |
362 @return KErrNone if operation was completed successfully, errorcode otherwise |
355 @return KErrNone if operation was completed successfully, errorcode otherwise |
363 */ |
356 */ |
364 TInt CBulkOnlyTransportUsbcLdd::SetupInterfaceDescriptors() |
357 TInt CBulkOnlyTransportUsbcLdd::SetupInterfaceDescriptors() |
365 { |
358 { |
366 __FNLOG("CBulkOnlyTransportUsbcLdd::SetupInterfaceDescriptors"); |
359 // Device caps |
367 // Device caps |
360 TUsbDeviceCaps d_caps; |
368 TUsbDeviceCaps d_caps; |
361 TInt ret = iLdd.DeviceCaps(d_caps); |
369 TInt ret = iLdd.DeviceCaps(d_caps); |
362 if (ret != KErrNone) |
370 if (ret != KErrNone) |
363 { |
371 { |
364 return ret; |
372 return ret; |
365 } |
373 } |
366 TInt totalEndpoints = d_caps().iTotalEndpoints; |
374 TInt totalEndpoints = d_caps().iTotalEndpoints; |
367 if (totalEndpoints < KRequiredNumberOfEndpoints) |
375 if (totalEndpoints < KRequiredNumberOfEndpoints) |
368 { |
376 { |
369 return KErrHardwareNotAvailable; |
377 return KErrHardwareNotAvailable; |
370 } |
378 } |
371 |
379 |
372 // Endpoint caps |
380 // Endpoint caps |
373 TUsbcEndpointData data[KUsbcMaxEndpoints]; |
381 TUsbcEndpointData data[KUsbcMaxEndpoints]; |
374 TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data)); |
382 TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data)); |
375 ret = iLdd.EndpointCaps(dataptr); |
383 ret = iLdd.EndpointCaps(dataptr); |
376 if (ret != KErrNone) |
384 if (ret != KErrNone) |
377 { |
385 { |
378 return ret; |
386 return ret; |
379 } |
387 } |
380 |
388 |
381 // Set the active interface |
389 // Set the active interface |
382 TUsbcInterfaceInfoBuf ifc; |
390 TUsbcInterfaceInfoBuf ifc; |
383 TInt ep_found = 0; |
391 TInt ep_found = 0; |
384 TBool foundBulkIN = EFalse; |
392 TBool foundBulkIN = EFalse; |
385 TBool foundBulkOUT = EFalse; |
393 TBool foundBulkOUT = EFalse; |
386 |
394 |
387 for (TInt i = 0; i < totalEndpoints ; i++) |
395 for (TInt i = 0; i < totalEndpoints ; i++) |
388 { |
396 { |
389 const TUsbcEndpointCaps* caps = &data[i].iCaps; |
397 const TUsbcEndpointCaps* caps = &data[i].iCaps; |
390 const TInt maxPacketSize = caps->MaxPacketSize(); |
398 const TInt maxPacketSize = caps->MaxPacketSize(); |
391 if (!foundBulkIN && |
399 if (!foundBulkIN && |
392 (caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirIn)) == (KUsbEpTypeBulk | KUsbEpDirIn)) |
400 (caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirIn)) == (KUsbEpTypeBulk | KUsbEpDirIn)) |
393 { |
401 { |
394 // InEndpoint is going to be our TX (IN, write) endpoint |
402 // InEndpoint is going to be our TX (IN, write) endpoint |
395 ifc().iEndpointData[0].iType = KUsbEpTypeBulk; |
403 ifc().iEndpointData[0].iType = KUsbEpTypeBulk; |
396 if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) == KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) |
404 if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) == KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) |
397 ifc().iEndpointData[0].iFeatureWord1 = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering; |
405 ifc().iEndpointData[0].iFeatureWord1 = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering; |
398 ifc().iEndpointData[0].iDir = KUsbEpDirIn; |
406 ifc().iEndpointData[0].iDir = KUsbEpDirIn; |
399 ifc().iEndpointData[0].iSize = maxPacketSize; |
407 ifc().iEndpointData[0].iSize = maxPacketSize; |
400 ifc().iEndpointData[0].iInterval_Hs = 0; |
408 ifc().iEndpointData[0].iInterval_Hs = 0; |
401 foundBulkIN = ETrue; |
409 foundBulkIN = ETrue; |
402 if (++ep_found == KRequiredNumberOfEndpoints) |
410 if (++ep_found == KRequiredNumberOfEndpoints) |
403 { |
411 { |
404 break; |
412 break; |
405 } |
413 } |
406 continue; |
414 continue; |
407 } |
415 } |
408 if (!foundBulkOUT && |
416 if (!foundBulkOUT && |
409 (caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirOut)) == (KUsbEpTypeBulk | KUsbEpDirOut)) |
417 (caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirOut)) == (KUsbEpTypeBulk | KUsbEpDirOut)) |
410 { |
418 { |
411 // OutEndpoint is going to be our RX (OUT, read) endpoint |
419 // OutEndpoint is going to be our RX (OUT, read) endpoint |
412 ifc().iEndpointData[1].iType = KUsbEpTypeBulk; |
420 ifc().iEndpointData[1].iType = KUsbEpTypeBulk; |
413 if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) == KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) |
421 if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) == KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) |
414 ifc().iEndpointData[1].iFeatureWord1 = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering; |
422 ifc().iEndpointData[1].iFeatureWord1 = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering; |
415 ifc().iEndpointData[1].iDir = KUsbEpDirOut; |
423 ifc().iEndpointData[1].iDir = KUsbEpDirOut; |
416 ifc().iEndpointData[1].iSize = maxPacketSize; |
424 ifc().iEndpointData[1].iSize = maxPacketSize; |
417 ifc().iEndpointData[1].iInterval_Hs = 0; |
425 ifc().iEndpointData[1].iInterval_Hs = 0; |
418 foundBulkOUT = ETrue; |
426 foundBulkOUT = ETrue; |
419 if (++ep_found == KRequiredNumberOfEndpoints) |
427 if (++ep_found == KRequiredNumberOfEndpoints) |
420 { |
428 { |
421 break; |
429 break; |
422 } |
430 } |
423 continue; |
431 continue; |
424 } |
432 } |
425 } |
433 } |
426 if (ep_found != KRequiredNumberOfEndpoints) |
434 if (ep_found != KRequiredNumberOfEndpoints) |
427 { |
435 { |
428 return KErrHardwareNotAvailable; |
436 return KErrHardwareNotAvailable; |
429 } |
437 } |
430 |
438 |
431 _LIT16(string, "USB Mass Storage Interface"); |
439 _LIT16(string, "USB Mass Storage Interface"); |
432 ifc().iString = const_cast<TDesC16*>(&string); |
440 ifc().iString = const_cast<TDesC16*>(&string); |
433 ifc().iTotalEndpointsUsed = KRequiredNumberOfEndpoints; |
441 ifc().iTotalEndpointsUsed = KRequiredNumberOfEndpoints; |
434 ifc().iClass.iClassNum = 0x08; // Mass Storage |
442 ifc().iClass.iClassNum = 0x08; // Mass Storage |
435 ifc().iClass.iSubClassNum = 0x06; // SCSI Transparent Command Set |
443 ifc().iClass.iSubClassNum = 0x06; // SCSI Transparent Command Set |
436 ifc().iClass.iProtocolNum = 0x50; // Bulk Only Transport |
444 ifc().iClass.iProtocolNum = 0x50; // Bulk Only Transport |
437 |
445 |
438 TUint bandwidth_priority = (EUsbcBandwidthOUTDefault | EUsbcBandwidthINDefault); |
446 TUint bandwidth_priority = (EUsbcBandwidthOUTDefault | EUsbcBandwidthINDefault); |
439 if (d_caps().iHighSpeed) |
447 if (d_caps().iHighSpeed) |
440 { |
448 { |
441 // If this device supports USB High-speed, then we request 64KB buffers |
449 // If this device supports USB High-speed, then we request 64KB buffers |
442 // (otherwise the default 4KB ones will do). |
450 // (otherwise the default 4KB ones will do). |
443 bandwidth_priority = (EUsbcBandwidthOUTPlus2 | EUsbcBandwidthINPlus2); |
451 bandwidth_priority = (EUsbcBandwidthOUTPlus2 | EUsbcBandwidthINPlus2); |
444 // Also, tell the Protocol about it, because it might want to do some |
452 // Also, tell the Protocol about it, because it might want to do some |
445 // optimizing too. |
453 // optimizing too. |
446 iProtocol->ReportHighSpeedDevice(); |
454 iProtocol->ReportHighSpeedDevice(); |
447 } |
455 } |
448 ret = iLdd.SetInterface(0, ifc, bandwidth_priority); |
456 ret = iLdd.SetInterface(0, ifc, bandwidth_priority); |
449 return ret; |
457 return ret; |
450 } |
458 } |
|
459 |
451 |
460 void CBulkOnlyTransportUsbcLdd::ReleaseInterface() |
452 void CBulkOnlyTransportUsbcLdd::ReleaseInterface() |
461 { |
453 { |
462 iLdd.ReleaseInterface(0); |
454 iLdd.ReleaseInterface(0); |
463 } |
455 } |
464 |
456 |
465 TInt CBulkOnlyTransportUsbcLdd::StartControlInterface() |
457 TInt CBulkOnlyTransportUsbcLdd::StartControlInterface() |
466 { |
458 { |
467 return iControlInterface->Start(); |
459 return iControlInterface->Start(); |
468 } |
460 } |
469 |
461 |
470 void CBulkOnlyTransportUsbcLdd::CancelControlInterface() |
462 void CBulkOnlyTransportUsbcLdd::CancelControlInterface() |
471 { |
463 { |
472 iControlInterface->Cancel(); |
464 iControlInterface->Cancel(); |
473 } |
465 } |
474 |
466 |
475 void CBulkOnlyTransportUsbcLdd::ActivateDeviceStateNotifier() |
467 void CBulkOnlyTransportUsbcLdd::ActivateDeviceStateNotifier() |
476 { |
468 { |
477 __ASSERT_DEBUG(iDeviceStateNotifier, User::Panic(KUsbMsSvrPncCat, EMsCDeviceStateNotifierNull)); |
469 __ASSERT_DEBUG(iDeviceStateNotifier, User::Panic(KUsbMsSvrPncCat, EMsCDeviceStateNotifierNull)); |
478 iDeviceStateNotifier->Activate(); |
470 iDeviceStateNotifier->Activate(); |
479 } |
471 } |
480 |
472 |
481 void CBulkOnlyTransportUsbcLdd::CancelDeviceStateNotifier() |
473 void CBulkOnlyTransportUsbcLdd::CancelDeviceStateNotifier() |
482 { |
474 { |
483 iDeviceStateNotifier->Cancel(); |
475 iDeviceStateNotifier->Cancel(); |
484 } |
476 } |
485 |
477 |
486 void CBulkOnlyTransportUsbcLdd::CancelReadWriteRequests() |
478 void CBulkOnlyTransportUsbcLdd::CancelReadWriteRequests() |
487 { |
479 { |
488 __FNLOG("CBulkOnlyTransportUsbcLdd::CancelReadWriteRequests"); |
480 iLdd.WriteCancel(InEndpoint); |
489 iLdd.WriteCancel(InEndpoint); |
481 iLdd.ReadCancel(OutEndpoint); |
490 iLdd.ReadCancel(OutEndpoint); |
482 } |
491 } |
|
492 |
483 |
493 void CBulkOnlyTransportUsbcLdd::AllocateEndpointResources() |
484 void CBulkOnlyTransportUsbcLdd::AllocateEndpointResources() |
494 { |
485 { |
495 TUsbDeviceCaps d_caps; |
486 TUsbDeviceCaps d_caps; |
496 TInt ret = iLdd.DeviceCaps(d_caps); |
487 TInt ret = iLdd.DeviceCaps(d_caps); |
497 if (ret == KErrNone) |
488 if (ret == KErrNone) |
498 { |
489 { |
499 if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) |
490 if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) |
500 { |
491 { |
501 // Set up DMA if possible (errors are non-critical) |
492 // Set up DMA if possible (errors are non-critical) |
502 TInt err = iLdd.AllocateEndpointResource(OutEndpoint, EUsbcEndpointResourceDMA); |
493 TInt err = iLdd.AllocateEndpointResource(OutEndpoint, EUsbcEndpointResourceDMA); |
503 if (err != KErrNone) |
494 if (err != KErrNone) |
504 { |
495 { |
505 __PRINT1(_L("Set DMA on OUT endpoint failed with error code: %d"), err); |
496 OstTrace1(TRACE_SMASSSTORAGE_BOT, A1, "Set DMA on OUT endpoint failed with error code: %d", err); |
506 } |
497 } |
507 err = iLdd.AllocateEndpointResource(InEndpoint, EUsbcEndpointResourceDMA); |
498 err = iLdd.AllocateEndpointResource(InEndpoint, EUsbcEndpointResourceDMA); |
508 if (err != KErrNone) |
499 if (err != KErrNone) |
509 { |
500 { |
510 __PRINT1(_L("Set DMA on IN endpoint failed with error code: %d"), err); |
501 OstTrace1(TRACE_SMASSSTORAGE_BOT, A2, "Set DMA on IN endpoint failed with error code: %d", err); |
511 } |
502 } |
512 |
503 |
513 // Set up Double Buffering if possible (errors are non-critical) |
504 // Set up Double Buffering if possible (errors are non-critical) |
514 err = iLdd.AllocateEndpointResource(OutEndpoint, EUsbcEndpointResourceDoubleBuffering); |
505 err = iLdd.AllocateEndpointResource(OutEndpoint, EUsbcEndpointResourceDoubleBuffering); |
515 if (err != KErrNone) |
506 if (err != KErrNone) |
516 { |
507 { |
517 __PRINT1(_L("Set Double Buffering on OUT endpoint failed with error code: %d"), err); |
508 OstTrace1(TRACE_SMASSSTORAGE_BOT, A3, "Set Double Buffering on OUT endpoint failed with error code: %d", err); |
518 } |
509 } |
519 err = iLdd.AllocateEndpointResource(InEndpoint, EUsbcEndpointResourceDoubleBuffering); |
510 err = iLdd.AllocateEndpointResource(InEndpoint, EUsbcEndpointResourceDoubleBuffering); |
520 if (err != KErrNone) |
511 if (err != KErrNone) |
521 { |
512 { |
522 __PRINT1(_L("Set Double Buffering on IN endpoint failed with error code: %d"), err); |
513 OstTrace1(TRACE_SMASSSTORAGE_BOT, A4, "Set Double Buffering on IN endpoint failed with error code: %d", err); |
523 } |
514 } |
524 } |
515 } |
525 } |
516 } |
526 } |
517 } |
527 |
518 |
528 TInt CBulkOnlyTransportUsbcLdd::GetDeviceStatus(TUsbcDeviceState& deviceStatus) |
519 TInt CBulkOnlyTransportUsbcLdd::GetDeviceStatus(TUsbcDeviceState& deviceStatus) |
529 { |
520 { |
530 return iLdd.DeviceStatus(deviceStatus); |
521 return iLdd.DeviceStatus(deviceStatus); |
531 } |
522 } |
532 |
523 |
533 void CBulkOnlyTransportUsbcLdd::FlushData() |
524 void CBulkOnlyTransportUsbcLdd::FlushData() |
534 { |
525 { |
535 TInt bytes; |
526 TInt bytes; |
536 const TInt err = iLdd.QueryReceiveBuffer(OutEndpoint, bytes); |
527 const TInt err = iLdd.QueryReceiveBuffer(OutEndpoint, bytes); |
537 if (err != KErrNone || bytes <= 0) |
528 if (err != KErrNone || bytes <= 0) |
538 { |
529 { |
539 __PRINT1(_L("Error: err=%d bytes=%d"), bytes); |
530 OstTraceExt2(TRACE_SMASSSTORAGE_BOT, B1, "ERROR: err=%d bytes=0x%x", err, bytes); |
540 } |
531 } |
541 else |
532 else |
542 { |
533 { |
543 __PRINT1(_L("RxBuffer has %d bytes"), bytes); |
534 OstTrace1(TRACE_SMASSSTORAGE_BOT1, B2, "RxBuffer has %d bytes", bytes); |
544 ReadAndDiscardData(bytes); |
535 ReadAndDiscardData(bytes); |
545 } |
536 } |
546 } |
537 } |
547 /** |
538 /** |
548 * Read out rest data from OutEndpoint and discard them |
539 * Read out rest data from OutEndpoint and discard them |
549 */ |
540 */ |
550 void CBulkOnlyTransportUsbcLdd::ReadAndDiscardData(TInt aBytes) |
541 void CBulkOnlyTransportUsbcLdd::ReadAndDiscardData(TInt aBytes) |
551 { |
542 { |
552 __FNLOG("CBulkOnlyTransportUsbcLdd::ReadAndDiscardData"); |
543 iDiscardBuf.SetMax(); |
553 iDiscardBuf.SetMax(); |
544 const TUint bufsize = static_cast<TUint>(iDiscardBuf.Length()); |
554 const TUint bufsize = static_cast<TUint>(iDiscardBuf.Length()); |
545 TRequestStatus status; |
555 TRequestStatus status; |
546 while (aBytes > 0) |
556 while (aBytes > 0) |
547 { |
557 { |
548 OstTrace1(TRACE_SMASSSTORAGE_BOT1, C1, "Bytes still to be read: 0x%x", aBytes); |
558 __PRINT1(_L("Bytes still to be read: %d\n"), aBytes); |
549 iLdd.ReadOneOrMore(status, OutEndpoint, iDiscardBuf, bufsize); |
559 iLdd.ReadOneOrMore(status, OutEndpoint, iDiscardBuf, bufsize); |
550 User::WaitForRequest(status); |
560 User::WaitForRequest(status); |
551 TInt err = status.Int(); |
561 TInt err = status.Int(); |
552 if (err != KErrNone) |
562 if (err != KErrNone) |
553 { |
563 { |
554 // Bad. |
564 // Bad. |
555 break; |
565 break; |
556 } |
566 } |
557 aBytes -= iDiscardBuf.Length(); |
567 aBytes -= iDiscardBuf.Length(); |
558 } |
568 } |
559 } |
569 } |
|
570 |
560 |
571 /** |
561 /** |
572 Called by the protocol to determine how many bytes of data are available in the read buffer. |
562 Called by the protocol to determine how many bytes of data are available in the read buffer. |
573 |
563 |
574 @return The number of bytes available in the read buffer |
564 @return The number of bytes available in the read buffer |
575 */ |
565 */ |
576 TInt CBulkOnlyTransportUsbcLdd::BytesAvailable() |
566 TInt CBulkOnlyTransportUsbcLdd::BytesAvailable() |
577 { |
567 { |
578 TInt bytes = 0; |
568 TInt bytes = 0; |
579 TInt err = iLdd.QueryReceiveBuffer(OutEndpoint, bytes); |
569 TInt err = iLdd.QueryReceiveBuffer(OutEndpoint, bytes); |
580 if (err != KErrNone) |
570 if (err != KErrNone) |
581 bytes = 0; |
571 bytes = 0; |
582 return bytes; |
572 return bytes; |
583 } |
573 } |
584 |
574 |
585 |
575 |
586 void CBulkOnlyTransportUsbcLdd::StallEndpointAndWaitForClear() |
576 void CBulkOnlyTransportUsbcLdd::StallEndpointAndWaitForClear() |
587 { |
577 { |
588 __FNLOG("CBulkOnlyTransportUsbcLdd::StallEndpointAndWaitForClear"); |
578 // Now stall this endpoint |
589 |
579 OstTrace1(TRACE_SMASSSTORAGE_BOT, D1, "Stalling endpoint %d", InEndpoint); |
590 // Now stall this endpoint |
580 TInt r = iLdd.HaltEndpoint(InEndpoint); |
591 __PRINT1(_L("Stalling endpoint %d"), InEndpoint); |
581 if (r != KErrNone) |
592 TInt r = iLdd.HaltEndpoint(InEndpoint); |
582 { |
593 if (r != KErrNone) |
583 OstTraceExt2(TRACE_SMASSSTORAGE_BOT, D2, "Error: stalling ep %d failed: %d", InEndpoint, r); |
594 { |
584 } |
595 __PRINT2(_L("Error: stalling ep %d failed: %d"), InEndpoint, r); |
585 TEndpointState ep_state; |
596 } |
586 TInt i = 0; |
597 TEndpointState ep_state; |
587 do |
598 TInt i = 0; |
588 { |
599 do |
589 // Wait for 10ms before checking the ep status |
600 { |
590 User::After(10000); |
601 // Wait for 10ms before checking the ep status |
591 iLdd.EndpointStatus(InEndpoint, ep_state); |
602 User::After(10000); |
592 if (++i >= 550) |
603 iLdd.EndpointStatus(InEndpoint, ep_state); |
593 { |
604 if (++i >= 550) |
594 // 5.5 secs should be enough (see 9.2.6.1 Request Processing Timing) |
605 { |
595 OstTrace1(TRACE_SMASSSTORAGE_BOT, D3, "Error: Checked for ep %d de-stall for 5.5s - giving up now", InEndpoint); |
606 // 5.5 secs should be enough (see 9.2.6.1 Request Processing Timing) |
596 // We can now only hope for a Reset Recovery |
607 __PRINT1(_L("Error: Checked for ep %d de-stall for 5.5s - giving up now"), InEndpoint); |
597 return; |
608 // We can now only hope for a Reset Recovery |
598 } |
609 return; |
599 } while ((ep_state == EEndpointStateStalled) && iStarted); |
610 } |
600 OstTraceExt2(TRACE_SMASSSTORAGE_BOT, D4, "Checked for ep %d de-stall: %d time(s)", InEndpoint, i); |
611 } while ((ep_state == EEndpointStateStalled) && iStarted); |
601 } |
612 __PRINT2(_L("Checked for ep %d de-stall: %d time(s)"), InEndpoint, i); |
|
613 } |
|
614 |
602 |
615 |
603 |
616 /** |
604 /** |
617 Read CBW data (KCbwLength) from the host into the read buffer. |
605 Read CBW data (KCbwLength) from the host into the read buffer. |
618 */ |
606 */ |
619 void CBulkOnlyTransportUsbcLdd::ReadCBW() |
607 void CBulkOnlyTransportUsbcLdd::ReadCBW() |
620 { |
608 { |
621 __FNLOG("CBulkOnlyTransportUsbcLdd::ReadCBW"); |
609 if (IsActive()) |
622 if (IsActive()) |
610 { |
623 { |
611 __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive)); |
624 __PRINT(_L("Still active\n")); |
612 return; |
625 __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive)); |
613 } |
626 return; |
614 |
627 } |
615 iCbwBuf.SetMax(); |
628 |
616 iLdd.ReadUntilShort(iStatus, OutEndpoint, iCbwBuf, KCbwLength); |
629 iCbwBuf.SetMax(); |
617 |
630 iLdd.ReadUntilShort(iStatus, OutEndpoint, iCbwBuf, KCbwLength); |
618 iCurrentState = EWaitForCBW; |
631 |
619 SetActive(); |
632 iCurrentState = EWaitForCBW; |
620 } |
633 SetActive(); |
|
634 } |
|
635 |
621 |
636 void CBulkOnlyTransportUsbcLdd::ExpireData(TAny* /*aAddress*/) |
622 void CBulkOnlyTransportUsbcLdd::ExpireData(TAny* /*aAddress*/) |
637 { |
623 { |
638 // Intentionally left blank |
624 // Intentionally left blank |
639 } |
625 } |
640 |
626 |
641 void CBulkOnlyTransportUsbcLdd::ProcessCbwEvent() |
627 void CBulkOnlyTransportUsbcLdd::ProcessCbwEvent() |
642 { |
628 { |
643 DecodeCBW(); |
629 DecodeCBW(); |
644 } |
630 } |
645 |
631 |
646 |
632 |
647 /** |
633 /** |
648 Request data form the host for the protocol |
634 Request data form the host for the protocol |
649 |
635 |
650 @param aLength amount of data (in bytes) to be received from the host |
636 @param aLength amount of data (in bytes) to be received from the host |
651 */ |
637 */ |
652 void CBulkOnlyTransportUsbcLdd::ReadData(TUint aLength) |
638 void CBulkOnlyTransportUsbcLdd::ReadData(TUint aLength) |
653 { |
639 { |
654 __FNLOG("CBulkOnlyTransportUsbcLdd::ReadData"); |
640 if (IsActive()) |
655 if (IsActive()) |
641 { |
656 { |
642 __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive)); |
657 __PRINT(_L("Still active\n")); |
643 return; |
658 __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive)); |
644 } |
659 return; |
645 |
660 } |
646 SetReadDataBufPtr(aLength); |
661 |
647 iLdd.Read(iStatus, OutEndpoint, iReadBufPtr, aLength); |
662 SetReadDataBufPtr(aLength); |
648 |
663 iLdd.Read(iStatus, OutEndpoint, iReadBufPtr, aLength); |
649 iCurrentState = EReadingData; |
664 |
650 SetActive(); |
665 iCurrentState = EReadingData; |
651 } |
666 SetActive(); |
|
667 } |
|
668 |
652 |
669 void CBulkOnlyTransportUsbcLdd::WriteUsb(TRequestStatus& aStatus, TPtrC8& aDes, TUint aLength, TBool aZlpRequired) |
653 void CBulkOnlyTransportUsbcLdd::WriteUsb(TRequestStatus& aStatus, TPtrC8& aDes, TUint aLength, TBool aZlpRequired) |
670 { |
654 { |
671 iLdd.Write(aStatus, InEndpoint, aDes, aLength, aZlpRequired); |
655 iLdd.Write(aStatus, InEndpoint, aDes, aLength, aZlpRequired); |
672 } |
656 } |
673 |
657 |
674 void CBulkOnlyTransportUsbcLdd::SetCbwPtr() |
658 void CBulkOnlyTransportUsbcLdd::SetCbwPtr() |
675 { |
659 { |
676 iCbwBufPtr.Set(iCbwBuf.Ptr(), iCbwBuf.Length()); |
660 iCbwBufPtr.Set(iCbwBuf.Ptr(), iCbwBuf.Length()); |
677 } |
661 } |
678 |
662 |
679 TPtr8& CBulkOnlyTransportUsbcLdd::SetCommandBufPtr(TUint aLength) |
663 TPtr8& CBulkOnlyTransportUsbcLdd::SetCommandBufPtr(TUint aLength) |
680 { |
664 { |
681 iCommandBufPtr.Set((TUint8*) iCommandBuf.Ptr(), aLength, aLength ); |
665 iCommandBufPtr.Set((TUint8*) iCommandBuf.Ptr(), aLength, aLength ); |
682 return iCommandBufPtr; |
666 return iCommandBufPtr; |
683 } |
667 } |
684 |
668 |
685 void CBulkOnlyTransportUsbcLdd::SetReadDataBufPtr(TUint aLength) //Write10(Host->Device |
669 void CBulkOnlyTransportUsbcLdd::SetReadDataBufPtr(TUint aLength) //Write10(Host->Device |
686 { |
670 { |
687 if (iSwap) |
671 iBulkMm.GetNextTransferBuffer(aLength, iReadBufPtr); |
688 { |
672 } |
689 iDataBuf1.SetLength(aLength); |
673 |
690 iReadBufPtr.Set(iDataBuf1.LeftTPtr(iDataBuf1.Length())); |
|
691 iSwap = EFalse; |
|
692 } |
|
693 else |
|
694 { |
|
695 iDataBuf2.SetLength(aLength); |
|
696 iReadBufPtr.Set(iDataBuf2.LeftTPtr(iDataBuf2.Length())); |
|
697 iSwap = ETrue; |
|
698 } |
|
699 } |
|
700 |
674 |
701 TPtr8& CBulkOnlyTransportUsbcLdd::SetDataBufPtr() //Read10(Device->Host) |
675 TPtr8& CBulkOnlyTransportUsbcLdd::SetDataBufPtr() //Read10(Device->Host) |
702 { |
676 { |
703 if (iSwap) |
677 iBulkMm.GetNextTransferBuffer(iDataBufPtr); |
704 { |
678 return iDataBufPtr; |
705 iDataBufPtr.Set((TUint8*) iDataBuf1.Ptr(), KMaxBufSize, KMaxBufSize); |
679 } |
706 iSwap = EFalse; |
|
707 } |
|
708 else |
|
709 { |
|
710 iDataBufPtr.Set((TUint8*) iDataBuf2.Ptr(), KMaxBufSize, KMaxBufSize); |
|
711 iSwap = ETrue; |
|
712 } |
|
713 return iDataBufPtr; |
|
714 } |
|
715 |
680 |
716 void CBulkOnlyTransportUsbcLdd::SetPaddingBufPtr(TUint aLength) |
681 void CBulkOnlyTransportUsbcLdd::SetPaddingBufPtr(TUint aLength) |
717 { |
682 { |
718 iPaddingBufPtr.Set((TUint8*) iBuf.Ptr(), aLength, aLength ); |
683 iPaddingBufPtr.Set((TUint8*) iBuf.Ptr(), aLength, aLength ); |
719 } |
684 } |
720 |
685 |
721 |
686 |
722 void CBulkOnlyTransportUsbcLdd::SetCswBufPtr(TUint aLength) |
687 void CBulkOnlyTransportUsbcLdd::SetCswBufPtr(TUint aLength) |
723 { |
688 { |
724 iCswBufPtr.Set((TUint8*) iCswBuf.Ptr(), aLength, aLength ); |
689 iCswBufPtr.Set((TUint8*) iCswBuf.Ptr(), aLength, aLength ); |
725 } |
690 } |
726 |
691 |
727 void CBulkOnlyTransportUsbcLdd::ProcessReadingDataEvent() |
692 void CBulkOnlyTransportUsbcLdd::ProcessReadingDataEvent() |
728 { |
693 { |
729 TInt ret = KErrNone; |
694 TInt ret = KErrNone; |
730 FOREVER |
695 FOREVER |
731 { |
696 { |
732 if (iReadSetUp) |
697 if (iReadSetUp) |
733 { |
698 { |
734 ret = iProtocol->ReadComplete(KErrNone); |
699 ret = iProtocol->ReadComplete(KErrNone); |
735 } |
700 } |
736 |
701 |
737 TUint deviceDataLength = iBufSize; // This is the amount (maximum in case of SC Ldd) to be read next. |
702 TUint deviceDataLength = iBufSize; // This is the amount (maximum in case of SC Ldd) to be read next. |
738 |
703 |
739 if(ret == KErrCompletion) |
704 if(ret == KErrCompletion) |
740 { |
705 { |
741 // The protocol has indicated with KErrCompletion that sufficient |
706 // The protocol has indicated with KErrCompletion that sufficient |
742 // data is available in the buffer to process the transfer immediately. |
707 // data is available in the buffer to process the transfer immediately. |
743 |
|
744 iDataResidue -= iReadBufPtr.Length(); |
|
745 SetReadDataBufPtr(deviceDataLength); |
|
746 |
|
747 iLdd.Read(iStatus, OutEndpoint, iReadBufPtr, deviceDataLength); |
|
748 User::WaitForRequest(iStatus); |
|
749 if (iStatus != KErrNone) |
|
750 { |
|
751 // An error occurred - halt endpoints for reset recovery |
|
752 __PRINT1(_L("Error %d in EReadingData, halt endpoints \n"), iStatus.Int()); |
|
753 SetPermError(); |
|
754 return; |
|
755 } |
|
756 } |
|
757 else if(ret == KErrNotReady) |
|
758 { |
|
759 // The protocol has indicated with KErrNotReady that insufficient |
|
760 // data is available in the buffer, so should wait for it to arrive |
|
761 |
708 |
762 iDataResidue -= iReadBufPtr.Length(); |
709 iDataResidue -= iReadBufPtr.Length(); |
763 ReadData(deviceDataLength); |
710 SetReadDataBufPtr(deviceDataLength); |
764 break; |
711 |
765 } |
712 iLdd.Read(iStatus, OutEndpoint, iReadBufPtr, deviceDataLength); |
766 else |
713 User::WaitForRequest(iStatus); |
767 { |
714 if (iStatus != KErrNone) |
768 // The protocol has indicated that transfer is |
715 { |
769 // complete, so send the CSW response to the host. |
716 // An error occurred - halt endpoints for reset recovery |
770 iDataResidue -= iReadBufPtr.Length(); |
717 OstTrace1(TRACE_SMASSSTORAGE_BOT, E1, "Error %d in EReadingData, halt endpoints", iStatus.Int()); |
771 iReadSetUp = EFalse; |
718 SetPermError(); |
772 |
719 return; |
773 if (ret != KErrNone) |
720 } |
774 { |
721 } |
775 iCmdStatus = ECommandFailed; |
722 else if(ret == KErrNotReady) |
776 } |
723 { |
777 |
724 // The protocol has indicated with KErrNotReady that insufficient |
778 if (iDataResidue) |
725 // data is available in the buffer, so should wait for it to arrive |
779 { |
726 |
780 __PRINT(_L("Discarding residue")); |
727 iDataResidue -= iReadBufPtr.Length(); |
781 // we have to read as much data as available that host PC sends; |
728 ReadData(deviceDataLength); |
782 // otherwise, bulk-out endpoint will need to keep sending NAK back. |
729 break; |
783 ReadAndDiscardData(iDataResidue); |
730 } |
784 } |
731 else |
785 SendCSW(iCbwTag, iDataResidue, iCmdStatus); |
732 { |
786 break; |
733 // The protocol has indicated that transfer is |
787 } |
734 // complete, so send the CSW response to the host. |
788 } |
735 iDataResidue -= iReadBufPtr.Length(); |
789 |
736 iReadSetUp = EFalse; |
790 } |
737 |
|
738 if (ret != KErrNone) |
|
739 { |
|
740 iCmdStatus = ECommandFailed; |
|
741 } |
|
742 |
|
743 if (iDataResidue) |
|
744 { |
|
745 OstTrace0(TRACE_SMASSSTORAGE_BOT, E2, "Discarding residue"); |
|
746 // we have to read as much data as available that host PC sends; |
|
747 // otherwise, bulk-out endpoint will need to keep sending NAK back. |
|
748 ReadAndDiscardData(iDataResidue); |
|
749 } |
|
750 SendCSW(iCbwTag, iDataResidue, iCmdStatus); |
|
751 break; |
|
752 } |
|
753 } |
|
754 |
|
755 } |
791 |
756 |
792 void CBulkOnlyTransportUsbcLdd::DiscardData(TUint aLength) |
757 void CBulkOnlyTransportUsbcLdd::DiscardData(TUint aLength) |
793 { |
758 { |
794 iBuf.SetLength(KBOTMaxBufSize); |
759 iBuf.SetLength(KBOTMaxBufSize); |
795 TUint c = 0; |
760 TUint c = 0; |
796 TRequestStatus status; |
761 TRequestStatus status; |
797 while (c < aLength) |
762 while (c < aLength) |
798 { |
763 { |
799 TInt len; |
764 TInt len; |
800 if (aLength - c > KBOTMaxBufSize) |
765 if (aLength - c > KBOTMaxBufSize) |
801 { |
766 { |
802 len = KBOTMaxBufSize; |
767 len = KBOTMaxBufSize; |
803 } |
768 } |
804 else |
769 else |
805 { |
770 { |
806 len = aLength - c; |
771 len = aLength - c; |
807 } |
772 } |
808 |
773 |
809 iLdd.Read(status, OutEndpoint, iBuf, len); |
774 iLdd.Read(status, OutEndpoint, iBuf, len); |
810 User::WaitForRequest(status); |
775 User::WaitForRequest(status); |
811 c += KBOTMaxBufSize; |
776 c += KBOTMaxBufSize; |
812 } |
777 } |
813 } |
778 } |
814 |
779 |
815 void CBulkOnlyTransportUsbcLdd::WriteToClient(TUint aLength) |
780 void CBulkOnlyTransportUsbcLdd::WriteToClient(TUint aLength) |
816 { |
781 { |
817 SetDataBufPtr(); |
782 SetDataBufPtr(); |
818 iLdd.Read(iStatus, OutEndpoint, iDataBufPtr, aLength); |
783 iLdd.Read(iStatus, OutEndpoint, iDataBufPtr, aLength); |
819 User::WaitForRequest(iStatus); |
784 User::WaitForRequest(iStatus); |
820 iProtocol->ReadComplete(KErrGeneral); |
785 iProtocol->ReadComplete(KErrGeneral); |
821 } |
786 } |
822 |
787 |
823 #ifdef MSDC_MULTITHREADED |
788 #ifdef MSDC_MULTITHREADED |
824 void CBulkOnlyTransportUsbcLdd::GetBufferPointers(TPtr8& aDes1, TPtr8& aDes2) |
789 void CBulkOnlyTransportUsbcLdd::GetBufferPointers(TPtr8& aDes1, TPtr8& aDes2) |
825 { |
790 { |
826 aDes1.Set((TUint8*) iDataBuf1.Ptr(), KMaxBufSize, KMaxBufSize); |
791 aDes1.Set(iBulkMm.Buf1(), KMaxBufSize, KMaxBufSize); |
827 aDes2.Set((TUint8*) iDataBuf2.Ptr(), KMaxBufSize, KMaxBufSize); |
792 aDes2.Set(iBulkMm.Buf2(), KMaxBufSize, KMaxBufSize); |
828 } |
793 } |
829 #endif |
794 #endif |
830 |
795 |
831 void CBulkOnlyTransportUsbcLdd::Activate(TRequestStatus& aStatus, TUint& aDeviceState) |
796 void CBulkOnlyTransportUsbcLdd::Activate(TRequestStatus& aStatus, TUint& aDeviceState) |
832 { |
797 { |
833 iLdd.AlternateDeviceStatusNotify(aStatus, aDeviceState); |
798 iLdd.AlternateDeviceStatusNotify(aStatus, aDeviceState); |
834 } |
799 } |
835 |
800 |
836 |
801 |
837 void CBulkOnlyTransportUsbcLdd::Cancel() |
802 void CBulkOnlyTransportUsbcLdd::Cancel() |
838 { |
803 { |
839 iLdd.AlternateDeviceStatusNotifyCancel(); |
804 iLdd.AlternateDeviceStatusNotifyCancel(); |
840 } |
805 } |
841 |
806 |
842 |
807 |
843 |
808 |
844 |
809 |