53 @param aController - reference to the parent |
52 @param aController - reference to the parent |
54 @return pointer to newly created object |
53 @return pointer to newly created object |
55 */ |
54 */ |
56 CBulkOnlyTransport* CBulkOnlyTransport::NewL(TInt aNumDrives, |
55 CBulkOnlyTransport* CBulkOnlyTransport::NewL(TInt aNumDrives, |
57 CUsbMassStorageController& aController) |
56 CUsbMassStorageController& aController) |
58 { |
57 { |
59 __MSFNSLOG |
58 if (aNumDrives <=0 || static_cast<TUint>(aNumDrives) > KUsbMsMaxDrives) |
60 if (aNumDrives <=0 || static_cast<TUint>(aNumDrives) > KUsbMsMaxDrives) |
59 { |
61 { |
60 User::Leave(KErrArgument); |
62 User::Leave(KErrArgument); |
61 } |
63 } |
62 CBulkOnlyTransport* self = new(ELeave) CBulkOnlyTransport(aNumDrives, aController); |
64 CBulkOnlyTransport* self = new(ELeave) CBulkOnlyTransport(aNumDrives, aController); |
63 CleanupStack::PushL(self); |
65 CleanupStack::PushL(self); |
64 self->ConstructL(); |
66 self->ConstructL(); |
65 CleanupStack::Pop(self); |
67 CleanupStack::Pop(self); |
66 return self; |
68 return self; |
67 } |
69 } |
|
70 |
68 |
71 #ifdef MSDC_TESTMODE |
69 #ifdef MSDC_TESTMODE |
72 CBulkOnlyTransport* CBulkOnlyTransport::NewL(TInt aNumDrives, |
70 CBulkOnlyTransport* CBulkOnlyTransport::NewL(TInt aNumDrives, |
73 CUsbMassStorageController& aController, |
71 CUsbMassStorageController& aController, |
74 TTestParser* aTestParser) |
72 TTestParser* aTestParser) |
75 { |
73 { |
76 __MSFNSLOG |
74 if (aNumDrives <=0 || static_cast<TUint>(aNumDrives) > KUsbMsMaxDrives) |
77 if (aNumDrives <=0 || static_cast<TUint>(aNumDrives) > KUsbMsMaxDrives) |
75 { |
78 { |
76 User::Leave(KErrArgument); |
79 User::Leave(KErrArgument); |
77 } |
80 } |
78 CBulkOnlyTransport* self = new(ELeave) CBulkOnlyTransport(aNumDrives, |
81 CBulkOnlyTransport* self = new(ELeave) CBulkOnlyTransport(aNumDrives, |
|
82 aController, |
79 aController, |
83 aTestParser); |
80 aTestParser); |
84 CleanupStack::PushL(self); |
81 CleanupStack::PushL(self); |
85 self->ConstructL(); |
82 self->ConstructL(); |
86 CleanupStack::Pop(self); |
83 CleanupStack::Pop(self); |
87 return self; |
84 return self; |
88 } |
85 } |
89 #endif |
86 #endif |
90 |
87 |
91 |
88 |
92 /** |
89 /** |
93 c'tor |
90 c'tor |
94 @param aNumDrives - The number of drives available for MS |
91 @param aNumDrives - The number of drives available for MS |
95 @param aController - reference to the parent |
92 @param aController - reference to the parent |
96 */ |
93 */ |
97 CBulkOnlyTransport::CBulkOnlyTransport(TInt aNumDrives, |
94 CBulkOnlyTransport::CBulkOnlyTransport(TInt aNumDrives, |
98 CUsbMassStorageController& aController): |
95 CUsbMassStorageController& aController): |
99 CActive(EPriorityStandard), |
96 CActive(EPriorityStandard), |
100 iMaxLun(aNumDrives-1), |
97 iMaxLun(aNumDrives-1), |
101 iController(aController), |
98 iController(aController), |
102 iStallAllowed(ETrue) |
99 iStallAllowed(ETrue) |
103 { |
100 { |
104 __MSFNLOG |
101 } |
105 } |
|
106 |
102 |
107 #ifdef MSDC_TESTMODE |
103 #ifdef MSDC_TESTMODE |
108 CBulkOnlyTransport::CBulkOnlyTransport(TInt aNumDrives, |
104 CBulkOnlyTransport::CBulkOnlyTransport(TInt aNumDrives, |
109 CUsbMassStorageController& aController, |
105 CUsbMassStorageController& aController, |
110 TTestParser* aTestParser) |
106 TTestParser* aTestParser) |
111 : CActive(EPriorityStandard), |
107 : CActive(EPriorityStandard), |
112 iMaxLun(aNumDrives-1), |
108 iMaxLun(aNumDrives-1), |
113 iController(aController), |
109 iController(aController), |
114 iStallAllowed(ETrue), |
110 iStallAllowed(ETrue), |
115 iTestParser(aTestParser) |
111 iTestParser(aTestParser) |
116 { |
112 { |
117 __MSFNLOG |
113 } |
118 } |
|
119 #endif |
114 #endif |
120 |
115 |
121 |
116 |
122 /** |
117 /** |
123 Constructs the CBulkOnlyTranspor object |
118 Constructs the CBulkOnlyTranspor object |
124 */ |
119 */ |
125 void CBulkOnlyTransport::ConstructL() |
120 void CBulkOnlyTransport::ConstructL() |
126 { |
121 { |
127 __MSFNLOG |
122 iBotControlInterface = CBotControlInterface::NewL(*this); |
128 iBotControlInterface = CBotControlInterface::NewL(*this); |
123 iDeviceStateNotifier = CActiveDeviceStateNotifier::NewL(*this); |
129 iDeviceStateNotifier = CActiveDeviceStateNotifier::NewL(*this); |
124 CActiveScheduler::Add(this); |
130 CActiveScheduler::Add(this); |
125 } |
131 } |
|
132 |
126 |
133 |
127 |
134 /** |
128 /** |
135 Destructor |
129 Destructor |
136 */ |
130 */ |
137 CBulkOnlyTransport::~CBulkOnlyTransport() |
131 CBulkOnlyTransport::~CBulkOnlyTransport() |
138 { |
132 { |
139 __MSFNLOG |
133 if (iInterfaceConfigured) |
140 if (iInterfaceConfigured) |
134 { |
141 { |
135 Stop(); |
142 Stop(); |
136 } |
143 } |
137 delete iBotControlInterface; |
144 delete iBotControlInterface; |
138 delete iDeviceStateNotifier; |
145 delete iDeviceStateNotifier; |
139 } |
146 } |
|
147 |
140 |
148 |
141 |
149 /** |
142 /** |
150 Set or unset configuration descriptor for USB MassStorage Bulk Only transport |
143 Set or unset configuration descriptor for USB MassStorage Bulk Only transport |
151 |
144 |
152 @param aUnset indicate whether set or unset descriptor |
145 @param aUnset indicate whether set or unset descriptor |
153 @return KErrNone if operation was completed successfully, errorcode otherwise |
146 @return KErrNone if operation was completed successfully, errorcode otherwise |
154 */ |
147 */ |
155 TInt CBulkOnlyTransport::SetupConfigurationDescriptor(TBool aUnset) |
148 TInt CBulkOnlyTransport::SetupConfigurationDescriptor(TBool aUnset) |
156 { |
149 { |
157 __MSFNLOG |
150 TInt ret(KErrNone); |
158 TInt ret(KErrNone); |
151 TInt configDescriptorSize(0); |
159 TInt configDescriptorSize(0); |
152 |
160 |
153 iLdd.GetConfigurationDescriptorSize(configDescriptorSize); |
161 iLdd.GetConfigurationDescriptorSize(configDescriptorSize); |
154 if (static_cast<TUint>(configDescriptorSize) != KUsbDescSize_Config) |
162 if (static_cast<TUint>(configDescriptorSize) != KUsbDescSize_Config) |
155 { |
163 { |
156 return KErrCorrupt; |
164 return KErrCorrupt; |
157 } |
165 } |
158 |
166 |
159 TBuf8<KUsbDescSize_Config> configDescriptor; |
167 TBuf8<KUsbDescSize_Config> configDescriptor; |
160 ret = iLdd.GetConfigurationDescriptor(configDescriptor); |
168 ret = iLdd.GetConfigurationDescriptor(configDescriptor); |
161 if (ret != KErrNone) |
169 if (ret != KErrNone) |
162 { |
170 { |
163 return ret; |
171 return ret; |
164 } |
172 } |
165 |
173 |
166 // I beleive that other fields setted up during LDD initialisation |
174 // I beleive that other fields setted up during LDD initialisation |
167 if (aUnset) |
175 if (aUnset) |
168 { |
176 { |
169 --configDescriptor[KUsbNumInterfacesOffset]; |
177 --configDescriptor[KUsbNumInterfacesOffset]; |
170 } |
178 } |
171 else |
179 else |
172 { |
180 { |
173 ++configDescriptor[KUsbNumInterfacesOffset]; |
181 ++configDescriptor[KUsbNumInterfacesOffset]; |
174 } |
182 } |
175 ret = iLdd.SetConfigurationDescriptor(configDescriptor); |
183 ret = iLdd.SetConfigurationDescriptor(configDescriptor); |
176 |
184 |
177 return ret; |
185 return ret; |
178 } |
186 } |
|
187 |
179 |
188 |
180 |
189 /** |
181 /** |
190 Set up interface descriptor |
182 Set up interface descriptor |
191 |
183 |
192 @return KErrNone if operation was completed successfully, errorcode otherwise |
184 @return KErrNone if operation was completed successfully, errorcode otherwise |
193 */ |
185 */ |
194 TInt CBulkOnlyTransport::SetupInterfaceDescriptors() |
186 TInt CBulkOnlyTransport::SetupInterfaceDescriptors() |
195 { |
187 { |
196 __MSFNLOG |
188 // Device caps |
197 // Device caps |
189 TUsbDeviceCaps d_caps; |
198 TUsbDeviceCaps d_caps; |
190 TInt ret = iLdd.DeviceCaps(d_caps); |
199 TInt ret = iLdd.DeviceCaps(d_caps); |
191 if (ret != KErrNone) |
200 if (ret != KErrNone) |
192 { |
201 { |
193 return ret; |
202 return ret; |
194 } |
203 } |
195 TInt totalEndpoints = d_caps().iTotalEndpoints; |
204 TInt totalEndpoints = d_caps().iTotalEndpoints; |
196 if (totalEndpoints < KRequiredNumberOfEndpoints) |
205 if (totalEndpoints < KRequiredNumberOfEndpoints) |
197 { |
206 { |
198 return KErrHardwareNotAvailable; |
207 return KErrHardwareNotAvailable; |
199 } |
208 } |
200 |
209 |
201 // Endpoint caps |
210 // Endpoint caps |
202 TUsbcEndpointData data[KUsbcMaxEndpoints]; |
211 TUsbcEndpointData data[KUsbcMaxEndpoints]; |
203 TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data)); |
212 TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data)); |
204 ret = iLdd.EndpointCaps(dataptr); |
213 ret = iLdd.EndpointCaps(dataptr); |
205 if (ret != KErrNone) |
214 if (ret != KErrNone) |
206 { |
215 { |
207 return ret; |
216 return ret; |
208 } |
217 } |
209 |
218 |
210 // Set the active interface |
219 // Set the active interface |
211 TUsbcInterfaceInfoBuf ifc; |
220 TUsbcInterfaceInfoBuf ifc; |
212 TInt ep_found = 0; |
221 TInt ep_found = 0; |
213 TBool foundBulkIN = EFalse; |
222 TBool foundBulkIN = EFalse; |
214 TBool foundBulkOUT = EFalse; |
223 TBool foundBulkOUT = EFalse; |
215 |
224 |
216 for (TInt i = 0; i < totalEndpoints ; i++) |
225 for (TInt i = 0; i < totalEndpoints ; i++) |
217 { |
226 { |
218 const TUsbcEndpointCaps* caps = &data[i].iCaps; |
227 const TUsbcEndpointCaps* caps = &data[i].iCaps; |
219 const TInt maxPacketSize = caps->MaxPacketSize(); |
228 const TInt maxPacketSize = caps->MaxPacketSize(); |
220 if (!foundBulkIN && |
229 if (!foundBulkIN && |
221 (caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirIn)) == (KUsbEpTypeBulk | KUsbEpDirIn)) |
230 (caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirIn)) == (KUsbEpTypeBulk | KUsbEpDirIn)) |
222 { |
231 { |
223 // KInEndpoint is going to be our TX (IN, write) endpoint |
232 // KInEndpoint is going to be our TX (IN, write) endpoint |
224 ifc().iEndpointData[0].iType = KUsbEpTypeBulk; |
233 ifc().iEndpointData[0].iType = KUsbEpTypeBulk; |
225 if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) == KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) |
234 if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) == KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) |
226 ifc().iEndpointData[0].iFeatureWord1 = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering; |
235 ifc().iEndpointData[0].iFeatureWord1 = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering; |
227 ifc().iEndpointData[0].iDir = KUsbEpDirIn; |
236 ifc().iEndpointData[0].iDir = KUsbEpDirIn; |
228 ifc().iEndpointData[0].iSize = maxPacketSize; |
237 ifc().iEndpointData[0].iSize = maxPacketSize; |
229 ifc().iEndpointData[0].iInterval_Hs = 0; |
238 ifc().iEndpointData[0].iInterval_Hs = 0; |
230 foundBulkIN = ETrue; |
239 foundBulkIN = ETrue; |
231 if (++ep_found == KRequiredNumberOfEndpoints) |
240 if (++ep_found == KRequiredNumberOfEndpoints) |
232 { |
241 { |
233 break; |
242 break; |
234 } |
243 } |
235 continue; |
244 continue; |
236 } |
245 } |
237 if (!foundBulkOUT && |
246 if (!foundBulkOUT && |
238 (caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirOut)) == (KUsbEpTypeBulk | KUsbEpDirOut)) |
247 (caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirOut)) == (KUsbEpTypeBulk | KUsbEpDirOut)) |
239 { |
248 { |
240 // KOutEndpoint is going to be our RX (OUT, read) endpoint |
249 // KOutEndpoint is going to be our RX (OUT, read) endpoint |
241 ifc().iEndpointData[1].iType = KUsbEpTypeBulk; |
250 ifc().iEndpointData[1].iType = KUsbEpTypeBulk; |
242 if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) == KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) |
251 if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) == KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) |
243 ifc().iEndpointData[1].iFeatureWord1 = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering; |
252 ifc().iEndpointData[1].iFeatureWord1 = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering; |
244 ifc().iEndpointData[1].iDir = KUsbEpDirOut; |
253 ifc().iEndpointData[1].iDir = KUsbEpDirOut; |
245 ifc().iEndpointData[1].iSize = maxPacketSize; |
254 ifc().iEndpointData[1].iSize = maxPacketSize; |
246 ifc().iEndpointData[1].iInterval_Hs = 0; |
255 ifc().iEndpointData[1].iInterval_Hs = 0; |
247 foundBulkOUT = ETrue; |
256 foundBulkOUT = ETrue; |
248 if (++ep_found == KRequiredNumberOfEndpoints) |
257 if (++ep_found == KRequiredNumberOfEndpoints) |
249 { |
258 { |
250 break; |
259 break; |
251 } |
260 } |
252 continue; |
261 continue; |
253 } |
262 } |
254 } |
263 } |
255 if (ep_found != KRequiredNumberOfEndpoints) |
264 if (ep_found != KRequiredNumberOfEndpoints) |
256 { |
265 { |
257 return KErrHardwareNotAvailable; |
266 return KErrHardwareNotAvailable; |
258 } |
267 } |
259 |
268 |
260 _LIT16(string, "USB Mass Storage Interface"); |
269 _LIT16(string, "USB Mass Storage Interface"); |
261 ifc().iString = const_cast<TDesC16*>(&string); |
270 ifc().iString = const_cast<TDesC16*>(&string); |
262 ifc().iTotalEndpointsUsed = KRequiredNumberOfEndpoints; |
271 ifc().iTotalEndpointsUsed = KRequiredNumberOfEndpoints; |
263 ifc().iClass.iClassNum = 0x08; // Mass Storage |
272 ifc().iClass.iClassNum = 0x08; // Mass Storage |
264 ifc().iClass.iSubClassNum = 0x06; // SCSI Transparent Command Set |
273 ifc().iClass.iSubClassNum = 0x06; // SCSI Transparent Command Set |
265 ifc().iClass.iProtocolNum = 0x50; // Bulk Only Transport |
274 ifc().iClass.iProtocolNum = 0x50; // Bulk Only Transport |
266 |
275 |
267 TUint bandwidth_priority = (EUsbcBandwidthOUTDefault | EUsbcBandwidthINDefault); |
276 TUint bandwidth_priority = (EUsbcBandwidthOUTDefault | EUsbcBandwidthINDefault); |
268 if (d_caps().iHighSpeed) |
277 if (d_caps().iHighSpeed) |
269 { |
278 { |
270 // If this device supports USB High-speed, then we request 64KB buffers |
279 // If this device supports USB High-speed, then we request 64KB buffers |
271 // (otherwise the default 4KB ones will do). |
280 // (otherwise the default 4KB ones will do). |
272 bandwidth_priority = (EUsbcBandwidthOUTPlus2 | EUsbcBandwidthINPlus2); |
281 bandwidth_priority = (EUsbcBandwidthOUTPlus2 | EUsbcBandwidthINPlus2); |
273 // Also, tell the Protocol about it, because it might want to do some |
282 // Also, tell the Protocol about it, because it might want to do some |
274 // optimizing too. |
283 // optimizing too. |
275 iProtocol->ReportHighSpeedDevice(); |
284 iProtocol->ReportHighSpeedDevice(); |
276 } |
285 } |
277 ret = iLdd.SetInterface(0, ifc, bandwidth_priority); |
286 ret = iLdd.SetInterface(0, ifc, bandwidth_priority); |
278 return ret; |
287 return ret; |
279 } |
288 } |
|
289 |
280 |
290 |
281 |
291 /** |
282 /** |
292 Called by the protocol after processing the packet to indicate that more data is required. |
283 Called by the protocol after processing the packet to indicate that more data is required. |
293 |
284 |
294 @param aData reference to the data buffer. |
285 @param aData reference to the data buffer. |
295 */ |
286 */ |
296 void CBulkOnlyTransport::SetupDataOut(TPtr8& aData) |
287 void CBulkOnlyTransport::SetupDataOut(TPtr8& aData) |
297 { |
288 { |
298 __MSFNLOG |
|
299 iDataTransferMan.SetModeDataOut(aData); |
289 iDataTransferMan.SetModeDataOut(aData); |
300 } |
290 } |
301 |
291 |
302 /** |
292 /** |
303 Called by the protocol after processing the packet to indicate that data should be written to the host. |
293 Called by the protocol after processing the packet to indicate that data should be written to the host. |
304 |
294 |
305 @param aData reference to the data buffer. |
295 @param aData reference to the data buffer. |
306 */ |
296 */ |
307 void CBulkOnlyTransport::SetupDataIn(TPtrC8& aData) |
297 void CBulkOnlyTransport::SetupDataIn(TPtrC8& aData) |
308 { |
298 { |
309 iDataTransferMan.SetModeDataIn(aData); |
299 iDataTransferMan.SetModeDataIn(aData); |
310 } |
300 } |
311 |
301 |
312 |
302 |
313 TInt CBulkOnlyTransport::Start() |
303 TInt CBulkOnlyTransport::Start() |
314 { |
304 { |
315 __MSFNLOG |
305 TInt err = KErrNone; |
316 TInt err = KErrNone; |
306 |
317 |
307 if (!iProtocol) |
318 if (!iProtocol) |
308 { |
319 { |
309 return KErrBadHandle; //protocol should be set up before start |
320 return KErrBadHandle; //protocol should be set up before start |
310 } |
321 } |
311 |
322 |
312 if (IsActive()) |
323 if (IsActive()) |
313 { |
324 { |
314 __PRINT(_L("CBulkOnlyTransport::Start - active before start!\n")); |
325 __PRINT(_L("CBulkOnlyTransport::Start - active before start!\n")); |
315 return KErrInUse; |
326 return KErrInUse; |
316 } |
327 } |
317 |
328 |
318 if ((err = iLdd.Open(0)) != KErrNone || |
329 if ((err = iLdd.Open(0)) != KErrNone || |
319 (err = SetupConfigurationDescriptor()) != KErrNone || |
330 (err = SetupConfigurationDescriptor()) != KErrNone || |
320 (err = SetupInterfaceDescriptors()) != KErrNone ) |
331 (err = SetupInterfaceDescriptors()) != KErrNone ) |
321 { |
332 { |
322 __PRINT(_L("CBulkOnlyTransport::Start - Error during descriptors setup!\n")); |
333 __PRINT(_L("CBulkOnlyTransport::Start - Error during descriptors setup!\n")); |
323 return err; |
334 return err; |
324 } |
335 } |
325 |
336 |
326 iDeviceStateNotifier->Activate(); // activate notifier wich will wait until USB became configured |
337 iDeviceStateNotifier->Activate(); // activate notifier wich will wait until USB became configured |
327 TUsbcDeviceState deviceStatus = EUsbcDeviceStateDefault; |
338 TUsbcDeviceState deviceStatus = EUsbcDeviceStateDefault; |
328 err = iLdd.DeviceStatus(deviceStatus); |
339 err = iLdd.DeviceStatus(deviceStatus); |
329 __PRINT1(_L("CBulkOnlyTransport::Start - Device status = %d\n"), deviceStatus); |
340 __PRINT1(_L("CBulkOnlyTransport::Start - Device status = %d\n"), deviceStatus); |
330 if (err == KErrNone && deviceStatus == EUsbcDeviceStateConfigured) |
341 if (err == KErrNone && deviceStatus == EUsbcDeviceStateConfigured) |
331 { |
342 { |
332 __PRINT(_L("CBulkOnlyTransport::Start - Starting bulk only transport\n")); |
343 __PRINT(_L("CBulkOnlyTransport::Start - Starting bulk only transport\n")); |
333 err = HwStart(); |
344 err = HwStart(); |
334 } |
345 } |
335 iInterfaceConfigured = ETrue; |
346 iInterfaceConfigured = ETrue; |
336 return err; |
347 return err; |
337 } |
348 } |
|
349 |
338 |
350 TInt CBulkOnlyTransport::HwStart(TBool aDiscard) |
339 TInt CBulkOnlyTransport::HwStart(TBool aDiscard) |
351 { |
340 { |
352 __MSFNLOG |
|
353 |
|
354 TInt lun = MaxLun(); |
341 TInt lun = MaxLun(); |
355 do |
342 do |
356 { |
343 { |
357 Controller().DriveManager().Connect(lun); |
344 Controller().DriveManager().Connect(lun); |
358 } |
345 } |
359 while(--lun >= 0); |
346 while(--lun >= 0); |
360 |
347 |
361 TInt res = iBotControlInterface->Start() ; |
348 TInt res = iBotControlInterface->Start() ; |
362 |
349 |
363 iCurrentState = ENone; |
350 iCurrentState = ENone; |
364 iDataTransferMan.Init(); |
351 iDataTransferMan.Init(); |
365 iStarted = ETrue; |
352 iStarted = ETrue; |
366 |
353 |
367 TUsbDeviceCaps d_caps; |
354 TUsbDeviceCaps d_caps; |
368 TInt ret = iLdd.DeviceCaps(d_caps); |
355 TInt ret = iLdd.DeviceCaps(d_caps); |
369 if (ret == KErrNone) |
356 if (ret == KErrNone) |
370 { |
357 { |
371 if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) |
358 if((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) |
372 { |
359 { |
373 // Set up DMA if possible (errors are non-critical) |
360 // Set up DMA if possible (errors are non-critical) |
374 TInt err = iLdd.AllocateEndpointResource(KOutEndpoint, EUsbcEndpointResourceDMA); |
361 TInt err = iLdd.AllocateEndpointResource(KOutEndpoint, EUsbcEndpointResourceDMA); |
375 if (err != KErrNone) |
362 if (err != KErrNone) |
376 { |
363 { |
377 __PRINT1(_L("Set DMA on OUT endpoint failed with error code: %d"), err); |
364 __PRINT1(_L("Set DMA on OUT endpoint failed with error code: %d"), err); |
378 } |
365 } |
379 err = iLdd.AllocateEndpointResource(KInEndpoint, EUsbcEndpointResourceDMA); |
366 err = iLdd.AllocateEndpointResource(KInEndpoint, EUsbcEndpointResourceDMA); |
380 if (err != KErrNone) |
367 if (err != KErrNone) |
381 { |
368 { |
382 __PRINT1(_L("Set DMA on IN endpoint failed with error code: %d"), err); |
369 __PRINT1(_L("Set DMA on IN endpoint failed with error code: %d"), err); |
383 } |
370 } |
384 |
371 |
385 // Set up Double Buffering if possible (errors are non-critical) |
372 // Set up Double Buffering if possible (errors are non-critical) |
386 err = iLdd.AllocateEndpointResource(KOutEndpoint, EUsbcEndpointResourceDoubleBuffering); |
373 err = iLdd.AllocateEndpointResource(KOutEndpoint, EUsbcEndpointResourceDoubleBuffering); |
387 if (err != KErrNone) |
374 if (err != KErrNone) |
388 { |
375 { |
389 __PRINT1(_L("Set Double Buffering on OUT endpoint failed with error code: %d"), err); |
376 __PRINT1(_L("Set Double Buffering on OUT endpoint failed with error code: %d"), err); |
390 } |
377 } |
391 err = iLdd.AllocateEndpointResource(KInEndpoint, EUsbcEndpointResourceDoubleBuffering); |
378 err = iLdd.AllocateEndpointResource(KInEndpoint, EUsbcEndpointResourceDoubleBuffering); |
392 if (err != KErrNone) |
379 if (err != KErrNone) |
393 { |
380 { |
394 __PRINT1(_L("Set Double Buffering on IN endpoint failed with error code: %d"), err); |
381 __PRINT1(_L("Set Double Buffering on IN endpoint failed with error code: %d"), err); |
395 } |
382 } |
396 } |
383 } |
397 } |
384 } |
398 |
385 |
399 if (aDiscard) |
386 if (aDiscard) |
400 { |
387 { |
401 TInt bytes; |
388 TInt bytes; |
402 const TInt err = iLdd.QueryReceiveBuffer(KOutEndpoint, bytes); |
389 const TInt err = iLdd.QueryReceiveBuffer(KOutEndpoint, bytes); |
403 if (err != KErrNone || bytes <= 0) |
390 if (err != KErrNone || bytes <= 0) |
404 { |
391 { |
405 __PRINT1(_L("Error: err=%d bytes=%d"), bytes); |
392 __PRINT1(_L("Error: err=%d bytes=%d"), bytes); |
406 } |
393 } |
407 else |
394 else |
408 { |
395 { |
409 __PRINT1(_L("RxBuffer has %d bytes"), bytes); |
396 __PRINT1(_L("RxBuffer has %d bytes"), bytes); |
410 FlushDataOut(bytes); |
397 FlushDataOut(bytes); |
411 } |
398 } |
412 } |
399 } |
413 |
400 |
414 ClientReadCbw(); |
401 ClientReadCbw(); |
415 return res; |
402 return res; |
416 } |
403 } |
417 |
404 |
418 |
405 |
419 void CBulkOnlyTransport::HwStop() |
406 void CBulkOnlyTransport::HwStop() |
420 { |
407 { |
421 __MSFNLOG |
408 if (iStarted) |
422 if (iStarted) |
409 { |
423 { |
|
424 iController.DriveManager().Disconnect(); |
410 iController.DriveManager().Disconnect(); |
425 Cancel(); |
411 Cancel(); |
426 iBotControlInterface->Cancel(); |
412 iBotControlInterface->Cancel(); |
427 iProtocol->Cancel(); |
413 iProtocol->Cancel(); |
428 iStarted = EFalse; |
414 iStarted = EFalse; |
429 } |
415 } |
430 } |
416 } |
431 |
417 |
432 |
418 |
433 void CBulkOnlyTransport::HwSuspend() |
419 void CBulkOnlyTransport::HwSuspend() |
434 { |
420 { |
435 __MSFNLOG |
|
436 iController.DriveManager().Disconnect(); |
421 iController.DriveManager().Disconnect(); |
437 } |
422 } |
438 |
423 |
439 |
424 |
440 void CBulkOnlyTransport::HwResume() |
425 void CBulkOnlyTransport::HwResume() |
441 { |
426 { |
442 __MSFNLOG |
|
443 iController.DriveManager().Connect(); |
427 iController.DriveManager().Connect(); |
444 } |
428 } |
445 |
429 |
446 |
430 |
447 /** |
431 /** |
448 Stops the Bulk Only Transport |
432 Stops the Bulk Only Transport |
449 */ |
433 */ |
450 TInt CBulkOnlyTransport::Stop() |
434 TInt CBulkOnlyTransport::Stop() |
451 { |
435 { |
452 __MSFNLOG |
436 iBotControlInterface->Cancel(); |
453 iBotControlInterface->Cancel(); |
437 iDeviceStateNotifier->Cancel(); |
454 iDeviceStateNotifier->Cancel(); |
438 Cancel(); |
455 Cancel(); |
439 if (iInterfaceConfigured) |
456 if (iInterfaceConfigured) |
440 { |
457 { |
441 iLdd.ReleaseInterface(0); |
458 iLdd.ReleaseInterface(0); |
442 SetupConfigurationDescriptor(ETrue); |
459 SetupConfigurationDescriptor(ETrue); |
443 iLdd.Close(); |
460 iLdd.Close(); |
444 } |
461 } |
445 iCurrentState = ENone; |
462 iCurrentState = ENone; |
446 iInterfaceConfigured = EFalse; |
463 iInterfaceConfigured = EFalse; |
447 |
464 |
448 return KErrNone; |
465 return KErrNone; |
449 } |
466 } |
|
467 |
450 |
468 |
451 |
469 /** |
452 /** |
470 Read aLength bytes of data from the host into the read buffer. |
453 Read aLength bytes of data from the host into the read buffer. |
471 @param aLength The number of bytes to read from the host. |
454 @param aLength The number of bytes to read from the host. |
472 */ |
455 */ |
473 void CBulkOnlyTransport::ClientReadCbw() |
456 void CBulkOnlyTransport::ClientReadCbw() |
474 { |
457 { |
475 __MSFNLOG |
458 if (IsActive()) |
476 if (IsActive()) |
459 { |
477 { |
460 __PRINT(_L("Still active\n")); |
478 __PRINT(_L("Still active\n")); |
461 __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsClientPanicCat, EMsBulkOnlyStillActive)); |
479 __ASSERT_DEBUG(EFalse, User::Panic(KUsbMsClientPanicCat, EMsBulkOnlyStillActive)); |
462 return; |
480 return; |
463 } |
481 } |
|
482 |
464 |
483 ReadCbw(); |
465 ReadCbw(); |
484 } |
466 } |
485 |
467 |
486 |
468 |
487 void CBulkOnlyTransport::ReadCbw() |
469 void CBulkOnlyTransport::ReadCbw() |
488 { |
470 { |
489 __MSFNLOG |
471 iCbwBuf.SetMax(); |
490 iCbwBuf.SetMax(); |
472 iLdd.ReadUntilShort(iStatus, KOutEndpoint, iCbwBuf, iCbwBuf.Length()); |
491 iLdd.ReadUntilShort(iStatus, KOutEndpoint, iCbwBuf, iCbwBuf.Length()); |
473 iCurrentState = EWaitForCBW; |
492 iCurrentState = EWaitForCBW; |
474 SetActive(); |
493 SetActive(); |
475 } |
494 } |
|
495 |
476 |
496 |
477 |
497 void CBulkOnlyTransport::DoCancel() |
478 void CBulkOnlyTransport::DoCancel() |
498 { |
479 { |
499 __MSFNLOG |
480 iLdd.WriteCancel(KInEndpoint); |
500 iLdd.WriteCancel(KInEndpoint); |
481 iLdd.ReadCancel(KOutEndpoint); |
501 iLdd.ReadCancel(KOutEndpoint); |
482 } |
502 } |
|
503 |
483 |
504 |
484 |
505 void CBulkOnlyTransport::Activate(TInt aReason) |
485 void CBulkOnlyTransport::Activate(TInt aReason) |
506 { |
486 { |
507 __MSFNLOG |
|
508 SetActive(); |
487 SetActive(); |
509 TRequestStatus* r = &iStatus; |
488 TRequestStatus* r = &iStatus; |
510 User::RequestComplete(r, aReason); |
489 User::RequestComplete(r, aReason); |
511 } |
490 } |
512 |
491 |
513 |
492 |
514 void CBulkOnlyTransport::RunL() |
493 void CBulkOnlyTransport::RunL() |
515 { |
494 { |
516 __MSFNLOG |
495 if (iStatus != KErrNone) |
517 if (iStatus != KErrNone) |
496 { |
518 { |
497 __PRINT1(_L("Error %d in RunL, halt endpoints \n"), iStatus.Int()); |
519 __PRINT1(_L("Error %d in RunL, halt endpoints \n"), iStatus.Int()); |
498 SetPermError(); //halt endpoints for reset recovery |
520 SetPermError(); //halt endpoints for reset recovery |
499 return; |
521 return; |
500 } |
522 } |
501 |
523 |
502 switch (iCurrentState) |
524 switch (iCurrentState) |
503 { |
525 { |
|
526 case EWaitForCBW: |
504 case EWaitForCBW: |
527 __PRINT(_L("EWaitForCBW")); |
505 __PRINT(_L("EWaitForCBW")); |
528 TRAPD(err, DecodeCbwL()); |
506 TRAPD(err, DecodeCbwL()); |
529 if (err) |
507 if (err) |
530 { |
508 { |
692 - Depending on the command, more data may be transmitted/received. |
670 - Depending on the command, more data may be transmitted/received. |
693 - ...or the CSW is sent (if not a data command). |
671 - ...or the CSW is sent (if not a data command). |
694 |
672 |
695 */ |
673 */ |
696 void CBulkOnlyTransport::DecodeCbwL() |
674 void CBulkOnlyTransport::DecodeCbwL() |
697 { |
675 { |
698 __MSFNLOG |
|
699 TBotServerReq req; |
676 TBotServerReq req; |
700 req.DecodeL(iCbwBuf); |
677 req.DecodeL(iCbwBuf); |
701 |
678 |
702 if (!(req.IsValidCbw() && req.IsMeaningfulCbw(iMaxLun))) |
679 if (!(req.IsValidCbw() && req.IsMeaningfulCbw(iMaxLun))) |
703 { |
680 { |
704 User::Leave(KErrGeneral); |
681 User::Leave(KErrGeneral); |
705 } |
682 } |
706 |
683 |
707 TPtrC8 aData(&iCbwBuf[TBotCbw::KCbwCbOffset], TBotCbw::KMaxCbwcbLength); |
684 TPtrC8 aData(&iCbwBuf[TBotCbw::KCbwCbOffset], TBotCbw::KMaxCbwcbLength); |
708 //aData.Set(&iCbwBuf[TBotCbw::KCbwCbOffset], TBotCbw::KMaxCbwcbLength); |
685 //aData.Set(&iCbwBuf[TBotCbw::KCbwCbOffset], TBotCbw::KMaxCbwcbLength); |
709 TUint8 lun = req.Lun(); |
686 TUint8 lun = req.Lun(); |
710 |
687 |
711 iCbwTag = req.Tag(); |
688 iCbwTag = req.Tag(); |
712 TUint32 hostDataLength = req.DataTransferLength(); |
689 TUint32 hostDataLength = req.DataTransferLength(); |
713 iDataTransferMan.SetHostDataLen(hostDataLength); |
690 iDataTransferMan.SetHostDataLen(hostDataLength); |
714 |
691 |
715 TBotServerReq::TCbwDirection dataToHost = req.Direction(); |
692 TBotServerReq::TCbwDirection dataToHost = req.Direction(); |
716 |
693 |
717 __PRINT4(_L("lun =%d, hostDataLength=%d, CBWtag = 0x%X\n, dataToHost=%d\n"), |
694 __PRINT4(_L("lun =%d, hostDataLength=%d, CBWtag = 0x%X\n, dataToHost=%d\n"), |
718 lun, hostDataLength, iCbwTag, dataToHost); |
695 lun, hostDataLength, iCbwTag, dataToHost); |
719 |
696 |
720 ////////////////////////////////////////////// |
697 ////////////////////////////////////////////// |
721 TBool ret = iProtocol->DecodePacket(aData, lun); |
698 TBool ret = iProtocol->DecodePacket(aData, lun); |
722 ////////////////////////////////////////////// |
699 ////////////////////////////////////////////// |
723 |
700 |
724 iStallAllowed = ETrue; |
701 iStallAllowed = ETrue; |
725 |
702 |
726 if (!ret) |
703 if (!ret) |
727 { |
704 { |
728 __PRINT(_L("Command Failed\n")); |
705 __PRINT(_L("Command Failed\n")); |
729 iCmdStatus = TBotCsw::ECommandFailed; |
706 iCmdStatus = TBotCsw::ECommandFailed; |
730 } |
707 } |
731 else |
708 else |
732 { |
709 { |
733 __PRINT(_L("Command Passed\n")); |
710 __PRINT(_L("Command Passed\n")); |
734 iCmdStatus = TBotCsw::ECommandPassed; |
711 iCmdStatus = TBotCsw::ECommandPassed; |
735 } |
712 } |
736 |
713 |
737 if (hostDataLength) // Host expected data transfer |
714 if (hostDataLength) // Host expected data transfer |
738 { |
715 { |
739 if (dataToHost == TBotServerReq::EDataIn) // send data to host |
716 if (dataToHost == TBotServerReq::EDataIn) // send data to host |
740 { |
717 { |
741 if (!iDataTransferMan.IsModeDataIn()) |
718 if (!iDataTransferMan.IsModeDataIn()) |
742 { |
719 { |
743 __PRINT(_L("Write buffer was not setup\n")); |
720 __PRINT(_L("Write buffer was not setup\n")); |
744 |
721 |
745 if (hostDataLength <= KBOTMaxBufSize) |
722 if (hostDataLength <= KBOTMaxBufSize) |
746 { |
723 { |
747 // Case 4 or 8" |
724 // Case 4 or 8" |
748 iBuf.FillZ(hostDataLength); |
725 iBuf.FillZ(hostDataLength); |
749 iLdd.Write(iStatus, KInEndpoint, iBuf, hostDataLength); |
726 iLdd.Write(iStatus, KInEndpoint, iBuf, hostDataLength); |
750 SetActive(); |
727 SetActive(); |
751 iCurrentState = EHandleDataIn; |
728 iCurrentState = EHandleDataIn; |
752 iStallAllowed = EFalse; |
729 iStallAllowed = EFalse; |
753 if (iDataTransferMan.IsModeDataOut()) |
730 if (iDataTransferMan.IsModeDataOut()) |
754 { |
731 { |
755 //read buffer WAS set up - case (8) |
732 //read buffer WAS set up - case (8) |
756 iCmdStatus = TBotCsw::EPhaseError; |
733 iCmdStatus = TBotCsw::EPhaseError; |
757 } |
734 } |
758 return; |
735 return; |
759 } |
736 } |
760 else |
737 else |
761 { |
738 { |
762 // Use next block instead of StallEndpointAndWaitForClear(KInEndpoint); |
739 // Use next block instead of StallEndpointAndWaitForClear(KInEndpoint); |
763 FlushDataIn(hostDataLength); |
740 FlushDataIn(hostDataLength); |
764 } |
741 } |
765 |
742 |
766 if (iDataTransferMan.IsModeDataOut()) |
743 if (iDataTransferMan.IsModeDataOut()) |
767 { |
744 { |
768 //read buffer WAS set up - case (8) |
745 //read buffer WAS set up - case (8) |
769 SendCsw(iCbwTag, hostDataLength, TBotCsw::EPhaseError); |
746 SendCsw(iCbwTag, hostDataLength, TBotCsw::EPhaseError); |
770 //don't care to reset any flag - should get reset recovery |
747 //don't care to reset any flag - should get reset recovery |
771 } |
748 } |
772 else |
749 else |
773 { |
750 { |
774 // case (4) |
751 // case (4) |
775 SendCsw(iCbwTag, hostDataLength, iCmdStatus); |
752 SendCsw(iCbwTag, hostDataLength, iCmdStatus); |
776 } |
753 } |
777 return; |
754 return; |
778 } |
755 } |
779 |
756 |
780 //================== |
757 //================== |
781 TInt deviceDataLength = iDataTransferMan.iWriteBuf.Length(); |
758 TInt deviceDataLength = iDataTransferMan.iWriteBuf.Length(); |
782 iDataTransferMan.iDataResidue = hostDataLength - deviceDataLength; |
759 iDataTransferMan.iDataResidue = hostDataLength - deviceDataLength; |
783 |
760 |
784 #ifdef MSDC_TESTMODE |
761 #ifdef MSDC_TESTMODE |
785 if (iTestParser && iTestParser->Enabled()) |
762 if (iTestParser && iTestParser->Enabled()) |
786 { |
763 { |
1039 @param aDataResidue the difference between the amount of data expected by the |
1013 @param aDataResidue the difference between the amount of data expected by the |
1040 host, and the actual amount of data processed by the device. |
1014 host, and the actual amount of data processed by the device. |
1041 @param aStatus indicates the success or failure of the command. |
1015 @param aStatus indicates the success or failure of the command. |
1042 */ |
1016 */ |
1043 void CBulkOnlyTransport::SendCsw(TUint aTag, TUint32 aDataResidue, TBotCsw::TCswStatus aStatus) |
1017 void CBulkOnlyTransport::SendCsw(TUint aTag, TUint32 aDataResidue, TBotCsw::TCswStatus aStatus) |
1044 { |
1018 { |
1045 __MSFNLOG |
1019 __PRINT2(_L("DataResidue = %d, Status = %d \n"), aDataResidue, aStatus); |
1046 __PRINT2(_L("DataResidue = %d, Status = %d \n"), aDataResidue, aStatus); |
|
1047 iCsw.SetLength(TBotCsw::KCswLength); |
1020 iCsw.SetLength(TBotCsw::KCswLength); |
1048 TBotServerResp resp(iCbwTag, aDataResidue, aStatus); |
1021 TBotServerResp resp(iCbwTag, aDataResidue, aStatus); |
1049 #ifdef MSDC_TESTMODE |
1022 #ifdef MSDC_TESTMODE |
1050 resp.EncodeL(iCsw, iTestParser); |
1023 resp.EncodeL(iCsw, iTestParser); |
1051 #else |
1024 #else |
1052 resp.EncodeL(iCsw); |
1025 resp.EncodeL(iCsw); |
1053 #endif |
1026 #endif |
1054 iLdd.Write(iStatus, KInEndpoint, iCsw, TBotCsw::KCswLength); |
1027 iLdd.Write(iStatus, KInEndpoint, iCsw, TBotCsw::KCswLength); |
1055 iCurrentState = ESendingCSW; |
1028 iCurrentState = ESendingCSW; |
1056 SetActive(); |
1029 SetActive(); |
1057 } |
1030 } |
1058 |
1031 |
1059 |
1032 |
1060 /** |
1033 /** |
1061 Associates the transport with the protocol. Called during initialization of the controller. |
1034 Associates the transport with the protocol. Called during initialization of the controller. |
1062 |
1035 |
1063 @param aProtocol reference to the protocol |
1036 @param aProtocol reference to the protocol |
1064 */ |
1037 */ |
1065 void CBulkOnlyTransport::RegisterProtocol(MServerProtocol& aProtocol) |
1038 void CBulkOnlyTransport::RegisterProtocol(MServerProtocol& aProtocol) |
1066 { |
1039 { |
1067 __MSFNLOG |
1040 iProtocol = &aProtocol; |
1068 iProtocol = &aProtocol; |
1041 } |
1069 } |
|
1070 |
1042 |
1071 |
1043 |
1072 /** |
1044 /** |
1073 Used by CControlInterface |
1045 Used by CControlInterface |
1074 |
1046 |
1075 @return reference to the controller which instantiate the CBulkOnlyTransport |
1047 @return reference to the controller which instantiate the CBulkOnlyTransport |
1076 */ |
1048 */ |
1077 CUsbMassStorageController& CBulkOnlyTransport::Controller() |
1049 CUsbMassStorageController& CBulkOnlyTransport::Controller() |
1078 { |
1050 { |
1079 return iController; |
1051 return iController; |
1080 } |
1052 } |
1081 |
1053 |
1082 |
1054 |
1083 /** |
1055 /** |
1084 @return the number of logical units supported by the device. |
1056 @return the number of logical units supported by the device. |
1085 Logical Unit Numbers on the device shall be numbered contiguously starting from LUN |
1057 Logical Unit Numbers on the device shall be numbered contiguously starting from LUN |
1086 0 to a maximum LUN of 15 (Fh). |
1058 0 to a maximum LUN of 15 (Fh). |
1087 */ |
1059 */ |
1088 TInt CBulkOnlyTransport::MaxLun() |
1060 TInt CBulkOnlyTransport::MaxLun() |
1089 { |
1061 { |
1090 __MSFNLOG |
1062 return iMaxLun; |
1091 return iMaxLun; |
1063 } |
1092 } |
|
1093 |
1064 |
1094 |
1065 |
1095 /** |
1066 /** |
1096 Used by CControlInterface |
1067 Used by CControlInterface |
1097 @return reference to USB logical driver |
1068 @return reference to USB logical driver |
1098 */ |
1069 */ |
1099 RDevUsbcClient& CBulkOnlyTransport::Ldd() |
1070 RDevUsbcClient& CBulkOnlyTransport::Ldd() |
1100 { |
1071 { |
1101 return iLdd; |
1072 return iLdd; |
1102 } |
1073 } |
1103 |
1074 |
1104 |
1075 |
1105 void CBulkOnlyTransport::StallEndpointAndWaitForClear(TEndpointNumber aEndpoint) |
1076 void CBulkOnlyTransport::StallEndpointAndWaitForClear(TEndpointNumber aEndpoint) |
1106 { |
1077 { |
1107 __MSFNLOG |
1078 __ASSERT_DEBUG(aEndpoint != EEndpoint0, User::Panic(KUsbMsClientPanicCat, EMsWrongEndpoint)); |
1108 __ASSERT_DEBUG(aEndpoint != EEndpoint0, User::Panic(KUsbMsClientPanicCat, EMsWrongEndpoint)); |
1079 |
1109 |
1080 // Now stall this endpoint |
1110 // Now stall this endpoint |
1081 __PRINT1(_L("Stalling endpoint %d"), aEndpoint); |
1111 __PRINT1(_L("Stalling endpoint %d"), aEndpoint); |
1082 __TESTMODEPRINT2("CBW Tag=0x%x: Stalling endpoint %d", iCbwTag, aEndpoint); |
1112 __TESTMODEPRINT2("CBW Tag=0x%x: Stalling endpoint %d", iCbwTag, aEndpoint); |
1083 TInt r = iLdd.HaltEndpoint(aEndpoint); |
1113 TInt r = iLdd.HaltEndpoint(aEndpoint); |
1084 if (r != KErrNone) |
1114 if (r != KErrNone) |
1085 { |
1115 { |
1086 __PRINT2(_L("Error: stalling ep %d failed: %d"), aEndpoint, r); |
1116 __PRINT2(_L("Error: stalling ep %d failed: %d"), aEndpoint, r); |
1087 } |
1117 } |
1088 TEndpointState ep_state; |
1118 TEndpointState ep_state; |
1089 TInt i = 0; |
1119 TInt i = 0; |
1090 do |
1120 do |
1091 { |
1121 { |
1092 // Wait for 10ms before checking the ep status |
1122 // Wait for 10ms before checking the ep status |
1093 User::After(10000); |
1123 User::After(10000); |
|
1124 |
1094 |
1125 if (aEndpoint == KInEndpoint) |
1095 if (aEndpoint == KInEndpoint) |
1126 { |
1096 { |
1127 // Discard BULK-OUT data |
1097 // Discard BULK-OUT data |
1128 TInt bytes; |
1098 TInt bytes; |
1136 __PRINT1(_L("RxBuffer has %d bytes"), bytes); |
1106 __PRINT1(_L("RxBuffer has %d bytes"), bytes); |
1137 FlushDataOut(bytes); |
1107 FlushDataOut(bytes); |
1138 } |
1108 } |
1139 } |
1109 } |
1140 |
1110 |
1141 iLdd.EndpointStatus(aEndpoint, ep_state); |
1111 iLdd.EndpointStatus(aEndpoint, ep_state); |
1142 if (++i >= 550) |
1112 if (++i >= 550) |
1143 { |
1113 { |
1144 // 5.5 secs should be enough (see 9.2.6.1 Request Processing Timing) |
1114 // 5.5 secs should be enough (see 9.2.6.1 Request Processing Timing) |
1145 __PRINT1(_L("Error: Checked for ep %d de-stall for 5.5s - giving up now"), aEndpoint); |
1115 __PRINT1(_L("Error: Checked for ep %d de-stall for 5.5s - giving up now"), aEndpoint); |
1146 __TESTMODEPRINT1("Error: Checked for ep %d de-stall for 5.5s - giving up now", aEndpoint); |
1116 __TESTMODEPRINT1("Error: Checked for ep %d de-stall for 5.5s - giving up now", aEndpoint); |
1147 // We can now only hope for a Reset Recovery |
1117 // We can now only hope for a Reset Recovery |
1148 return; |
1118 return; |
1149 } |
1119 } |
1150 } while ((ep_state == EEndpointStateStalled) && iStarted); |
1120 } while ((ep_state == EEndpointStateStalled) && iStarted); |
1151 __PRINT2(_L("Checked for ep %d de-stall: %d time(s)"), aEndpoint, i); |
1121 __PRINT2(_L("Checked for ep %d de-stall: %d time(s)"), aEndpoint, i); |
1152 __TESTMODEPRINT2("Checked for ep %d de-stall: %d time(s)", aEndpoint, i); |
1122 __TESTMODEPRINT2("Checked for ep %d de-stall: %d time(s)", aEndpoint, i); |
1153 } |
1123 } |
1154 |
1124 |
1155 |
1125 |
1156 |
1126 |
1157 /** |
1127 /** |
1158 Called by the protocol to determine how many bytes of data are available in the read buffer. |
1128 Called by the protocol to determine how many bytes of data are available in the read buffer. |
1159 |
1129 |
1160 @return The number of bytes available in the read buffer |
1130 @return The number of bytes available in the read buffer |
1161 */ |
1131 */ |
1162 TInt CBulkOnlyTransport::BytesAvailable() |
1132 TInt CBulkOnlyTransport::BytesAvailable() |
1163 { |
1133 { |
1164 __MSFNLOG |
1134 TInt bytes = 0; |
1165 TInt bytes = 0; |
1135 TInt err = iLdd.QueryReceiveBuffer(KOutEndpoint, bytes); |
1166 TInt err = iLdd.QueryReceiveBuffer(KOutEndpoint, bytes); |
1136 if (err != KErrNone) |
1167 if (err != KErrNone) |
1137 bytes = 0; |
1168 bytes = 0; |
1138 return bytes; |
1169 return bytes; |
1139 } |
1170 } |
|
1171 |
1140 |
1172 |
1141 |
1173 /** |
1142 /** |
1174 * Read out rest data from KOutEndpoint and discard them |
1143 * Read out rest data from KOutEndpoint and discard them |
1175 */ |
1144 */ |
1176 void CBulkOnlyTransport::FlushDataOut(TInt aLength) |
1145 void CBulkOnlyTransport::FlushDataOut(TInt aLength) |
1177 { |
1146 { |
1178 __MSFNLOG |
1147 iBuf.SetMax(); |
1179 iBuf.SetMax(); |
1148 TRequestStatus status; |
1180 TRequestStatus status; |
1149 while (aLength > 0) |
1181 while (aLength > 0) |
1150 { |
1182 { |
1151 iLdd.ReadOneOrMore(status, KOutEndpoint, iBuf, iBuf.Length()); |
1183 iLdd.ReadOneOrMore(status, KOutEndpoint, iBuf, iBuf.Length()); |
1152 User::WaitForRequest(status); |
1184 User::WaitForRequest(status); |
1153 TInt err = status.Int(); |
1185 TInt err = status.Int(); |
1154 if (err != KErrNone) |
1186 if (err != KErrNone) |
1155 { |
1187 { |
1156 // Bad. |
1188 // Bad. |
1157 break; |
1189 break; |
1158 } |
1190 } |
1159 aLength -= iBuf.Length(); |
1191 aLength -= iBuf.Length(); |
1160 } |
1192 } |
1161 } |
1193 } |
|
1194 |
1162 |
1195 |
1163 |
1196 void CBulkOnlyTransport::FlushDataIn(TInt aLength) |
1164 void CBulkOnlyTransport::FlushDataIn(TInt aLength) |
1197 { |
1165 { |
1198 iBuf.SetMax(); |
1166 iBuf.SetMax(); |
1199 TInt c = 0; |
1167 TInt c = 0; |
1200 TInt len; |
1168 TInt len; |
1201 TRequestStatus status; |
1169 TRequestStatus status; |
1202 while (c < aLength) |
1170 while (c < aLength) |
1203 { |
1171 { |
1204 len = aLength - c; |
1172 len = aLength - c; |
1205 if (len > KBOTMaxBufSize) |
1173 if (len > KBOTMaxBufSize) |
1206 { |
1174 { |
1207 len = KBOTMaxBufSize; |
1175 len = KBOTMaxBufSize; |
1208 } |
1176 } |
1209 iLdd.Write(status, KInEndpoint, iBuf, len); |
1177 iLdd.Write(status, KInEndpoint, iBuf, len); |
1210 User::WaitForRequest(status); |
1178 User::WaitForRequest(status); |
1211 c += KBOTMaxBufSize; |
1179 c += KBOTMaxBufSize; |
1212 } |
1180 } |
1213 } |
1181 } |
1214 |
1182 |
1215 // |
1183 // |
1216 // --- class CActiveDeviceStateNotifier --------------------------------------------------------- |
1184 // --- class CActiveDeviceStateNotifier --------------------------------------------------------- |
1217 // |
1185 // |
1218 CActiveDeviceStateNotifier::CActiveDeviceStateNotifier(CBulkOnlyTransport& aParent) |
1186 CActiveDeviceStateNotifier::CActiveDeviceStateNotifier(CBulkOnlyTransport& aParent) |
1219 : CActive(EPriorityStandard), |
1187 : CActive(EPriorityStandard), |
1220 iParent(aParent), |
1188 iParent(aParent), |
1221 iDeviceState(EUsbcNoState), |
1189 iDeviceState(EUsbcNoState), |
1222 iOldDeviceState(EUsbcNoState) |
1190 iOldDeviceState(EUsbcNoState) |
1223 { |
1191 { |
1224 __MSFNLOG |
1192 } |
1225 } |
|
1226 |
1193 |
1227 |
1194 |
1228 CActiveDeviceStateNotifier* CActiveDeviceStateNotifier::NewL(CBulkOnlyTransport& aParent) |
1195 CActiveDeviceStateNotifier* CActiveDeviceStateNotifier::NewL(CBulkOnlyTransport& aParent) |
1229 { |
1196 { |
1230 __MSFNSLOG |
1197 CActiveDeviceStateNotifier* self = new (ELeave) CActiveDeviceStateNotifier(aParent); |
1231 CActiveDeviceStateNotifier* self = new (ELeave) CActiveDeviceStateNotifier(aParent); |
1198 CleanupStack::PushL(self); |
1232 CleanupStack::PushL(self); |
1199 self->ConstructL(); |
1233 self->ConstructL(); |
1200 CActiveScheduler::Add(self); |
1234 CActiveScheduler::Add(self); |
1201 CleanupStack::Pop(); // self |
1235 CleanupStack::Pop(); // self |
1202 return (self); |
1236 return (self); |
1203 } |
1237 } |
|
1238 |
1204 |
1239 |
1205 |
1240 void CActiveDeviceStateNotifier::ConstructL() |
1206 void CActiveDeviceStateNotifier::ConstructL() |
1241 { |
1207 { |
1242 __MSFNLOG |
1208 } |
1243 } |
|
1244 |
1209 |
1245 |
1210 |
1246 CActiveDeviceStateNotifier::~CActiveDeviceStateNotifier() |
1211 CActiveDeviceStateNotifier::~CActiveDeviceStateNotifier() |
1247 { |
1212 { |
1248 __MSFNLOG |
1213 Cancel(); // base class |
1249 Cancel(); // base class |
1214 } |
1250 } |
|
1251 |
1215 |
1252 |
1216 |
1253 void CActiveDeviceStateNotifier::DoCancel() |
1217 void CActiveDeviceStateNotifier::DoCancel() |
1254 /** |
1218 /** |
1255 * |
1219 * |
1256 */ |
1220 */ |
1257 { |
1221 { |
1258 __MSFNLOG |
1222 iParent.Ldd().AlternateDeviceStatusNotifyCancel(); |
1259 iParent.Ldd().AlternateDeviceStatusNotifyCancel(); |
1223 } |
1260 } |
|
1261 |
1224 |
1262 |
1225 |
1263 void CActiveDeviceStateNotifier::RunL() |
1226 void CActiveDeviceStateNotifier::RunL() |
1264 /** |
1227 /** |
1265 * |
1228 * |
1266 */ |
1229 */ |
1267 { |
1230 { |
1268 __MSFNLOG |
1231 // This displays the device state. |
1269 // This displays the device state. |
1232 // In a real world program, the user could take here appropriate action (cancel a |
1270 // In a real world program, the user could take here appropriate action (cancel a |
1233 // transfer request or whatever). |
1271 // transfer request or whatever). |
1234 if (!(iDeviceState & KUsbAlternateSetting)) |
1272 if (!(iDeviceState & KUsbAlternateSetting)) |
1235 { |
1273 { |
1236 switch (iDeviceState) |
1274 switch (iDeviceState) |
1237 { |
1275 { |
1238 case EUsbcDeviceStateUndefined: |
1276 case EUsbcDeviceStateUndefined: |
1239 __PRINT(_L("Device State notifier: Undefined\n")); |
1277 __PRINT(_L("Device State notifier: Undefined\n")); |
1240 iParent.HwStop(); |
1278 iParent.HwStop(); |
1241 break; |
1279 break; |
1242 case EUsbcDeviceStateAttached: |
1280 case EUsbcDeviceStateAttached: |
1243 __PRINT(_L("Device State notifier: Attached\n")); |
1281 __PRINT(_L("Device State notifier: Attached\n")); |
1244 iParent.HwStop(); |
1282 iParent.HwStop(); |
1245 break; |
1283 break; |
1246 case EUsbcDeviceStatePowered: |
1284 case EUsbcDeviceStatePowered: |
1247 __PRINT(_L("Device State notifier: Powered\n")); |
1285 __PRINT(_L("Device State notifier: Powered\n")); |
1248 iParent.HwStop(); |
1286 iParent.HwStop(); |
1249 break; |
1287 break; |
1250 case EUsbcDeviceStateDefault: |
1288 case EUsbcDeviceStateDefault: |
1251 __PRINT(_L("Device State notifier: Default\n")); |
1289 __PRINT(_L("Device State notifier: Default\n")); |
1252 iParent.HwStop(); |
1290 iParent.HwStop(); |
1253 break; |
1291 break; |
1254 case EUsbcDeviceStateAddress: |
1292 case EUsbcDeviceStateAddress: |
1255 __PRINT(_L("Device State notifier: Address\n")); |
1293 __PRINT(_L("Device State notifier: Address\n")); |
1256 iParent.HwStop(); |
1294 iParent.HwStop(); |
1257 break; |
1295 break; |
1258 case EUsbcDeviceStateConfigured: |
1296 case EUsbcDeviceStateConfigured: |
1259 __PRINT(_L("Device State notifier: Configured\n")); |
1297 __PRINT(_L("Device State notifier: Configured\n")); |
1260 if (iOldDeviceState == EUsbcDeviceStateSuspended) |
1298 if (iOldDeviceState == EUsbcDeviceStateSuspended) |
1261 { |
1299 { |
1262 iParent.HwResume(); |
1300 iParent.HwResume(); |
1263 } |
1301 } |
1264 else |
1302 else |
1265 { |
1303 { |
1266 iParent.HwStart(); |
1304 iParent.HwStart(); |
1267 } |
1305 } |
1268 break; |
1306 break; |
1269 case EUsbcDeviceStateSuspended: |
1307 case EUsbcDeviceStateSuspended: |
1270 __PRINT(_L("Device State notifier: Suspended\n")); |
1308 __PRINT(_L("Device State notifier: Suspended\n")); |
1271 if (iOldDeviceState == EUsbcDeviceStateConfigured) |
1309 if (iOldDeviceState == EUsbcDeviceStateConfigured) |
1272 { |
1310 { |
1273 iParent.HwSuspend(); |
1311 iParent.HwSuspend(); |
1274 } |
1312 } |
1275 break; |
1313 break; |
1276 default: |
1314 default: |
1277 __PRINT(_L("Device State notifier: ***BAD***\n")); |
1315 __PRINT(_L("Device State notifier: ***BAD***\n")); |
1278 iParent.HwStop(); |
1316 iParent.HwStop(); |
1279 break; |
1317 break; |
1280 } |
1318 } |
1281 iOldDeviceState = iDeviceState; |
1319 iOldDeviceState = iDeviceState; |
1282 } |
1320 } |
1283 else if (iDeviceState & KUsbAlternateSetting) |
1321 else if (iDeviceState & KUsbAlternateSetting) |
1284 { |
1322 { |
1285 __PRINT1(_L("Device State notifier: Alternate interface setting has changed: now %d\n"), iDeviceState & ~KUsbAlternateSetting); |
1323 __PRINT1(_L("Device State notifier: Alternate interface setting has changed: now %d\n"), iDeviceState & ~KUsbAlternateSetting); |
1286 } |
1324 } |
1287 Activate(); |
1325 Activate(); |
1288 } |
1326 } |
|
1327 |
1289 |
1328 |
1290 |
1329 void CActiveDeviceStateNotifier::Activate() |
1291 void CActiveDeviceStateNotifier::Activate() |
1330 /** |
1292 /** |
1331 * |
1293 * |
1332 */ |
1294 */ |
1333 { |
1295 { |
1334 __MSFNLOG |
1296 if (IsActive()) |
1335 if (IsActive()) |
1297 { |
1336 { |
1298 __PRINT(_L("Still active\n")); |
1337 __PRINT(_L("Still active\n")); |
1299 return; |
1338 return; |
1300 } |
1339 } |
1301 iParent.Ldd().AlternateDeviceStatusNotify(iStatus, iDeviceState); |
1340 iParent.Ldd().AlternateDeviceStatusNotify(iStatus, iDeviceState); |
1302 SetActive(); |
1341 SetActive(); |
1303 } |
1342 } |
|