52 @param aBuffer Input buffer |
64 @param aBuffer Input buffer |
53 @param aTarget Unpacked header. |
65 @param aTarget Unpacked header. |
54 @return Error. |
66 @return Error. |
55 */ |
67 */ |
56 TInt TUsbRequestHdr::Decode(const TDesC8& aBuffer) |
68 TInt TUsbRequestHdr::Decode(const TDesC8& aBuffer) |
57 { |
69 { |
58 if (aBuffer.Length() < static_cast<TInt>(KRequestHdrSize)) |
70 if (aBuffer.Length() < static_cast<TInt>(KRequestHdrSize)) |
59 { |
71 { |
60 __PRINT1(_L("TUsbRequestHdr::Decode buffer invalid length %d"), aBuffer.Length()); |
72 OstTrace1(TRACE_SMASSSTORAGE_USB, TUSBREQUESTHDR_DECODE_ERR, |
61 return KErrGeneral; |
73 "ERROR: USB DEVICE REQUEST invalid length 0x%x", aBuffer.Length()); |
62 } |
74 return KErrGeneral; |
63 |
75 } |
64 iRequestType = aBuffer[0]; |
76 |
65 iRequest = static_cast<TEp0Request>(aBuffer[1]); |
77 iRequestType = aBuffer[0]; |
66 iValue = static_cast<TUint16>(aBuffer[2] + (aBuffer[3] << 8)); |
78 iRequest = static_cast<TEp0Request>(aBuffer[1]); |
67 iIndex = static_cast<TUint16>(aBuffer[4] + (aBuffer[5] << 8)); |
79 iValue = static_cast<TUint16>(aBuffer[2] + (aBuffer[3] << 8)); |
68 iLength = static_cast<TUint16>(aBuffer[6] + (aBuffer[7] << 8)); |
80 iIndex = static_cast<TUint16>(aBuffer[4] + (aBuffer[5] << 8)); |
69 __PRINT5(_L("type=%d request=%d value=%d index=%d length=%d"), iRequestType,iRequest,iValue,iIndex,iLength); |
81 iLength = static_cast<TUint16>(aBuffer[6] + (aBuffer[7] << 8)); |
70 |
82 OstTraceExt5(TRACE_SMASSSTORAGE_USB, TUSBREQUESTHDR_DECODE, |
71 return KErrNone; |
83 "USB DEVICE REQUEST type=0x%x request=0x%x value=%d index=%d length=%d", |
72 } |
84 iRequestType, iRequest, iValue, iIndex, iLength); |
|
85 |
|
86 return KErrNone; |
|
87 } |
73 |
88 |
74 |
89 |
75 /** |
90 /** |
76 This function determines whether data is required by the host in response |
91 This function determines whether data is required by the host in response |
77 to a message header. |
92 to a message header. |
78 |
93 |
79 @return TBool Flag indicating whether a data response required. |
94 @return TBool Flag indicating whether a data response required. |
80 */ |
95 */ |
81 TBool TUsbRequestHdr::IsDataResponseRequired() const |
96 TBool TUsbRequestHdr::IsDataResponseRequired() const |
82 |
97 |
83 { |
98 { |
84 return (iRequestType & 0x80) ? (TBool)ETrue : (TBool)EFalse; |
99 return (iRequestType & 0x80) ? (TBool)ETrue : (TBool)EFalse; |
85 } |
100 } |
86 |
101 |
87 //------------------------------------- |
102 //------------------------------------- |
88 /** |
103 /** |
89 Create an object of a class derived from CBulkOnlyTransport (default to CBulkOnlyTransportUsbcLdd object) |
104 Create an object of a class derived from CBulkOnlyTransport (default to CBulkOnlyTransportUsbcLdd object) |
90 @param aNumDrives - The number of drives available for MS |
105 @param aNumDrives - The number of drives available for MS |
91 @param aController - reference to the parent |
106 @param aController - reference to the parent |
92 @return pointer to newly created derived class object |
107 @return pointer to newly created derived class object |
93 */ |
108 */ |
94 CBulkOnlyTransport* CBulkOnlyTransport::NewL(TInt aNumDrives,CUsbMassStorageController& aController) |
109 CBulkOnlyTransport* CBulkOnlyTransport::NewL(TInt aNumDrives,CUsbMassStorageController& aController) |
95 { |
110 { |
96 __FNLOG("CBulkOnlyTransport::NewL()"); |
111 return NewL(aNumDrives,aController, (CUsbMassStorageController::TTransportldd) 1); |
97 |
112 } |
98 return NewL(aNumDrives,aController, (CUsbMassStorageController::TTransportldd) 1); |
113 |
99 } |
114 /** |
100 |
115 Create an object of a class derived from CBulkOnlyTransport |
101 /** |
|
102 Create an object of a class derived from CBulkOnlyTransport |
|
103 @param aNumDrives - The number of drives available for MS |
116 @param aNumDrives - The number of drives available for MS |
104 @param aController - reference to the parent |
117 @param aController - reference to the parent |
105 @param aTransportLddFlag - Type of usb client ldd |
118 @param aTransportLddFlag - Type of usb client ldd |
106 @return pointer to newly created derived class object |
119 @return pointer to newly created derived class object |
107 */ |
120 */ |
108 CBulkOnlyTransport* CBulkOnlyTransport::NewL(TInt aNumDrives,CUsbMassStorageController& aController, CUsbMassStorageController::TTransportldd aTransportLddFlag) |
121 CBulkOnlyTransport* CBulkOnlyTransport::NewL(TInt aNumDrives,CUsbMassStorageController& aController, CUsbMassStorageController::TTransportldd aTransportLddFlag) |
109 { |
122 { |
110 __FNLOG("CBulkOnlyTransport::NewL()"); |
123 if (aNumDrives <=0 || static_cast<TUint>(aNumDrives) > KUsbMsMaxDrives) |
111 |
124 { |
112 if (aNumDrives <=0 || static_cast<TUint>(aNumDrives) > KUsbMsMaxDrives) |
125 User::Leave(KErrArgument); |
113 { |
126 } |
114 User::Leave(KErrArgument); |
|
115 } |
|
116 |
127 |
117 #if !defined(__WINS__) && !defined(__X86__) |
128 #if !defined(__WINS__) && !defined(__X86__) |
118 CBulkOnlyTransportUsbcScLdd* scTransport; |
129 CBulkOnlyTransportUsbcScLdd* scTransport; |
119 #endif |
130 #endif |
120 CBulkOnlyTransportUsbcLdd* nonscTransport; |
131 CBulkOnlyTransportUsbcLdd* nonscTransport; |
121 switch (aTransportLddFlag) |
132 switch (aTransportLddFlag) |
122 { |
133 { |
123 case 1: |
134 case 1: |
124 nonscTransport = new(ELeave) CBulkOnlyTransportUsbcLdd(aNumDrives, aController); |
135 nonscTransport = new(ELeave) CBulkOnlyTransportUsbcLdd(aNumDrives, aController); |
125 return nonscTransport; |
136 OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_NEWL1, "CBulkOnlyTransportUsbcLdd created."); |
|
137 return nonscTransport; |
126 #if !defined(__WINS__) && !defined(__X86__) |
138 #if !defined(__WINS__) && !defined(__X86__) |
127 case 2: |
139 case 2: |
128 scTransport = new(ELeave) CBulkOnlyTransportUsbcScLdd(aNumDrives, aController); |
140 scTransport = new(ELeave) CBulkOnlyTransportUsbcScLdd(aNumDrives, aController); |
129 return scTransport; |
141 OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_NEWL2, "CBulkOnlyTransportUsbcScLdd created."); |
|
142 return scTransport; |
130 #endif |
143 #endif |
131 default: |
144 default: |
132 __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsCBulkOnlyTransportNull)); |
145 __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsCBulkOnlyTransportNull)); |
133 return NULL; |
146 return NULL; |
134 |
147 |
135 } |
148 } |
136 } |
149 } |
137 |
150 |
138 |
151 |
139 TInt CBulkOnlyTransport::InitialiseTransportL(TInt aTransportLddFlag) |
152 TInt CBulkOnlyTransport::InitialiseTransportL(TInt aTransportLddFlag) |
140 { |
153 { |
141 __FNLOG("CBulkOnlyTransportUsbcScLdd::InitialiseTransportL()"); |
154 TInt ret = KErrNone; |
142 TInt ret = KErrNone; |
155 MTransportBase* transport; |
143 MTransportBase* transport; |
156 iController.GetTransport(transport); |
144 iController.GetTransport(transport); |
157 switch (aTransportLddFlag) |
145 switch (aTransportLddFlag) |
158 { |
146 { |
|
147 #if !defined(__WINS__) && !defined(__X86__) |
159 #if !defined(__WINS__) && !defined(__X86__) |
148 case 2: |
160 case 2: |
149 ret = ((CBulkOnlyTransportUsbcScLdd*) transport)->Ldd().Open(0); |
161 ret = ((CBulkOnlyTransportUsbcScLdd*) transport)->Ldd().Open(0); |
150 if (ret != KErrNone) |
162 if (ret != KErrNone) |
151 { |
163 { |
152 return ret; |
164 return ret; |
153 } |
165 } |
154 else |
166 else |
155 { |
167 { |
156 ((CBulkOnlyTransportUsbcScLdd*) transport)->Ldd().Close(); |
168 ((CBulkOnlyTransportUsbcScLdd*) transport)->Ldd().Close(); |
157 CleanupStack::PushL(transport); |
169 CleanupStack::PushL(transport); |
158 ((CBulkOnlyTransportUsbcScLdd*) transport)->ConstructL(); |
170 ((CBulkOnlyTransportUsbcScLdd*) transport)->ConstructL(); |
159 CleanupStack::Pop(transport); |
171 CleanupStack::Pop(transport); |
160 return ret; |
172 return ret; |
161 } |
173 } |
162 #endif |
174 #endif |
163 case 1: |
175 case 1: |
164 ret = ((CBulkOnlyTransportUsbcLdd*) transport)->Ldd().Open(0); |
176 ret = ((CBulkOnlyTransportUsbcLdd*) transport)->Ldd().Open(0); |
165 if (ret != KErrNone) |
177 if (ret != KErrNone) |
166 { |
178 { |
167 return ret; |
179 return ret; |
168 } |
180 } |
169 else |
181 else |
170 { |
182 { |
171 ((CBulkOnlyTransportUsbcLdd*) transport)->Ldd().Close(); |
183 ((CBulkOnlyTransportUsbcLdd*) transport)->Ldd().Close(); |
172 CleanupStack::PushL(transport); |
184 CleanupStack::PushL(transport); |
173 ((CBulkOnlyTransportUsbcLdd*) transport)->ConstructL(); |
185 ((CBulkOnlyTransportUsbcLdd*) transport)->ConstructL(); |
174 CleanupStack::Pop(transport); |
186 CleanupStack::Pop(transport); |
175 return ret; |
187 return ret; |
176 } |
188 } |
177 default: |
189 default: |
178 return KErrNotFound; |
190 return KErrNotFound; |
179 } |
191 } |
180 } |
192 } |
181 |
193 |
182 /** |
194 /** |
183 c'tor |
195 c'tor |
184 @param aNumDrives - The number of drives available for MS |
196 @param aNumDrives - The number of drives available for MS |
185 @param aController - reference to the parent |
197 @param aController - reference to the parent |
186 */ |
198 */ |
187 CBulkOnlyTransport::CBulkOnlyTransport(TInt aNumDrives,CUsbMassStorageController& aController): |
199 CBulkOnlyTransport::CBulkOnlyTransport(TInt aNumDrives,CUsbMassStorageController& aController): |
188 CActive(EPriorityStandard), |
200 CActive(EPriorityStandard), |
189 iMaxLun(aNumDrives-1), |
201 iMaxLun(aNumDrives-1), |
190 iController(aController), |
202 iController(aController), |
191 iStallAllowed(ETrue), |
203 iStallAllowed(ETrue), |
192 iInterfaceConfigured(EFalse), |
204 iInterfaceConfigured(EFalse), |
193 iCommandBufPtr(NULL,0), |
205 iCommandBufPtr(NULL,0), |
194 iDataBufPtr(NULL,0), |
206 iDataBufPtr(NULL,0), |
195 iCswBufPtr(NULL,0), |
207 iCswBufPtr(NULL,0), |
196 iPaddingBufPtr(NULL,0), |
208 iPaddingBufPtr(NULL,0), |
197 iWriteBufPtr(NULL,0), |
209 iWriteBufPtr(NULL,0), |
198 iReadBufPtr(NULL, 0), |
210 iReadBufPtr(NULL, 0), |
199 iCbwBufPtr(NULL,0) |
211 iCbwBufPtr(NULL,0) |
200 { |
212 { |
201 __FNLOG("CBulkOnlyTransport::CBulkOnlyTransport"); |
213 } |
202 } |
|
203 |
214 |
204 /** |
215 /** |
205 Destructor |
216 Destructor |
206 */ |
217 */ |
207 CBulkOnlyTransport::~CBulkOnlyTransport() |
218 CBulkOnlyTransport::~CBulkOnlyTransport() |
208 { |
219 { |
209 } |
220 } |
210 |
221 |
211 |
222 |
212 /** |
223 /** |
213 Called by the protocol after processing the packet to indicate that more data is required. |
224 Called by the protocol after processing the packet to indicate that more data is required. |
214 |
225 |
215 @param aData reference to the data buffer. |
226 @param aData reference to the data buffer. |
216 */ |
227 */ |
217 void CBulkOnlyTransport::SetupReadData(TUint aLength) |
228 void CBulkOnlyTransport::SetupReadData(TUint aLength) |
218 { |
229 { |
219 __FNLOG("CBulkOnlyTransport::SetupReadData"); |
230 OstTrace1(TRACE_SMASSSTORAGE_BOTDATA, CBULKONLYTRANSPORT_SETUPREADDATA, |
220 __PRINT1(_L("Length = %d (bytes)\n"), aLength); |
231 "BOT SetupReadData Length = 0x%x bytes", aLength); |
221 iBufSize = aLength; |
232 iBufSize = aLength; |
222 iReadSetUp = ETrue; |
233 iReadSetUp = ETrue; |
223 } |
234 } |
224 |
235 |
225 |
236 |
226 /** |
237 /** |
227 Called by the protocol after processing the packet to indicate that data should be written to the host. |
238 Called by the protocol after processing the packet to indicate that data should be written to the host. |
228 |
239 |
229 @param aData reference to the data buffer. |
240 @param aData reference to the data buffer. |
230 */ |
241 */ |
231 void CBulkOnlyTransport::SetupWriteData(TPtrC8& aData) |
242 void CBulkOnlyTransport::SetupWriteData(TPtrC8& aData) |
232 { |
243 { |
233 __FNLOG("CBulkOnlyTransport::SetupWriteData"); |
244 OstTrace1(TRACE_SMASSSTORAGE_BOTDATA, CBULKONLYTRANSPORT_SETUPWRITEDATA, |
234 __PRINT1(_L("Length = %d (bytes)\n"), aData.Length()); |
245 "BOT SetupWriteData Length = 0x%x bytes", aData.Length()); |
235 iWriteBufPtr.Set(aData); |
246 iWriteBufPtr.Set(aData); |
236 iWriteSetUp = ETrue; |
247 iWriteSetUp = ETrue; |
237 } |
248 } |
238 |
249 |
239 |
250 |
240 TInt CBulkOnlyTransport::Start() |
251 TInt CBulkOnlyTransport::Start() |
241 { |
252 { |
242 __FNLOG("CBulkOnlyTransport::Start"); |
253 OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_START, "Start..."); |
243 |
254 if (!iProtocol) |
244 TInt err = KErrNone; |
255 { |
245 |
256 return KErrBadHandle; //protocol should be set up before start |
246 if (!iProtocol) |
257 } |
247 { |
258 |
248 return KErrBadHandle; //protocol should be set up before start |
259 if (IsActive()) |
249 } |
260 { |
250 |
261 OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_START1, "Error: active before start!"); |
251 if (IsActive()) |
262 return KErrInUse; |
252 { |
263 } |
253 __PRINT(_L("CBulkOnlyTransport::Start - active before start!\n")); |
264 |
254 return KErrInUse; |
265 TInt err = KErrNone; |
255 } |
266 if ((err = SetupConfigurationDescriptor()) != KErrNone || |
256 |
267 (err = SetupInterfaceDescriptors()) != KErrNone ) |
257 if ((err = SetupConfigurationDescriptor()) != KErrNone || |
268 { |
258 (err = SetupInterfaceDescriptors()) != KErrNone ) |
269 OstTrace1(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_START2, "Error: descriptors setup failed %d", err); |
259 { |
270 return err; |
260 __PRINT(_L("CBulkOnlyTransport::Start - Error during descriptors setup!\n")); |
271 } |
261 return err; |
272 |
262 } |
273 AllocateEndpointResources(); |
263 |
274 ActivateDeviceStateNotifier(); // activate notifier wich will wait until USB became configured |
264 AllocateEndpointResources(); |
275 TUsbcDeviceState deviceStatus = EUsbcDeviceStateDefault; |
265 ActivateDeviceStateNotifier(); // activate notifier wich will wait until USB became configured |
276 err = GetDeviceStatus(deviceStatus); |
266 TUsbcDeviceState deviceStatus = EUsbcDeviceStateDefault; |
277 if (err == KErrNone && deviceStatus == EUsbcDeviceStateConfigured) |
267 err = GetDeviceStatus(deviceStatus); |
278 { |
268 __PRINT1(_L("CBulkOnlyTransport::Start - Device status = %d\n"), deviceStatus); |
279 err = HwStart(); |
269 if (err == KErrNone && deviceStatus == EUsbcDeviceStateConfigured) |
280 } |
270 { |
|
271 __PRINT(_L("CBulkOnlyTransport::Start - Starting bulk only transport\n")); |
|
272 err = HwStart(); |
|
273 } |
|
274 |
281 |
275 #ifdef MSDC_MULTITHREADED |
282 #ifdef MSDC_MULTITHREADED |
276 TPtr8 aDes1(NULL,0); |
283 TPtr8 aDes1(NULL,0); |
277 TPtr8 aDes2(NULL,0); |
284 TPtr8 aDes2(NULL,0); |
278 GetBufferPointers(aDes1, aDes2); |
285 GetBufferPointers(aDes1, aDes2); |
279 iProtocol->InitializeBufferPointers(aDes1, aDes2); // have to pass pointer to memory not offsets to initialise TPtr, and lengths |
286 iProtocol->InitializeBufferPointers(aDes1, aDes2); // have to pass pointer to memory not offsets to initialise TPtr, and lengths |
280 #endif |
287 #endif |
281 |
288 |
282 iInterfaceConfigured = ETrue; |
289 iInterfaceConfigured = ETrue; |
283 return err; |
290 return err; |
284 } |
291 } |
285 |
292 |
286 TInt CBulkOnlyTransport::HwStart(TBool aDiscard) |
293 TInt CBulkOnlyTransport::HwStart(TBool aDiscard) |
287 { |
294 { |
288 __FNLOG("CBulkOnlyTransport::HwStart"); |
295 TInt lun = MaxLun(); |
289 |
296 OstTrace1(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_HWSTART, "HwStart MAX LUN=%d", lun); |
|
297 do |
|
298 { |
|
299 Controller().DriveManager().Connect(lun); |
|
300 } |
|
301 while(--lun >= 0); |
|
302 |
|
303 TInt res = StartControlInterface(); |
|
304 |
|
305 iCurrentState = ENone; |
|
306 iWriteSetUp=EFalse; |
|
307 iReadSetUp=EFalse; |
|
308 iStarted = ETrue; |
|
309 |
|
310 if (aDiscard) |
|
311 { |
|
312 FlushData(); |
|
313 } |
|
314 |
|
315 ReadCBW(); |
|
316 return res; |
|
317 } |
|
318 |
|
319 |
|
320 TInt CBulkOnlyTransport::HwStop() |
|
321 { |
|
322 OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_HWSTOP, "HwStop"); |
|
323 if (iStarted) |
|
324 { |
|
325 StopBulkOnlyEndpoint(); |
|
326 CancelControlInterface(); |
|
327 iStarted = EFalse; |
|
328 } |
|
329 return KErrNone; |
|
330 } |
|
331 |
|
332 |
|
333 void CBulkOnlyTransport::StopBulkOnlyEndpoint() |
|
334 { |
290 TInt lun = MaxLun(); |
335 TInt lun = MaxLun(); |
291 do |
336 do |
292 { |
337 { |
293 Controller().DriveManager().Connect(lun); |
338 Controller().DriveManager().Disconnect(lun); |
294 } |
339 } |
295 while(--lun >= 0); |
340 while(--lun >= 0); |
296 |
341 Cancel(); |
297 TInt res = StartControlInterface(); |
342 iProtocol->Cancel(); |
298 |
343 } |
299 iCurrentState = ENone; |
344 |
300 iWriteSetUp=EFalse; |
345 |
301 iReadSetUp=EFalse; |
346 TInt CBulkOnlyTransport::HwSuspend() |
302 iStarted = ETrue; |
347 { |
303 |
348 OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_HWSUSPEND, "HwSuspend"); |
304 if (aDiscard) |
|
305 { |
|
306 FlushData(); |
|
307 } |
|
308 |
|
309 ReadCBW(); |
|
310 return res; |
|
311 } |
|
312 |
|
313 |
|
314 TInt CBulkOnlyTransport::HwStop() |
|
315 { |
|
316 __FNLOG("CBulkOnlyTransport::HwStop"); |
|
317 if (iStarted) |
|
318 { |
|
319 StopBulkOnlyEndpoint(); |
|
320 CancelControlInterface(); |
|
321 iStarted = EFalse; |
|
322 } |
|
323 return KErrNone; |
|
324 } |
|
325 |
|
326 |
|
327 void CBulkOnlyTransport::StopBulkOnlyEndpoint() |
|
328 { |
|
329 __FNLOG("CBulkOnlyTransport::StopBulkOnlyEndpoint"); |
|
330 |
|
331 TInt lun = MaxLun(); |
349 TInt lun = MaxLun(); |
332 do |
350 do |
333 { |
351 { |
334 Controller().DriveManager().Disconnect(lun); |
352 Controller().DriveManager().Disconnect(lun); |
335 } |
353 } |
336 while(--lun >= 0); |
354 while(--lun >= 0); |
337 Cancel(); |
355 |
338 iProtocol->Cancel(); |
356 return KErrNone; |
339 } |
357 } |
340 |
|
341 |
|
342 TInt CBulkOnlyTransport::HwSuspend() |
|
343 { |
|
344 __FNLOG("CBulkOnlyTransport::HwSuspend"); |
|
345 |
|
346 TInt lun = MaxLun(); |
|
347 do |
|
348 { |
|
349 Controller().DriveManager().Disconnect(lun); |
|
350 } |
|
351 while(--lun >= 0); |
|
352 |
|
353 return KErrNone; |
|
354 } |
|
355 |
358 |
356 |
359 |
357 TInt CBulkOnlyTransport::HwResume() |
360 TInt CBulkOnlyTransport::HwResume() |
358 { |
361 { |
359 __FNLOG("CBulkOnlyTransport::HwResume"); |
362 OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_HWRESUME, "HwResume"); |
360 |
|
361 TInt lun = MaxLun(); |
363 TInt lun = MaxLun(); |
362 do |
364 do |
363 { |
365 { |
364 Controller().DriveManager().Connect(lun); |
366 Controller().DriveManager().Connect(lun); |
365 } |
367 } |
366 while(--lun >= 0); |
368 while(--lun >= 0); |
367 |
369 |
368 return KErrNone; |
370 return KErrNone; |
369 } |
371 } |
370 |
372 |
371 /** |
373 /** |
372 Stops the Bulk Only Transport |
374 Stops the Bulk Only Transport |
373 */ |
375 */ |
374 TInt CBulkOnlyTransport::Stop() |
376 TInt CBulkOnlyTransport::Stop() |
375 { |
377 { |
376 __FNLOG("CBulkOnlyTransport::Stop"); |
378 OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_STOP, "Stop"); |
377 CancelControlInterface(); |
379 CancelControlInterface(); |
378 CancelDeviceStateNotifier(); |
380 CancelDeviceStateNotifier(); |
379 Cancel(); |
381 Cancel(); |
380 if (iInterfaceConfigured) |
382 if (iInterfaceConfigured) |
381 { |
383 { |
382 ReleaseInterface(); |
384 ReleaseInterface(); |
383 SetupConfigurationDescriptor(ETrue); |
385 SetupConfigurationDescriptor(ETrue); |
384 } |
386 } |
385 iCurrentState = ENone; |
387 iCurrentState = ENone; |
386 iInterfaceConfigured = EFalse; |
388 iInterfaceConfigured = EFalse; |
387 |
389 |
388 return KErrNone; |
390 return KErrNone; |
389 } |
391 } |
390 |
392 |
391 |
393 |
392 |
394 |
393 void CBulkOnlyTransport::DoCancel() |
395 void CBulkOnlyTransport::DoCancel() |
394 { |
396 { |
395 __FNLOG("CBulkOnlyTransport::DoCancel"); |
397 CancelReadWriteRequests(); |
396 CancelReadWriteRequests(); |
398 } |
397 } |
|
398 |
399 |
399 |
400 |
400 void CBulkOnlyTransport::Activate(TInt aReason) |
401 void CBulkOnlyTransport::Activate(TInt aReason) |
401 { |
402 { |
402 SetActive(); |
403 SetActive(); |
464 - Depending on the command, more data may be transmitted/received. |
463 - Depending on the command, more data may be transmitted/received. |
465 - ...or the CSW is sent (if not a data command). |
464 - ...or the CSW is sent (if not a data command). |
466 |
465 |
467 */ |
466 */ |
468 void CBulkOnlyTransport::DecodeCBW() |
467 void CBulkOnlyTransport::DecodeCBW() |
469 { |
468 { |
470 __FNLOG("CBulkOnlyTransport::DecodeCBW"); |
469 SetCbwPtr(); |
471 |
470 |
472 SetCbwPtr(); |
471 if (!CheckCBW()) //check if CBW valid and meaningful |
473 |
472 { |
474 if (!CheckCBW()) //check if CBW valid and meaningful |
|
475 { |
|
476 // CBW not valid or meaningful |
473 // CBW not valid or meaningful |
477 // Specification says: "If the CBW is not valid, the device shall STALL |
474 // Specification says: "If the CBW is not valid, the device shall STALL |
478 // the Bulk-In pipe. Also, the device shall either STALL the Bulk-Out pipe, |
475 // the Bulk-In pipe. Also, the device shall either STALL the Bulk-Out pipe, |
479 // or the device shall accept and discard any Bulk-Out data. The device |
476 // or the device shall accept and discard any Bulk-Out data. The device |
480 // shall maintain this state until a Reset Recovery." |
477 // shall maintain this state until a Reset Recovery." |
481 // Here we keep bulk-in ep stalled and ignore bulk-out ep. |
478 // Here we keep bulk-in ep stalled and ignore bulk-out ep. |
482 SetPermError(); |
479 SetPermError(); |
483 ExpireData((TAny*) (iCbwBufPtr.Ptr())); |
480 ExpireData((TAny*) (iCbwBufPtr.Ptr())); |
484 return; |
481 return; |
485 } |
482 } |
486 |
483 |
487 TPtrC8 aData; |
484 TPtrC8 aData; |
488 aData.Set(&iCbwBufPtr[KCbwCbLengthOffset], KMaxCbwcbLength+1); //prepare data for protocol starting form Length |
485 aData.Set(&iCbwBufPtr[KCbwCbLengthOffset], KMaxCbwcbLength+1); //prepare data for protocol starting form Length |
489 TUint8 lun = static_cast<TUint8>(iCbwBufPtr[13] & 0x0f); |
486 TUint lun = static_cast<TUint8>(iCbwBufPtr[13] & 0x0f); |
490 |
487 |
491 iCbwTag = static_cast<TUint32>(iCbwBufPtr[KCbwTagOffset]) | |
488 iCbwTag = static_cast<TUint32>(iCbwBufPtr[KCbwTagOffset]) | |
492 static_cast<TUint32>(iCbwBufPtr[KCbwTagOffset+1]) <<8 | |
489 static_cast<TUint32>(iCbwBufPtr[KCbwTagOffset+1]) <<8 | |
493 static_cast<TUint32>(iCbwBufPtr[KCbwTagOffset+2]) <<16| |
490 static_cast<TUint32>(iCbwBufPtr[KCbwTagOffset+2]) <<16| |
494 static_cast<TUint32>(iCbwBufPtr[KCbwTagOffset+3]) <<24; |
491 static_cast<TUint32>(iCbwBufPtr[KCbwTagOffset+3]) <<24; |
495 |
492 |
496 TInt i = KCbwDataTransferLengthOffset; |
493 TInt i = KCbwDataTransferLengthOffset; |
497 TUint hostDataLength = static_cast<TUint32>(iCbwBufPtr[i ]) | |
494 TUint32 hostDataLength = static_cast<TUint32>(iCbwBufPtr[i ]) | |
498 static_cast<TUint32>(iCbwBufPtr[i+1]) <<8 | |
495 static_cast<TUint32>(iCbwBufPtr[i+1]) <<8 | |
499 static_cast<TUint32>(iCbwBufPtr[i+2]) <<16 | |
496 static_cast<TUint32>(iCbwBufPtr[i+2]) <<16 | |
500 static_cast<TUint32>(iCbwBufPtr[i+3]) <<24; |
497 static_cast<TUint32>(iCbwBufPtr[i+3]) <<24; |
501 |
498 |
502 TBool dataToHost = iCbwBufPtr[KCbwFlagOffset] & 0x80; |
499 TBool dataToHost = iCbwBufPtr[KCbwFlagOffset] & 0x80; |
503 |
500 |
504 __PRINT4(_L("lun =%d, hostDataLength=%d, CBWtag = 0x%x, dataToHost=%d\n"), lun, hostDataLength, iCbwTag, dataToHost); |
501 OstTrace1(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_DECODECBW, |
505 ////////////////////////////////////////////// |
502 "CBW LUN=%d", lun); |
506 TBool ret = iProtocol->DecodePacket(aData, lun); |
503 OstTraceExt3(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_DECODECBW0, |
507 ////////////////////////////////////////////// |
504 "CBW hostDataLength=0x%x, CBWtag = 0x%x, dataToHost=%d", |
508 ExpireData((TAny*) (iCbwBufPtr.Ptr())); |
505 hostDataLength, iCbwTag, (TUint32)dataToHost); |
509 |
506 ////////////////////////////////////////////// |
510 |
507 TBool ret = iProtocol->DecodePacket(aData, lun); |
511 iStallAllowed = ETrue; |
508 ////////////////////////////////////////////// |
512 |
509 ExpireData((TAny*) (iCbwBufPtr.Ptr())); |
513 if (!ret) |
510 |
514 { |
511 iStallAllowed = ETrue; |
515 __PRINT(_L("Command Failed\n")); |
512 |
516 iCmdStatus = ECommandFailed; |
513 if (!ret) |
517 } |
514 { |
518 else |
515 OstTrace1(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_DECODECBW1, "ERROR: DecodePacket err=%d", ret); |
519 { |
516 iCmdStatus = ECommandFailed; |
520 __PRINT(_L("Command Passed\n")); |
517 } |
521 iCmdStatus = ECommandPassed; |
518 else |
522 } |
519 { |
523 |
520 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW2, "ERROR: DecodePacket OK"); |
524 if (hostDataLength) // Host expected data transfer |
521 iCmdStatus = ECommandPassed; |
525 { |
522 } |
526 if (dataToHost) // send data to host |
523 |
527 { |
524 if (hostDataLength) // Host expected data transfer |
528 if (!iWriteSetUp) //write buffer was not set up |
525 { |
529 { |
526 if (dataToHost) // send data to host |
530 __PRINT(_L("Write buffer was not setup\n")); |
527 { |
531 iDataResidue =hostDataLength; |
528 if (!iWriteSetUp) //write buffer was not set up |
532 __PRINT1(_L("DataResidue (write to host)=%d\n"),iDataResidue); |
529 { |
|
530 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW3, "Write buffer was not setup"); |
|
531 iDataResidue =hostDataLength; |
|
532 OstTrace1(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW4, "DataResidue (write to host)=%d", iDataResidue); |
533 |
533 |
534 //------------------------------------ |
534 //------------------------------------ |
535 if (hostDataLength <= KBOTMaxBufSize) |
535 if (hostDataLength <= KBOTMaxBufSize) |
536 { |
536 { |
537 __PRINT(_L("Case 4 or 8\n")); |
537 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW5, "Case 4 or 8"); |
538 SetPaddingBufPtr(hostDataLength); |
538 SetPaddingBufPtr(hostDataLength); |
539 iPaddingBufPtr.FillZ(hostDataLength); |
539 iPaddingBufPtr.FillZ(hostDataLength); |
540 TPtrC8 ptr(NULL, 0); |
540 TPtrC8 ptr(NULL, 0); |
541 ptr.Set((TUint8*)iPaddingBufPtr.Ptr(), hostDataLength); |
541 ptr.Set((TUint8*)iPaddingBufPtr.Ptr(), hostDataLength); |
542 WriteData(iStatus, ptr, hostDataLength, EFalse); |
542 WriteData(iStatus, ptr, hostDataLength, EFalse); |
543 iStallAllowed = EFalse; |
543 iStallAllowed = EFalse; |
544 if (iReadSetUp) //read buffer WAS set up - case (8) |
544 if (iReadSetUp) //read buffer WAS set up - case (8) |
545 { |
545 { |
546 __PRINT(_L("It is Case 8\n")); |
546 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW6, "It is Case 8"); |
547 iCmdStatus = EPhaseError; |
547 iCmdStatus = EPhaseError; |
548 } |
548 } |
549 return; |
549 return; |
550 } |
550 } |
551 else |
551 else |
552 //------------------------------------ |
552 //------------------------------------ |
553 // Use next block instead of StallEndpointAndWaitForClear(InEndpoint); |
553 // Use next block instead of StallEndpointAndWaitForClear(InEndpoint); |
554 { |
554 { |
555 SetPaddingBufPtr(hostDataLength); |
555 SetPaddingBufPtr(hostDataLength); |
556 iPaddingBufPtr.FillZ(KBOTMaxBufSize); |
556 iPaddingBufPtr.FillZ(KBOTMaxBufSize); |
557 TUint c =0; |
557 TUint c =0; |
558 TRequestStatus status; |
558 TRequestStatus status; |
559 while (c<hostDataLength) |
559 while (c<hostDataLength) |
560 { |
560 { |
561 TInt len; |
561 TInt len; |
562 if (hostDataLength - c > KBOTMaxBufSize) |
562 if (hostDataLength - c > KBOTMaxBufSize) |
563 { |
563 { |
564 len = KBOTMaxBufSize; |
564 len = KBOTMaxBufSize; |
565 } |
565 } |
566 else |
566 else |
567 { |
567 { |
568 len = hostDataLength - c; |
568 len = hostDataLength - c; |
569 } |
569 } |
570 |
570 |
571 TPtrC8 ptr(NULL, 0); |
571 TPtrC8 ptr(NULL, 0); |
572 ptr.Set((TUint8*)iPaddingBufPtr.Ptr(), len); |
572 ptr.Set((TUint8*)iPaddingBufPtr.Ptr(), len); |
573 WriteUsb(status, ptr, len); |
573 WriteUsb(status, ptr, len); |
574 User::WaitForRequest(status); |
574 User::WaitForRequest(status); |
575 c += KBOTMaxBufSize; |
575 c += KBOTMaxBufSize; |
576 } |
576 } |
577 } |
577 } |
578 |
578 |
579 if (iReadSetUp) //read buffer WAS set up - case (8) |
579 if (iReadSetUp) //read buffer WAS set up - case (8) |
580 { |
580 { |
581 __PRINT(_L("Case 8\n")); |
581 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW7, "Case 8"); |
582 SendCSW(iCbwTag, hostDataLength, EPhaseError); |
582 SendCSW(iCbwTag, hostDataLength, EPhaseError); |
583 //don't care to reset any flag - should get reset recovery |
583 //don't care to reset any flag - should get reset recovery |
584 } |
584 } |
585 else // case (4) |
585 else // case (4) |
586 { |
586 { |
587 __PRINT(_L("Case 4\n")); |
587 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW8, "Case 4"); |
588 SendCSW(iCbwTag, hostDataLength, iCmdStatus); |
588 SendCSW(iCbwTag, hostDataLength, iCmdStatus); |
589 } |
589 } |
590 return; |
590 return; |
591 } // if (!iWriteSetUp) |
591 } // if (!iWriteSetUp) |
592 |
592 |
593 //================== |
593 //================== |
594 TUint deviceDataLength = static_cast<TUint>(iWriteBufPtr.Length()); |
594 TUint32 deviceDataLength = iWriteBufPtr.Length(); |
595 iDataResidue =hostDataLength - deviceDataLength ; |
595 iDataResidue =hostDataLength - deviceDataLength ; |
596 __PRINT2(_L("Device data length = %d, DataResidue (write to host)=%d\n"), deviceDataLength, iDataResidue); |
596 OstTraceExt2(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW9, |
597 |
597 "Device data length = 0x%x, DataResidue (write to host)=0x%x", deviceDataLength, iDataResidue); |
598 if (deviceDataLength < hostDataLength && |
598 |
599 hostDataLength < KBOTMaxBufSize ) |
599 if (deviceDataLength < hostDataLength && |
600 { |
600 hostDataLength < KBOTMaxBufSize ) |
601 __PRINT(_L("Case 5 (padding)\n")); |
601 { |
602 SetPaddingBufPtr(hostDataLength); |
602 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW10, "Case 5 (padding)"); |
603 iPaddingBufPtr.Zero(); |
603 SetPaddingBufPtr(hostDataLength); |
604 iPaddingBufPtr.Append(iWriteBufPtr); |
604 iPaddingBufPtr.Zero(); |
605 iStallAllowed = EFalse; |
605 iPaddingBufPtr.Append(iWriteBufPtr); |
606 __PRINT1(_L("iPaddingBufPtr.Length = %d\n"),iPaddingBufPtr.Length()); |
606 iStallAllowed = EFalse; |
607 TPtrC8 ptr(NULL, 0); |
607 OstTrace1(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW11, |
608 ptr.Set((TUint8*)iPaddingBufPtr.Ptr(), hostDataLength); |
608 "iPaddingBufPtr.Length = 0x%x", |
609 WriteData(iStatus, ptr, hostDataLength, EFalse); |
609 iPaddingBufPtr.Length()); |
610 return; |
610 TPtrC8 ptr(NULL, 0); |
611 } |
611 ptr.Set((TUint8*)iPaddingBufPtr.Ptr(), hostDataLength); |
|
612 WriteData(iStatus, ptr, hostDataLength, EFalse); |
|
613 return; |
|
614 } |
612 |
615 |
613 //=================== |
616 //=================== |
614 |
617 |
615 if (deviceDataLength == hostDataLength) //case (6)[==] |
618 if (deviceDataLength == hostDataLength) //case (6)[==] |
616 { |
619 { |
617 __PRINT(_L("Case 6\n")); |
620 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW12, "Case 6"); |
618 WriteData(iStatus, iWriteBufPtr, deviceDataLength); |
621 WriteData(iStatus, iWriteBufPtr, deviceDataLength); |
619 return; |
622 return; |
620 } |
623 } |
621 else if (deviceDataLength < hostDataLength) //case (5)[<] |
624 else if (deviceDataLength < hostDataLength) //case (5)[<] |
622 { |
625 { |
623 __PRINT(_L("Case 5\n")); |
626 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW13, "Case 5"); |
624 WriteData(iStatus, iWriteBufPtr, deviceDataLength, ETrue); // Send ZLP |
627 WriteData(iStatus, iWriteBufPtr, deviceDataLength, ETrue); // Send ZLP |
625 return; |
628 return; |
626 } |
629 } |
627 else // deviceDataLength > hostDataLength - case (7) |
630 else // deviceDataLength > hostDataLength - case (7) |
628 { |
631 { |
629 __PRINT(_L("Case 7\n")); |
632 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW14, "Case 7"); |
630 iCmdStatus = EPhaseError; |
633 iCmdStatus = EPhaseError; |
631 iDataResidue = 0; |
634 iDataResidue = 0; |
632 WriteData(iStatus, iWriteBufPtr, hostDataLength); |
635 WriteData(iStatus, iWriteBufPtr, hostDataLength); |
633 return; |
636 return; |
634 } |
637 } |
635 } |
638 } |
636 else //read data from host |
639 else //read data from host |
637 { |
640 { |
638 if (!iReadSetUp) |
641 if (!iReadSetUp) |
639 { |
642 { |
640 iDataResidue = hostDataLength; |
643 iDataResidue = hostDataLength; |
641 __PRINT(_L("Read buffer was not setup\n")); |
644 OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_DECODECBW15, "Read buffer was not setup"); |
642 // Use next block instead of StallEndpointAndWaitForClear(OutEndpoint); |
645 // Use next block instead of StallEndpointAndWaitForClear(OutEndpoint); |
643 DiscardData(hostDataLength); |
646 DiscardData(hostDataLength); |
644 |
647 |
645 if (iWriteSetUp) //case (10) |
648 if (iWriteSetUp) //case (10) |
646 { |
649 { |
647 __PRINT(_L("case 10\n")); |
650 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW16, "case 10"); |
648 SendCSW(iCbwTag, hostDataLength, EPhaseError); |
651 SendCSW(iCbwTag, hostDataLength, EPhaseError); |
649 } |
652 } |
650 else // case (9) |
653 else // case (9) |
651 { |
654 { |
652 __PRINT(_L("Case 9\n")); |
655 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW17, "Case 9"); |
653 SendCSW(iCbwTag, hostDataLength, iCmdStatus); |
656 SendCSW(iCbwTag, hostDataLength, iCmdStatus); |
654 } |
657 } |
655 |
658 |
656 return; |
659 return; |
657 } |
660 } |
658 |
661 |
659 TUint deviceDataLength = iBufSize; |
662 TUint32 deviceDataLength = iBufSize; |
660 iDataResidue = hostDataLength; // calculate residue later |
663 iDataResidue = hostDataLength; // calculate residue later |
661 |
664 |
662 __PRINT2(_L("deviceDataLength = iBufSize = %d, DataResidue = HDL for now (read from host) =%d\n"),deviceDataLength,iDataResidue); |
665 OstTraceExt2(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW18, |
663 |
666 "deviceDataLength = iBufSize = 0x%x, DataResidue = HDL for now (read from host) =0x%x", |
664 if (deviceDataLength <= hostDataLength) // case (11) and (12) |
667 deviceDataLength, iDataResidue); |
665 { |
668 |
666 __PRINT(_L("Case 11 or 12\n")); |
669 if (deviceDataLength <= hostDataLength) // case (11) and (12) |
667 ReadData(deviceDataLength); |
670 { |
668 return; |
671 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW19, "Case 11 or 12"); |
669 } |
672 ReadData(deviceDataLength); |
670 if (deviceDataLength > hostDataLength) // case (13) |
673 return; |
671 { |
674 } |
672 __PRINT(_L("Case 13\n")); |
675 if (deviceDataLength > hostDataLength) // case (13) |
|
676 { |
|
677 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW20, "Case 13"); |
673 /** |
678 /** |
674 * Comment following line in order to pass compliant test. |
679 * Comment following line in order to pass compliant test. |
675 * As spec said in case 13:"The device may receive data up to a |
680 * As spec said in case 13:"The device may receive data up to a |
676 * total of dCBWDataTransferLength." |
681 * total of dCBWDataTransferLength." |
677 * Here we choose to ignore incoming data. |
682 * Here we choose to ignore incoming data. |
678 */ |
683 */ |
679 //StallEndpointAndWaitForClear(OutEndpoint); //Stall Out endpoint |
684 //StallEndpointAndWaitForClear(OutEndpoint); //Stall Out endpoint |
680 if (iReadSetUp) |
685 if (iReadSetUp) |
681 { |
686 { |
682 WriteToClient(hostDataLength); |
687 WriteToClient(hostDataLength); |
683 iReadSetUp = EFalse; |
688 iReadSetUp = EFalse; |
684 } |
689 } |
685 SendCSW(iCbwTag, hostDataLength, EPhaseError); |
690 SendCSW(iCbwTag, hostDataLength, EPhaseError); |
686 return; |
691 return; |
687 } |
692 } |
688 } |
693 } |
689 } |
694 } |
690 else // Host expected no data transfer |
695 else // Host expected no data transfer |
691 { |
696 { |
692 __PRINT(_L("No data transfer expected\n")); |
697 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW21, "No data transfer expected"); |
693 iDataResidue = 0; |
698 iDataResidue = 0; |
694 if (iWriteSetUp || iReadSetUp) // case (2) and (3) |
699 if (iWriteSetUp || iReadSetUp) // case (2) and (3) |
695 { |
700 { |
696 __PRINT(_L("Case 2 or 3\n")); |
701 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW22, "Case 2 or 3"); |
697 SendCSW(iCbwTag, 0, EPhaseError); |
702 SendCSW(iCbwTag, 0, EPhaseError); |
698 } |
703 } |
699 else |
704 else |
700 { |
705 { |
701 __PRINT(_L("Case 1\n")); |
706 OstTrace0(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_DECODECBW23, "Case 1"); |
702 SendCSW(iCbwTag, 0, iCmdStatus); //case (1) |
707 SendCSW(iCbwTag, 0, iCmdStatus); //case (1) |
703 } |
708 } |
704 } |
709 } |
705 } |
710 } |
706 |
711 |
707 |
712 |
708 /** |
713 /** |
709 Check if CBW Valid and Meaningful. |
714 Check if CBW Valid and Meaningful. |
710 |
715 |
711 @return ETrue if CBW is Valid and Meaningful, EFalse otherwise |
716 @return ETrue if CBW is Valid and Meaningful, EFalse otherwise |
712 */ |
717 */ |
713 TBool CBulkOnlyTransport::CheckCBW() |
718 TBool CBulkOnlyTransport::CheckCBW() |
714 { |
719 { |
715 __FNLOG("CBulkOnlyTransport::CheckCBW"); |
|
716 |
|
717 // |
720 // |
718 // Check valid |
721 // Check valid |
719 // |
722 // |
720 |
723 |
721 // Check length |
724 // Check length |
722 if ((TUint) (iCbwBufPtr.Length()) != KCbwLength) |
725 if ((TUint) (iCbwBufPtr.Length()) != KCbwLength) |
723 { |
726 { |
724 __PRINT2(_L("Bad length: %d != KCbwLength"), iCbwBufPtr.Length(), KCbwLength); |
727 OstTrace1(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_CHECKCBW, "ERROR Bad length: 0x%x != KCbwLength", iCbwBufPtr.Length()); |
725 return EFalse; |
728 return EFalse; |
726 } |
729 } |
727 |
730 |
728 // Check signature |
731 // Check signature |
729 TInt i = KCbwSignatureOffset; |
732 TInt i = KCbwSignatureOffset; |
730 if (iCbwBufPtr[i ] != 0x55 || // CBW Singature from USB Bulk-Only Transport spec |
733 if (iCbwBufPtr[i ] != 0x55 || // CBW Singature from USB Bulk-Only Transport spec |
731 iCbwBufPtr[i+1] != 0x53 || |
734 iCbwBufPtr[i+1] != 0x53 || |
732 iCbwBufPtr[i+2] != 0x42 || |
735 iCbwBufPtr[i+2] != 0x42 || |
733 iCbwBufPtr[i+3] != 0x43) |
736 iCbwBufPtr[i+3] != 0x43) |
734 { |
737 { |
735 __PRINT(_L("Bad signature")); |
738 OstTraceData(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_CHECKCBW1, |
736 __PRINT4(_L(" 0x%x, 0x%x, 0x%x, 0x%x \n"), iCbwBufPtr[i], iCbwBufPtr[i+1], iCbwBufPtr[i+2],iCbwBufPtr[i+3]) |
739 "CBW ERROR: Bad signature %s", &iCbwBufPtr[i], 4); |
737 return EFalse; |
740 return EFalse; |
738 } |
741 } |
739 |
742 |
740 // |
743 // |
741 // Check meaningful |
744 // Check meaningful |
742 // |
745 // |
743 |
746 |
744 // Check reserved bits ( must be zero ) |
747 // Check reserved bits ( must be zero ) |
745 if ((iCbwBufPtr[KCbwLunOffset] & 0xF0) || (iCbwBufPtr[KCbwCbLengthOffset] & 0xE0)) |
748 if ((iCbwBufPtr[KCbwLunOffset] & 0xF0) || (iCbwBufPtr[KCbwCbLengthOffset] & 0xE0)) |
746 { |
749 { |
747 __PRINT(_L("Reserved bits not zero\n")); |
750 OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_CHECKCBW2, "CBW ERROR: Reserved bits not zero"); |
748 return EFalse; |
751 return EFalse; |
749 } |
752 } |
750 |
753 |
751 // check command block length |
754 // check command block length |
752 TInt cbwcbLength = iCbwBufPtr[KCbwCbLengthOffset] & 0x1F; |
755 TInt cbwcbLength = iCbwBufPtr[KCbwCbLengthOffset] & 0x1F; |
753 if (cbwcbLength >KMaxCbwcbLength) |
756 if (cbwcbLength >KMaxCbwcbLength) |
754 { |
757 { |
755 __PRINT(_L("Incorrect block length\n")); |
758 OstTrace0(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_CHECKCBW3, "CBW ERROR: Incorrect block length"); |
756 return EFalse; |
759 return EFalse; |
757 } |
760 } |
758 |
761 |
759 //check LUN |
762 //check LUN |
760 TInt8 lun = static_cast<TUint8>(iCbwBufPtr[KCbwLunOffset] & 0x0f); |
763 TInt8 lun = static_cast<TUint8>(iCbwBufPtr[KCbwLunOffset] & 0x0f); |
761 if (iMaxLun < lun) |
764 if (iMaxLun < lun) |
762 { |
765 { |
763 RDebug::Print(_L("bad lun: %d"), lun); |
766 OstTrace1(TRACE_SMASSSTORAGE_BOT, CBULKONLYTRANSPORT_CHECKCBW4, "CBW ERROR: bad lun: %d", lun); |
764 return EFalse; |
767 return EFalse; |
765 } |
768 } |
766 |
769 |
767 return ETrue; |
770 return ETrue; |
768 } |
771 } |
769 |
772 |
770 |
773 |
771 /** |
774 /** |
772 Initiate stalling of bulk IN endpoint. |
775 Initiate stalling of bulk IN endpoint. |
773 Used when protocol wants to force host to initiate a reset recovery. |
776 Used when protocol wants to force host to initiate a reset recovery. |
774 */ |
777 */ |
775 void CBulkOnlyTransport::SetPermError() |
778 void CBulkOnlyTransport::SetPermError() |
776 { |
779 { |
777 __FNLOG("CBulkOnlyTransport::SetPermError"); |
|
778 iCurrentState = EPermErr; |
780 iCurrentState = EPermErr; |
779 Activate(KErrNone); |
781 Activate(KErrNone); |
780 } |
782 } |
781 |
783 |
782 |
784 |
783 /** |
785 /** |
784 Send data provided by protocol to the host |
786 Send data provided by protocol to the host |
785 |
787 |
786 @param aLength amount of data (in bytes) to be send to host |
788 @param aLength amount of data (in bytes) to be send to host |
787 */ |
789 */ |
788 void CBulkOnlyTransport::WriteData(TRequestStatus& aStatus, TPtrC8& aDes, TUint aLength, TBool aZlpRequired) |
790 void CBulkOnlyTransport::WriteData(TRequestStatus& aStatus, TPtrC8& aDes, TUint aLength, TBool aZlpRequired) |
789 { |
791 { |
790 __FNLOG("CBulkOnlyTransport::WriteData"); |
792 if (IsActive()) |
791 |
793 { |
792 if (IsActive()) |
794 __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive)); |
793 { |
795 return; |
794 __PRINT(_L("Still active\n")); |
796 } |
795 __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive)); |
797 WriteUsb(aStatus, aDes, aLength, aZlpRequired); |
796 return; |
798 iCurrentState = EWritingData; |
797 } |
799 SetActive(); |
798 WriteUsb(aStatus, aDes, aLength, aZlpRequired); |
800 } |
799 iCurrentState = EWritingData; |
|
800 SetActive(); |
|
801 } |
|
802 |
801 |
803 |
802 |
804 /** |
803 /** |
805 Send Command Status Wrapper to the host |
804 Send Command Status Wrapper to the host |
806 |
805 |
808 @param aDataResidue the difference between the amount of data expected by the |
807 @param aDataResidue the difference between the amount of data expected by the |
809 host, and the actual amount of data processed by the device. |
808 host, and the actual amount of data processed by the device. |
810 @param aStatus indicates the success or failure of the command. |
809 @param aStatus indicates the success or failure of the command. |
811 */ |
810 */ |
812 void CBulkOnlyTransport::SendCSW(TUint aTag, TUint aDataResidue, TCswStatus aStatus) |
811 void CBulkOnlyTransport::SendCSW(TUint aTag, TUint aDataResidue, TCswStatus aStatus) |
813 { |
812 { |
814 __FNLOG("CBulkOnlyTransport::SendCSW"); |
813 OstTraceExt2(TRACE_SMASSSTORAGE_BOT1, CBULKONLYTRANSPORT_SENDCSW, |
815 __PRINT2(_L("DataResidue = %d, Status = %d \n"), aDataResidue, aStatus); |
814 "CSW DataResidue = 0x%x, Status = %d", aDataResidue, aStatus); |
816 |
815 |
817 if (IsActive()) |
816 if (IsActive()) |
818 { |
817 { |
819 __PRINT(_L("Still active\n")); |
818 __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive)); |
820 __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsSvrPncCat, EMsBulkOnlyStillActive)); |
819 return; |
821 return; |
820 } |
822 } |
821 |
823 |
822 SetCswBufPtr(KCswLength); |
824 SetCswBufPtr(KCswLength); |
823 TInt i = KCswSingnatureOffset; |
825 TInt i = KCswSingnatureOffset; |
824 iCswBufPtr[i ] = 0x55; // CSW Singature from USB Bulk-Only Transport spec |
826 iCswBufPtr[i ] = 0x55; // CSW Singature from USB Bulk-Only Transport spec |
825 iCswBufPtr[i+1] = 0x53; |
827 iCswBufPtr[i+1] = 0x53; |
826 iCswBufPtr[i+2] = 0x42; |
828 iCswBufPtr[i+2] = 0x42; |
827 iCswBufPtr[i+3] = 0x53; |
829 iCswBufPtr[i+3] = 0x53; |
828 |
830 |
829 i = KCswTagOffset; |
831 i = KCswTagOffset; |
830 |
832 |
831 iCswBufPtr[i ] = static_cast<TUint8>((aTag & 0x000000FF)); |
833 iCswBufPtr[i ] = static_cast<TUint8>((aTag & 0x000000FF)); |
832 iCswBufPtr[i+1] = static_cast<TUint8>((aTag & 0x0000FF00) >> 8); |
834 iCswBufPtr[i+1] = static_cast<TUint8>((aTag & 0x0000FF00) >> 8); |
833 iCswBufPtr[i+2] = static_cast<TUint8>((aTag & 0x00FF0000) >> 16); |
835 iCswBufPtr[i+2] = static_cast<TUint8>((aTag & 0x00FF0000) >> 16); |
834 iCswBufPtr[i+3] = static_cast<TUint8>((aTag & 0xFF000000) >> 24); |
836 iCswBufPtr[i+3] = static_cast<TUint8>((aTag & 0xFF000000) >> 24); |
835 |
837 |
836 i = KCswDataResidueOffset; |
838 i = KCswDataResidueOffset; |
837 iCswBufPtr[i ] = static_cast<TUint8>((aDataResidue & 0x000000FF)); |
839 iCswBufPtr[i ] = static_cast<TUint8>((aDataResidue & 0x000000FF)); |
838 iCswBufPtr[i+1] = static_cast<TUint8>((aDataResidue & 0x0000FF00) >> 8); |
840 iCswBufPtr[i+1] = static_cast<TUint8>((aDataResidue & 0x0000FF00) >> 8); |
839 iCswBufPtr[i+2] = static_cast<TUint8>((aDataResidue & 0x00FF0000) >> 16); |
841 iCswBufPtr[i+2] = static_cast<TUint8>((aDataResidue & 0x00FF0000) >> 16); |
840 iCswBufPtr[i+3] = static_cast<TUint8>((aDataResidue & 0xFF000000) >> 24); |
842 iCswBufPtr[i+3] = static_cast<TUint8>((aDataResidue & 0xFF000000) >> 24); |
841 |
843 |
842 iCswBufPtr[KCswStatusOffset] = static_cast<TUint8>(aStatus); |
844 iCswBufPtr[KCswStatusOffset] = static_cast<TUint8>(aStatus); |
843 |
845 |
844 TPtrC8 ptr(NULL, 0); |
846 TPtrC8 ptr(NULL, 0); |
845 ptr.Set((const TUint8*)iCswBufPtr.Ptr(), KCswLength); |
847 ptr.Set((const TUint8*)iCswBufPtr.Ptr(), KCswLength); |
846 |
848 |
847 WriteUsb(iStatus, ptr, KCswLength); |
849 WriteUsb(iStatus, ptr, KCswLength); |
848 |
850 |
849 iCurrentState = ESendingCSW; |
851 iCurrentState = ESendingCSW; |
850 |
852 |
851 SetActive(); |
853 SetActive(); |
852 } |
854 } |
|
855 |
853 |
856 |
854 |
857 /** |
855 /** |
858 Associates the transport with the protocol. Called during initialization of the controller. |
856 Associates the transport with the protocol. Called during initialization of the controller. |
859 |
857 |
860 @param aProtocol reference to the protocol |
858 @param aProtocol reference to the protocol |
861 */ |
859 */ |
862 void CBulkOnlyTransport::RegisterProtocol(MProtocolBase& aProtocol) |
860 void CBulkOnlyTransport::RegisterProtocol(MProtocolBase& aProtocol) |
863 { |
861 { |
864 __FNLOG("CBulkOnlyTransport::RegisterProtocol"); |
862 iProtocol = &aProtocol; |
865 iProtocol = &aProtocol; |
863 } |
866 } |
|
867 |
864 |
868 |
865 |
869 /** |
866 /** |
870 Used by CControlInterface |
867 Used by CControlInterface |
871 |
868 |
872 @return reference to the controller which instantiate the CBulkOnlyTransport |
869 @return reference to the controller which instantiate the CBulkOnlyTransport |
873 */ |
870 */ |
874 CUsbMassStorageController& CBulkOnlyTransport::Controller() |
871 CUsbMassStorageController& CBulkOnlyTransport::Controller() |
875 { |
872 { |
876 return iController; |
873 return iController; |
877 } |
874 } |
878 |
875 |
879 |
876 |
880 /** |
877 /** |
881 @return the number of logical units supported by the device. |
878 @return the number of logical units supported by the device. |
882 Logical Unit Numbers on the device shall be numbered contiguously starting from LUN |
879 Logical Unit Numbers on the device shall be numbered contiguously starting from LUN |
883 0 to a maximum LUN of 15 (Fh). |
880 0 to a maximum LUN of 15 (Fh). |
884 */ |
881 */ |
885 TInt CBulkOnlyTransport::MaxLun() |
882 TInt CBulkOnlyTransport::MaxLun() |
886 { |
883 { |
887 return iMaxLun; |
884 return iMaxLun; |
888 } |
885 } |
889 |
886 |
890 |
887 |
891 void CBulkOnlyTransport::GetCommandBufPtr(TPtr8& aDes, TUint aLength) // Set pointer to buffer of specified aLength for command |
888 void CBulkOnlyTransport::GetCommandBufPtr(TPtr8& aDes, TUint aLength) // Set pointer to buffer of specified aLength for command |
892 { |
889 { |
893 aDes.Set(SetCommandBufPtr(aLength)); |
890 aDes.Set(SetCommandBufPtr(aLength)); |
894 } |
891 } |
895 |
892 |
896 void CBulkOnlyTransport::GetReadDataBufPtr(TPtr8& aDes) // Set pointer to buffer into which data is to be read from drive (Read10) |
893 void CBulkOnlyTransport::GetReadDataBufPtr(TPtr8& aDes) // Set pointer to buffer into which data is to be read from drive (Read10) |
897 { |
894 { |
898 aDes.Set(SetDataBufPtr()); |
895 aDes.Set(SetDataBufPtr()); |
899 } |
896 } |
900 |
897 |
901 |
898 |
902 void CBulkOnlyTransport::GetWriteDataBufPtr(TPtrC8& aDes) // Set pointer to buffer from which data is to be written to drive (Write10) |
899 void CBulkOnlyTransport::GetWriteDataBufPtr(TPtrC8& aDes) // Set pointer to buffer from which data is to be written to drive (Write10) |
903 { |
900 { |
904 aDes.Set(iReadBufPtr); |
901 aDes.Set(iReadBufPtr); |
905 } |
902 } |
906 |
903 |
907 #ifdef MSDC_MULTITHREADED |
904 #ifdef MSDC_MULTITHREADED |
908 void CBulkOnlyTransport::ProcessReadData(TAny* aAddress) |
905 void CBulkOnlyTransport::ProcessReadData(TAny* aAddress) |
909 { |
906 { |
910 ExpireData(aAddress); |
907 ExpireData(aAddress); |
911 } |
908 } |
912 #endif |
909 #endif |
913 |
910 |
914 |
911 |
915 |
912 |
916 |
913 |