|
1 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32/drivers/usbcc/chapter9.cpp |
|
15 // Platform independent layer (PIL) of the USB Device controller driver: |
|
16 // Processing of USB spec chapter 9 standard requests. |
|
17 // |
|
18 // |
|
19 |
|
20 /** |
|
21 @file chapter9.cpp |
|
22 @internalTechnology |
|
23 */ |
|
24 |
|
25 #include <usb/usbc.h> |
|
26 |
|
27 #include "controltransfersm.h" |
|
28 |
|
29 //#define ENABLE_EXCESSIVE_DEBUG_OUTPUT |
|
30 // |
|
31 // === USB Controller member function implementation - PSL API (protected) ======================== |
|
32 // |
|
33 |
|
34 /** Used to synchronize the Ep0 state machine between the PSL and PIL. |
|
35 Accepts a SETUP packet and returns the next Ep0 state. |
|
36 |
|
37 @param aSetupBuf The SETUP packet just received by the PSL. |
|
38 @return The next Ep0 state. |
|
39 |
|
40 @publishedPartner @released |
|
41 */ |
|
42 UsbShai::TControlStage DUsbClientController::EnquireEp0NextStage(const TUint8* aSetupBuf) const |
|
43 { |
|
44 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnquireEp0NextState()")); |
|
45 |
|
46 // This function may be called by the PSL from within an ISR -- so we have |
|
47 // to take care what we do here (and also in all functions that get called |
|
48 // from here). |
|
49 |
|
50 if (SWAP_BYTES_16((reinterpret_cast<const TUint16*>(aSetupBuf)[3])) == 0) // iLength |
|
51 { |
|
52 __KTRACE_OPT(KUSB, Kern::Printf(" --> EControlTransferStageStatusIn")); |
|
53 return UsbShai::EControlTransferStageStatusIn; // No-data Control => Status_IN |
|
54 } |
|
55 else if ((aSetupBuf[0] & KUsbRequestType_DirMask) == KUsbRequestType_DirToDev) |
|
56 { |
|
57 __KTRACE_OPT(KUSB, Kern::Printf(" --> EControlTransferStageDataOut")); |
|
58 return UsbShai::EControlTransferStageDataOut; // Control Write => Data_OUT |
|
59 } |
|
60 else |
|
61 { |
|
62 __KTRACE_OPT(KUSB, Kern::Printf(" --> EControlTransferStageDataIn")); |
|
63 return UsbShai::EControlTransferStageDataIn; // Control Read => Data_IN |
|
64 } |
|
65 } |
|
66 |
|
67 // |
|
68 // About iLastError. |
|
69 // This member is used to remember the last error happend during a |
|
70 // processXXX likewise function. |
|
71 // |
|
72 // Before entry of each ProcessXXX, iLastError will be cleared to KErrNone. |
|
73 // |
|
74 |
|
75 // --- The USB Spec Chapter 9 Standard Endpoint Zero Device Requests --- |
|
76 // Record error happend with iLastError, the value already been set to zero |
|
77 // before entering ProcessSetupPacket call. |
|
78 void DUsbClientController::ProcessGetDeviceStatus(const TUsbcSetup& aPacket) |
|
79 { |
|
80 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetDeviceStatus()")); |
|
81 if ( iDeviceState < UsbShai::EUsbPeripheralStateAddress) |
|
82 { |
|
83 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
84 iLastError = KErrGeneral; |
|
85 } |
|
86 else |
|
87 { |
|
88 // We always assume Device is bus-powered, even though mobile phone almost always |
|
89 // has a battry there, because self-powered device can not required more then 100ma current |
|
90 // which is not acceptable for Usb charging. |
|
91 TBool selfPowered = EFalse; |
|
92 |
|
93 /* FIXME: modify selfPowered to make it compilance with following rule. |
|
94 |
|
95 1. If current draw exceeds 100mA, the device must report itself |
|
96 as bus-powered during enumeration. |
|
97 |
|
98 2. In all cases, the GetStatus(DEVICE) call must accurately report |
|
99 whether the device is currently operating on self- or bus-power. |
|
100 |
|
101 3. A device that is actively drawing more than 100mA from USB must |
|
102 report itself as bus-powered in the GetStatus(DEVICE) call. |
|
103 |
|
104 4. Peripherals that return "Self-powered" in the GetStatus(DEVICE) |
|
105 call are prohibited from drawing more than 100mA at any time. |
|
106 */ |
|
107 /* |
|
108 TBuf8<KUsbDescSize_Config> config; |
|
109 |
|
110 if(iDescriptors.GetConfigurationDescriptorTC(&Kern::CurrentThread(),config) == KErrNone) |
|
111 { |
|
112 TUint8 maxPower = config[8]; |
|
113 if(maxPower <= 50) |
|
114 { |
|
115 selfPowered = EFalse; |
|
116 } |
|
117 } |
|
118 */ |
|
119 |
|
120 const TUint16 status = ((selfPowered ? KUsbDevStat_SelfPowered : 0) | |
|
121 (iRmWakeupStatus_Enabled ? KUsbDevStat_RemoteWakeup : 0)); |
|
122 __KTRACE_OPT(KUSB, Kern::Printf(" Reporting device status: 0x%02x", status)); |
|
123 *reinterpret_cast<TUint16*>(iEp0_TxBuf) = SWAP_BYTES_16(status); |
|
124 if (iConTransferMgr->SetupEndpointZeroWrite(iEp0_TxBuf, sizeof(status)) == KErrNone) |
|
125 { |
|
126 iEp0WritePending = ETrue; |
|
127 } |
|
128 else |
|
129 { |
|
130 __KTRACE_OPT(KUSB, Kern::Printf(" Wrong: Write to Ep0 Failed")); |
|
131 } |
|
132 } |
|
133 } |
|
134 |
|
135 void DUsbClientController::ProcessGetInterfaceStatus(const TUsbcSetup& aPacket) |
|
136 { |
|
137 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetInterfaceStatus()")); |
|
138 if ( iDeviceState < UsbShai::EUsbPeripheralStateConfigured) |
|
139 { |
|
140 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
141 iLastError = KErrGeneral; |
|
142 } |
|
143 else |
|
144 { |
|
145 if (InterfaceExists(aPacket.iIndex) == EFalse) |
|
146 { |
|
147 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Interface does not exist")); |
|
148 iLastError = KErrGeneral; |
|
149 } |
|
150 else |
|
151 { |
|
152 const TUint16 status = 0x0000; // as of USB Spec 2.0 |
|
153 __KTRACE_OPT(KUSB, Kern::Printf(" Reporting interface status: 0x%02x", status)); |
|
154 *reinterpret_cast<TUint16*>(iEp0_TxBuf) = SWAP_BYTES_16(status); |
|
155 if (iConTransferMgr->SetupEndpointZeroWrite(iEp0_TxBuf, sizeof(status)) == KErrNone) |
|
156 { |
|
157 iEp0WritePending = ETrue; |
|
158 } |
|
159 else |
|
160 { |
|
161 __KTRACE_OPT(KUSB, Kern::Printf(" Wrong: Write to Ep0 Failed")); |
|
162 } |
|
163 } |
|
164 } |
|
165 } |
|
166 |
|
167 |
|
168 void DUsbClientController::ProcessGetEndpointStatus(const TUsbcSetup& aPacket) |
|
169 { |
|
170 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetEndpointStatus()")); |
|
171 if ( |
|
172 ((iDeviceState < UsbShai::EUsbPeripheralStateAddress) || |
|
173 (iDeviceState == UsbShai::EUsbPeripheralStateAddress && (aPacket.iIndex & KUsbEpAddress_Portmask) != 0))) |
|
174 { |
|
175 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
176 iLastError = KErrGeneral; |
|
177 } |
|
178 else |
|
179 { |
|
180 if (EndpointExists(aPacket.iIndex) == EFalse) |
|
181 { |
|
182 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint does not exist")); |
|
183 iLastError = KErrGeneral; |
|
184 } |
|
185 else |
|
186 { |
|
187 const TInt ep = EpAddr2Idx(aPacket.iIndex); |
|
188 const TUint16 status = (iRealEndpoints[ep].iHalt) ? KUsbEpStat_Halt : 0; |
|
189 __KTRACE_OPT(KUSB, Kern::Printf(" Reporting endpoint status 0x%02x for real endpoint %d", |
|
190 status, ep)); |
|
191 *reinterpret_cast<TUint16*>(iEp0_TxBuf) = SWAP_BYTES_16(status); |
|
192 if (iConTransferMgr->SetupEndpointZeroWrite(iEp0_TxBuf, 2) == KErrNone) |
|
193 { |
|
194 iEp0WritePending = ETrue; |
|
195 } |
|
196 else |
|
197 { |
|
198 __KTRACE_OPT(KUSB, Kern::Printf(" Wrong: Write to Ep0 Failed")); |
|
199 } |
|
200 } |
|
201 } |
|
202 } |
|
203 |
|
204 |
|
205 void DUsbClientController::ProcessSetClearDevFeature(const TUsbcSetup& aPacket) |
|
206 { |
|
207 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetClearDevFeature()")); |
|
208 if ( iDeviceState < UsbShai::EUsbPeripheralStateDefault) |
|
209 { |
|
210 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
211 iLastError = KErrGeneral; |
|
212 return; |
|
213 } |
|
214 |
|
215 TInt test_sel = 0; |
|
216 |
|
217 if (aPacket.iRequest == KUsbRequest_SetFeature) |
|
218 { |
|
219 switch (aPacket.iValue) |
|
220 { |
|
221 case KUsbFeature_RemoteWakeup: |
|
222 if ( iDeviceState < UsbShai::EUsbPeripheralStateAddress) |
|
223 { |
|
224 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
225 iLastError = KErrGeneral; |
|
226 } |
|
227 else |
|
228 { |
|
229 iRmWakeupStatus_Enabled = ETrue; |
|
230 } |
|
231 break; |
|
232 |
|
233 case KUsbFeature_TestMode: |
|
234 if (!iHighSpeed) |
|
235 { |
|
236 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only supported in High-Speed mode")); |
|
237 iLastError = KErrGeneral; |
|
238 } |
|
239 else if (LowByte(aPacket.iIndex) != 0) |
|
240 { |
|
241 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Lower byte of wIndex must be zero")); |
|
242 iLastError = KErrGeneral; |
|
243 } |
|
244 else |
|
245 { |
|
246 test_sel = HighByte(aPacket.iIndex); |
|
247 if ((test_sel < UsbShai::EUsbTestSelector_Test_J) || (test_sel > UsbShai::EUsbTestSelector_Test_Force_Enable)) |
|
248 { |
|
249 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid test selector: %d", test_sel)); |
|
250 iLastError = KErrGeneral; |
|
251 } |
|
252 } |
|
253 break; |
|
254 |
|
255 case KUsbFeature_B_HnpEnable: |
|
256 if (!iOtgSupport) |
|
257 { |
|
258 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only supported on a OTG device")); |
|
259 iLastError = KErrGeneral; |
|
260 } |
|
261 else if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp)) |
|
262 { |
|
263 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only valid if OTG device supports HNP")); |
|
264 iLastError = KErrGeneral; |
|
265 } |
|
266 else |
|
267 { |
|
268 iOtgFuncMap |= KUsbOtgAttr_B_HnpEnable; |
|
269 OtgFeaturesNotify(); |
|
270 } |
|
271 break; |
|
272 |
|
273 case KUsbFeature_A_HnpSupport: |
|
274 if (!iOtgSupport) |
|
275 { |
|
276 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only supported on a OTG device")); |
|
277 iLastError = KErrGeneral; |
|
278 } |
|
279 else if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp)) |
|
280 { |
|
281 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only valid if OTG device supports HNP")); |
|
282 iLastError = KErrGeneral; |
|
283 } |
|
284 else |
|
285 { |
|
286 iOtgFuncMap |= KUsbOtgAttr_A_HnpSupport; |
|
287 OtgFeaturesNotify(); |
|
288 } |
|
289 break; |
|
290 |
|
291 case KUsbFeature_A_AltHnpSupport: |
|
292 if (!iOtgSupport) |
|
293 { |
|
294 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only supported on a OTG device")); |
|
295 iLastError = KErrGeneral; |
|
296 } |
|
297 else if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp)) |
|
298 { |
|
299 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only valid if OTG device supports HNP")); |
|
300 iLastError = KErrGeneral; |
|
301 } |
|
302 else |
|
303 { |
|
304 iOtgFuncMap |= KUsbOtgAttr_A_AltHnpSupport; |
|
305 OtgFeaturesNotify(); |
|
306 } |
|
307 break; |
|
308 |
|
309 default: |
|
310 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Unknown feature requested")); |
|
311 iLastError = KErrGeneral; |
|
312 } |
|
313 } |
|
314 else // KUsbRequest_ClearFeature |
|
315 { |
|
316 switch (aPacket.iValue) |
|
317 { |
|
318 case KUsbFeature_RemoteWakeup: |
|
319 if ( iDeviceState < UsbShai::EUsbPeripheralStateAddress) |
|
320 { |
|
321 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
322 iLastError = KErrGeneral; |
|
323 } |
|
324 else |
|
325 { |
|
326 iRmWakeupStatus_Enabled = EFalse; |
|
327 } |
|
328 break; |
|
329 |
|
330 default: |
|
331 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Unknown feature requested")); |
|
332 iLastError = KErrGeneral; |
|
333 } |
|
334 } |
|
335 |
|
336 if(iLastError == KErrNone) |
|
337 { |
|
338 // Sent out status packet if no error found. |
|
339 iConTransferMgr->SendEp0ZeroByteStatusPacket(); // success: zero bytes data during status stage |
|
340 |
|
341 // 9.4.9: "The transition to test mode of an upstream facing port must not happen until |
|
342 // after the status stage of the request." |
|
343 if (test_sel) |
|
344 { |
|
345 __KTRACE_OPT(KPANIC, Kern::Printf(" Entering HS Test Mode %d", test_sel)); |
|
346 iController.EnterTestMode((UsbShai::TUsbTestModeSelector)test_sel); |
|
347 } |
|
348 } |
|
349 } |
|
350 |
|
351 |
|
352 void DUsbClientController::ProcessSetClearIfcFeature(const TUsbcSetup& aPacket) |
|
353 { |
|
354 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetClearIfcFeature()")); |
|
355 if ( iDeviceState < UsbShai::EUsbPeripheralStateConfigured) |
|
356 { |
|
357 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
358 iLastError = KErrGeneral; |
|
359 } |
|
360 else |
|
361 { |
|
362 // No interface features defined in USB spec, thus |
|
363 iLastError = KErrGeneral; |
|
364 } |
|
365 } |
|
366 |
|
367 |
|
368 void DUsbClientController::ProcessSetClearEpFeature(const TUsbcSetup& aPacket) |
|
369 { |
|
370 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetClearEpFeature()")); |
|
371 if ( |
|
372 ((iDeviceState < UsbShai::EUsbPeripheralStateAddress) || |
|
373 (iDeviceState == UsbShai::EUsbPeripheralStateAddress && (aPacket.iIndex & KUsbEpAddress_Portmask) != 0))) |
|
374 { |
|
375 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
376 iLastError = KErrGeneral; |
|
377 } |
|
378 else if (aPacket.iValue != KUsbFeature_EndpointHalt) |
|
379 { |
|
380 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Unknown feature requested")); |
|
381 iLastError = KErrGeneral; |
|
382 } |
|
383 else if (EndpointExists(aPacket.iIndex) == EFalse) |
|
384 { |
|
385 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint does not exist")); |
|
386 iLastError = KErrGeneral; |
|
387 } |
|
388 else |
|
389 { |
|
390 const TInt ep = EpAddr2Idx(aPacket.iIndex); |
|
391 if (iRealEndpoints[ep].iLEndpoint->iInfo.iType == UsbShai::KUsbEpTypeControl || |
|
392 iRealEndpoints[ep].iLEndpoint->iInfo.iType == UsbShai::KUsbEpTypeIsochronous) |
|
393 { |
|
394 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint is Control or Isochronous")); |
|
395 iLastError = KErrGeneral; |
|
396 } |
|
397 else |
|
398 { |
|
399 SetClearHaltFeature(ep, aPacket.iRequest); |
|
400 |
|
401 // success: zero bytes data during status stage |
|
402 iConTransferMgr->SendEp0ZeroByteStatusPacket(); |
|
403 } |
|
404 } |
|
405 } |
|
406 |
|
407 |
|
408 void DUsbClientController::ProcessSetAddress(const TUsbcSetup& aPacket) |
|
409 { |
|
410 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetAddress()")); |
|
411 if ( iDeviceState > UsbShai::EUsbPeripheralStateAddress) |
|
412 { |
|
413 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
414 iLastError = KErrGeneral; |
|
415 } |
|
416 else |
|
417 { |
|
418 const TUint16 addr = aPacket.iValue; |
|
419 |
|
420 if (addr > 127) |
|
421 { |
|
422 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Bad address value: %d (>127)", addr)); |
|
423 iLastError = KErrGeneral; |
|
424 } |
|
425 else if (addr == 0) |
|
426 { |
|
427 // Enter Default state (from Default or Address) |
|
428 NextDeviceState(UsbShai::EUsbPeripheralStateDefault); |
|
429 } |
|
430 |
|
431 __KTRACE_OPT(KUSB, Kern::Printf(" USB address: %d", addr)); |
|
432 |
|
433 // If controller support hw acceleration,call set address first and then status |
|
434 if(iControllerProperties.iControllerCaps & UsbShai::KDevCapSetAddressAcceleration) |
|
435 { |
|
436 iController.SetDeviceAddress(addr); |
|
437 } |
|
438 |
|
439 // The spec says, under section 9.4.6: |
|
440 // "Stages after the initial Setup packet assume the same device address as the Setup packet. The USB |
|
441 // device does not change its device address until after the Status stage of this request is completed |
|
442 // successfully. Note that this is a difference between this request and all other requests. For all other |
|
443 // requests, the operation indicated must be completed before the Status stage." |
|
444 // Therefore, here we first send the status packet and only then actually execute the request. |
|
445 iConTransferMgr->SendEp0ZeroByteStatusPacket(); |
|
446 |
|
447 // If controller doesn't support hw acceleration, call set address after status |
|
448 if((iControllerProperties.iControllerCaps & UsbShai::KDevCapSetAddressAcceleration) == 0) |
|
449 { |
|
450 iController.SetDeviceAddress(addr); |
|
451 } |
|
452 } |
|
453 } |
|
454 |
|
455 |
|
456 void DUsbClientController::ProcessGetDescriptor(const TUsbcSetup& aPacket) |
|
457 { |
|
458 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetDescriptor()")); |
|
459 if ( iDeviceState < UsbShai::EUsbPeripheralStateDefault) |
|
460 { |
|
461 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
462 iLastError = KErrGeneral; |
|
463 return ; |
|
464 } |
|
465 |
|
466 // Make sure we assume the correct speed |
|
467 __ASSERT_DEBUG((iHighSpeed == CurrentlyUsingHighSpeed()), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
|
468 |
|
469 TInt size = 0; |
|
470 const TInt result = iDescriptors.FindDescriptor(HighByte(aPacket.iValue), // Type |
|
471 LowByte(aPacket.iValue), // Index |
|
472 aPacket.iIndex, // Language ID |
|
473 size); |
|
474 |
|
475 if ((result != KErrNone) || (size == 0)) |
|
476 { |
|
477 // This doesn't have to be an error - protocol-wise it's OK. |
|
478 __KTRACE_OPT(KUSB, Kern::Printf(" Couldn't retrieve descriptor")); |
|
479 iLastError = KErrGeneral; |
|
480 return; |
|
481 } |
|
482 |
|
483 __KTRACE_OPT(KUSB, Kern::Printf(" Descriptor found, size: %d (requested: %d)", |
|
484 size, aPacket.iLength)); |
|
485 if (size > KUsbcBufSz_Ep0Tx) |
|
486 { |
|
487 // This should actually not be possible (i.e. we should never get here). |
|
488 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Ep0_Tx buffer too small")); |
|
489 } |
|
490 if (size > aPacket.iLength) |
|
491 { |
|
492 // Send only as much data as requested by the host |
|
493 size = aPacket.iLength; |
|
494 } |
|
495 |
|
496 #ifdef ENABLE_EXCESSIVE_DEBUG_OUTPUT |
|
497 __KTRACE_OPT(KUSB, |
|
498 Kern::Printf(" Data: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x ...", |
|
499 iEp0_TxBuf[0], iEp0_TxBuf[1], iEp0_TxBuf[2], iEp0_TxBuf[3], |
|
500 iEp0_TxBuf[4], iEp0_TxBuf[5], iEp0_TxBuf[6], iEp0_TxBuf[7])); |
|
501 #endif |
|
502 // If we're about to send less bytes than expected by the host AND our number is a |
|
503 // multiple of the packet size, in order to indicate the end of the control transfer, |
|
504 // we must finally send a zero length data packet (ZLP): |
|
505 const TBool zlp = ((size < aPacket.iLength) && (size % iEp0MaxPacketSize == 0)); |
|
506 if (iConTransferMgr->SetupEndpointZeroWrite(iEp0_TxBuf, size, zlp) == KErrNone) |
|
507 { |
|
508 iEp0WritePending = ETrue; |
|
509 } |
|
510 else |
|
511 { |
|
512 __KTRACE_OPT(KUSB, Kern::Printf(" Wrong: Write to Ep0 Failed")); |
|
513 } |
|
514 } |
|
515 |
|
516 |
|
517 void DUsbClientController::ProcessSetDescriptor(const TUsbcSetup& aPacket) |
|
518 { |
|
519 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetDescriptor()")); |
|
520 #ifndef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST |
|
521 iLastError = KErrGeneral; |
|
522 return; |
|
523 #else |
|
524 if ( iDeviceState < UsbShai::EUsbPeripheralStateAddress) |
|
525 { |
|
526 // Error: Invalid device state! |
|
527 iLastError = KErrGeneral; |
|
528 } |
|
529 else if (aPacket.iLength > KUsbcBufSz_Ep0Rx) |
|
530 { |
|
531 // Error: Our Rx buffer is too small! (Raise a defect to make it larger) |
|
532 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Ep0_Rx buffer too small")); |
|
533 iLastError = KErrGeneral; |
|
534 } |
|
535 else |
|
536 { |
|
537 SetEp0DataOutVars(); |
|
538 iConTransferMgr->SetupEndpointZeroRead(); |
|
539 } |
|
540 #endif |
|
541 } |
|
542 |
|
543 void DUsbClientController::ProcessGetConfiguration(const TUsbcSetup& aPacket) |
|
544 { |
|
545 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetConfiguration()")); |
|
546 if ( iDeviceState < UsbShai::EUsbPeripheralStateAddress) |
|
547 { |
|
548 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
549 iLastError = KErrGeneral; |
|
550 } |
|
551 else if ( iDeviceState == UsbShai::EUsbPeripheralStateAddress && iCurrentConfig != 0) |
|
552 { |
|
553 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: DeviceState Address && Config != 0")); |
|
554 iLastError = KErrGeneral; |
|
555 } |
|
556 else if ( iDeviceState == UsbShai::EUsbPeripheralStateConfigured && iCurrentConfig == 0) |
|
557 { |
|
558 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: DeviceState Configured && Config == 0")); |
|
559 iLastError = KErrGeneral; |
|
560 } |
|
561 else |
|
562 { |
|
563 if (aPacket.iLength != 1) // "unspecified behavior" |
|
564 { |
|
565 __KTRACE_OPT(KUSB, Kern::Printf(" Warning: wLength != 1 (= %d)", aPacket.iLength)); |
|
566 } |
|
567 __KTRACE_OPT(KUSB, Kern::Printf(" Reporting configuration value %d", iCurrentConfig)); |
|
568 if (iConTransferMgr->SetupEndpointZeroWrite(&iCurrentConfig, sizeof(iCurrentConfig)) == KErrNone) |
|
569 { |
|
570 iEp0WritePending = ETrue; |
|
571 } |
|
572 else |
|
573 { |
|
574 __KTRACE_OPT(KUSB, Kern::Printf(" Wrong: Write to Ep0 Failed")); |
|
575 } |
|
576 } |
|
577 } |
|
578 |
|
579 |
|
580 /** Changes the device's configuration value, including interface setup and/or |
|
581 teardown and state change notification of higher-layer clients. |
|
582 May also be called by the PSL in special cases - therefore publishedPartner. |
|
583 |
|
584 @param aPacket The received Ep0 SET_CONFIGURATION setup request packet. |
|
585 @return KErrGeneral in case of a protocol error, KErrNone otherwise. |
|
586 |
|
587 @publishedPartner @released |
|
588 */ |
|
589 TInt DUsbClientController::ProcessSetConfiguration(const TUsbcSetup& aPacket) |
|
590 { |
|
591 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetConfiguration()")); |
|
592 |
|
593 // This function may be called by the PSL from within an ISR -- so we have |
|
594 // to take care what we do here (and also in all functions that get called |
|
595 // from here). |
|
596 const TInt value = aPacket.iValue; |
|
597 |
|
598 if ( iDeviceState < UsbShai::EUsbPeripheralStateAddress) |
|
599 { |
|
600 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
601 iLastError = KErrGeneral; |
|
602 } |
|
603 else if (value > 1) // we support only one configuration |
|
604 { |
|
605 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Configuration value too large: %d", value)); |
|
606 iLastError = KErrGeneral; |
|
607 } |
|
608 else |
|
609 { |
|
610 __KTRACE_OPT(KUSB, Kern::Printf(" Configuration value: %d", value)); |
|
611 ChangeConfiguration(value); |
|
612 |
|
613 // In 9.4.5 under GET_STATUS we read, that after SET_CONFIGURATION the HALT feature |
|
614 // for all endpoints is reset to zero. |
|
615 TInt num = 0; |
|
616 (TAny) DoForEveryEndpointInUse(&DUsbClientController::ClearHaltFeature, num); |
|
617 __KTRACE_OPT(KUSB, Kern::Printf(" Called ClearHaltFeature() for %d endpoints", num)); |
|
618 // success: zero bytes data during status stage |
|
619 iConTransferMgr->SendEp0ZeroByteStatusPacket(); |
|
620 } |
|
621 |
|
622 return iLastError; |
|
623 } |
|
624 |
|
625 void DUsbClientController::ProcessGetInterface(const TUsbcSetup& aPacket) |
|
626 { |
|
627 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetInterface()")); |
|
628 |
|
629 const TInt number = aPacket.iIndex; |
|
630 |
|
631 if ( iDeviceState < UsbShai::EUsbPeripheralStateConfigured) |
|
632 { |
|
633 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
634 iLastError = KErrGeneral; |
|
635 } |
|
636 else if (iCurrentConfig == 0) |
|
637 { |
|
638 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Device not configured")); |
|
639 iLastError = KErrGeneral; |
|
640 } |
|
641 else if (!InterfaceExists(number)) |
|
642 { |
|
643 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Bad interface index: %d", number)); |
|
644 iLastError = KErrGeneral; |
|
645 } |
|
646 else |
|
647 { |
|
648 // Send alternate setting code of iCurrentInterface of Interface(set) <number> of the current |
|
649 // config (iCurrentConfig). |
|
650 const TUint8 setting = InterfaceNumber2InterfacePointer(number)->iCurrentInterface; |
|
651 __KTRACE_OPT(KUSB, Kern::Printf(" Reporting interface setting %d", setting)); |
|
652 if (iConTransferMgr->SetupEndpointZeroWrite(&setting, 1) == KErrNone) |
|
653 { |
|
654 iEp0WritePending = ETrue; |
|
655 } |
|
656 else |
|
657 { |
|
658 __KTRACE_OPT(KUSB, Kern::Printf(" Wrong: Write to Ep0 Failed")); |
|
659 } |
|
660 } |
|
661 } |
|
662 |
|
663 |
|
664 void DUsbClientController::ProcessSetInterface(const TUsbcSetup& aPacket) |
|
665 { |
|
666 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetInterface()")); |
|
667 |
|
668 const TInt number = aPacket.iIndex; |
|
669 |
|
670 if ( iDeviceState < UsbShai::EUsbPeripheralStateConfigured) |
|
671 { |
|
672 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
673 iLastError = KErrGeneral; |
|
674 } |
|
675 else if (iCurrentConfig == 0) |
|
676 { |
|
677 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Device not configured")); |
|
678 iLastError = KErrGeneral; |
|
679 } |
|
680 else if (!InterfaceExists(number)) |
|
681 { |
|
682 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Bad interface index: %d", number)); |
|
683 iLastError = KErrGeneral; |
|
684 } |
|
685 else |
|
686 { |
|
687 const TInt setting = aPacket.iValue; |
|
688 TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(number); |
|
689 RPointerArray<TUsbcInterface>& ifcs = ifcset_ptr->iInterfaces; |
|
690 if (setting >= ifcs.Count()) |
|
691 { |
|
692 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Alt Setting >= bNumAltSettings: %d", setting)); |
|
693 iLastError = KErrGeneral; |
|
694 } |
|
695 else |
|
696 { |
|
697 __KTRACE_OPT(KUSB, Kern::Printf(" Interface setting:: %d", setting)); |
|
698 // Set iCurrentInterface of Interface(set) <number> of the current config |
|
699 // (iCurrentConfig) to alternate setting <setting>. |
|
700 ChangeInterface(ifcs[setting]); |
|
701 // In 9.4.5 under GET_STATUS we read, that after SET_INTERFACE the HALT feature |
|
702 // for all endpoints (of the now current interface setting) is reset to zero. |
|
703 RPointerArray<TUsbcLogicalEndpoint>& eps = ifcset_ptr->CurrentInterface()->iEndpoints; |
|
704 const TInt num_eps = eps.Count(); |
|
705 for (TInt i = 0; i < num_eps; i++) |
|
706 { |
|
707 const TInt ep_num = EpAddr2Idx(eps[i]->iPEndpoint->iEndpointAddr); |
|
708 (TAny) ClearHaltFeature(ep_num); |
|
709 } |
|
710 // success: zero bytes data during status stage |
|
711 iConTransferMgr->SendEp0ZeroByteStatusPacket(); |
|
712 } |
|
713 } |
|
714 } |
|
715 |
|
716 |
|
717 void DUsbClientController::ProcessSynchFrame(const TUsbcSetup& aPacket) |
|
718 { |
|
719 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSynchFrame()")); |
|
720 |
|
721 const TInt ep = aPacket.iIndex; |
|
722 |
|
723 if ( iDeviceState < UsbShai::EUsbPeripheralStateConfigured) |
|
724 { |
|
725 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
726 iLastError = KErrGeneral; |
|
727 } |
|
728 else if (EndpointExists(ep) == EFalse) |
|
729 { |
|
730 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint does not exist")); |
|
731 iLastError = KErrGeneral; |
|
732 } |
|
733 else if (iRealEndpoints[EpAddr2Idx(ep)].iLEndpoint->iInfo.iType != UsbShai::KUsbEpTypeIsochronous) |
|
734 { |
|
735 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint is not isochronous")); |
|
736 iLastError = KErrGeneral; |
|
737 } |
|
738 else |
|
739 { |
|
740 // We always send 0: |
|
741 *reinterpret_cast<TUint16*>(iEp0_TxBuf) = 0x00; |
|
742 if (iConTransferMgr->SetupEndpointZeroWrite(iEp0_TxBuf, 2) == KErrNone) |
|
743 { |
|
744 iEp0WritePending = ETrue; |
|
745 } |
|
746 else |
|
747 { |
|
748 __KTRACE_OPT(KUSB, Kern::Printf(" Wrong: Write to Ep0 Failed")); |
|
749 } |
|
750 } |
|
751 } |
|
752 |
|
753 |
|
754 #ifdef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST |
|
755 void DUsbClientController::ProceedSetDescriptor() |
|
756 { |
|
757 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProceedSetDescriptor()")); |
|
758 // iEp0DataReceived already reflects the current buffer state |
|
759 if (iEp0DataReceived < iConTransferMgr->PktParser().DataLength()) |
|
760 { |
|
761 // Not yet all data received => proceed |
|
762 return; |
|
763 } |
|
764 if (iEp0DataReceived > iConTransferMgr->PktParser().DataLength()) |
|
765 { |
|
766 // Error: more data received than expected |
|
767 // but we don't care... |
|
768 } |
|
769 const TUint8 type = HighByte(iConTransferMgr->PktParser().Value()); |
|
770 if (type == KUsbDescType_String) |
|
771 { |
|
772 // set/add new string descriptor |
|
773 } |
|
774 else |
|
775 { |
|
776 // set/add new ordinary descriptor |
|
777 } |
|
778 TUint8 index = LowByte(iConTransferMgr->PktParser().Value()); |
|
779 TUint16 langid = iConTransferMgr->PktParser().Index(); |
|
780 TUint16 length_total = iConTransferMgr->PktParser().DataLength(); |
|
781 |
|
782 iConTransferMgr->SendEp0ZeroByteStatusPacket(); |
|
783 } |
|
784 #endif |
|
785 |
|
786 |
|
787 // --- Secondary (Helper) Functions |
|
788 |
|
789 void DUsbClientController::SetClearHaltFeature(TInt aRealEndpoint, TUint8 aRequest) |
|
790 { |
|
791 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetClearHaltFeature()")); |
|
792 if (aRequest == KUsbRequest_SetFeature) |
|
793 { |
|
794 if (iRealEndpoints[aRealEndpoint].iHalt) |
|
795 { |
|
796 // (This condition is not really an error) |
|
797 __KTRACE_OPT(KUSB, Kern::Printf(" Warning: HALT feature already set")); |
|
798 return; |
|
799 } |
|
800 __KTRACE_OPT(KUSB, Kern::Printf(" setting HALT feature for real endpoint %d", |
|
801 aRealEndpoint)); |
|
802 iController.StallEndpoint(aRealEndpoint); |
|
803 iRealEndpoints[aRealEndpoint].iHalt = ETrue; |
|
804 } |
|
805 else // KUsbRequest_ClearFeature |
|
806 { |
|
807 if (iRealEndpoints[aRealEndpoint].iHalt == EFalse) |
|
808 { |
|
809 // In this case, before we return, the data toggles are reset to DATA0. |
|
810 __KTRACE_OPT(KUSB, Kern::Printf(" Warning: HALT feature already cleared")); |
|
811 iController.ResetDataToggle(aRealEndpoint); |
|
812 return; |
|
813 } |
|
814 __KTRACE_OPT(KUSB, Kern::Printf(" clearing HALT feature for real endpoint %d", |
|
815 aRealEndpoint)); |
|
816 iController.ResetDataToggle(aRealEndpoint); |
|
817 iController.ClearStallEndpoint(aRealEndpoint); |
|
818 iRealEndpoints[aRealEndpoint].iHalt = EFalse; |
|
819 } |
|
820 EpStatusNotify(aRealEndpoint); // only called if actually something changed |
|
821 } |
|
822 |
|
823 |
|
824 TInt DUsbClientController::ClearHaltFeature(TInt aRealEndpoint) |
|
825 { |
|
826 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ClearHaltFeature()")); |
|
827 if (iRealEndpoints[aRealEndpoint].iHalt != EFalse) |
|
828 { |
|
829 iController.ClearStallEndpoint(aRealEndpoint); |
|
830 iRealEndpoints[aRealEndpoint].iHalt = EFalse; |
|
831 } |
|
832 return KErrNone; |
|
833 } |
|
834 |
|
835 |
|
836 void DUsbClientController::ChangeConfiguration(TUint16 aValue) |
|
837 { |
|
838 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ChangeConfiguration()")); |
|
839 // New configuration is the same as the old one: 0 |
|
840 if (iCurrentConfig == 0 && aValue == 0) |
|
841 { |
|
842 // no-op |
|
843 __KTRACE_OPT(KUSB, Kern::Printf(" Configuration: New == Old == 0 --> exiting")); |
|
844 return; |
|
845 } |
|
846 // New configuration is the same as the old one (but not 0) |
|
847 if (iCurrentConfig == aValue) |
|
848 { |
|
849 // no-op |
|
850 __KTRACE_OPT(KUSB, Kern::Printf(" Configuration: New == Old == %d --> exiting", aValue)); |
|
851 return; |
|
852 } |
|
853 // Device is already configured |
|
854 if (iCurrentConfig != 0) |
|
855 { |
|
856 __KTRACE_OPT(KUSB, Kern::Printf(" Device was configured: %d", iCurrentConfig)); |
|
857 // Tear down all interface(set)s of the old configuration |
|
858 RPointerArray<TUsbcInterfaceSet>& ifcsets = CurrentConfig()->iInterfaceSets; |
|
859 for (TInt i = 0; i < ifcsets.Count(); ++i) |
|
860 { |
|
861 __KTRACE_OPT(KUSB, Kern::Printf(" Tearing down InterfaceSet %d", i)); |
|
862 InterfaceSetTeardown(ifcsets[i]); |
|
863 } |
|
864 iCurrentConfig = 0; |
|
865 // Enter Address state (from Configured) |
|
866 if (iDeviceState == UsbShai::EUsbPeripheralStateConfigured) |
|
867 NextDeviceState(UsbShai::EUsbPeripheralStateAddress); |
|
868 } |
|
869 // Device gets a new configuration |
|
870 if (aValue != 0) |
|
871 { |
|
872 __KTRACE_OPT(KUSB, Kern::Printf(" Device gets new configuration...")); |
|
873 // Setup all alternate settings 0 of all interfaces |
|
874 // (Don't separate the next two lines of code.) |
|
875 iCurrentConfig = aValue; |
|
876 RPointerArray<TUsbcInterfaceSet>& ifcsets = CurrentConfig()->iInterfaceSets; |
|
877 const TInt n = ifcsets.Count(); |
|
878 for (TInt i = 0; i < n; ++i) |
|
879 { |
|
880 __KTRACE_OPT(KUSB, Kern::Printf(" Setting up InterfaceSet %d", i)); |
|
881 InterfaceSetup(ifcsets[i]->iInterfaces[0]); |
|
882 } |
|
883 // Enter Configured state (from Address or Configured) |
|
884 NextDeviceState(UsbShai::EUsbPeripheralStateConfigured); |
|
885 } |
|
886 __KTRACE_OPT(KUSB, Kern::Printf(" New configuration: %d", iCurrentConfig)); |
|
887 return; |
|
888 } |
|
889 |
|
890 |
|
891 void DUsbClientController::InterfaceSetup(TUsbcInterface* aIfc) |
|
892 { |
|
893 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::InterfaceSetup()")); |
|
894 const TInt num_eps = aIfc->iEndpoints.Count(); |
|
895 for (TInt i = 0; i < num_eps; i++) |
|
896 { |
|
897 // Prepare this endpoint for I/O |
|
898 TUsbcLogicalEndpoint* const ep = aIfc->iEndpoints[i]; |
|
899 // (TUsbcLogicalEndpoint's FS/HS endpoint sizes and interval values got |
|
900 // adjusted in its constructor.) |
|
901 if (iHighSpeed) |
|
902 { |
|
903 __KTRACE_OPT(KUSB, Kern::Printf(" Setting Ep info size to %d (HS)", ep->iEpSize_Hs)); |
|
904 ep->iInfo.iSize = ep->iEpSize_Hs; |
|
905 } |
|
906 else |
|
907 { |
|
908 __KTRACE_OPT(KUSB, Kern::Printf(" Setting Ep info size to %d (FS)", ep->iEpSize_Fs)); |
|
909 ep->iInfo.iSize = ep->iEpSize_Fs; |
|
910 } |
|
911 const TInt idx = EpAddr2Idx(ep->iPEndpoint->iEndpointAddr); |
|
912 if (iController.ConfigureEndpoint(idx, ep->iInfo) != KErrNone) |
|
913 { |
|
914 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint %d configuration failed", idx)); |
|
915 continue; |
|
916 } |
|
917 // Should there be a problem with it then we could try resetting the ep |
|
918 // data toggle at this point (or before the Configure) as well. |
|
919 __KTRACE_OPT(KUSB, Kern::Printf(" Connecting real ep addr 0x%02x & logical ep #%d", |
|
920 ep->iPEndpoint->iEndpointAddr, ep->iLEndpointNum)); |
|
921 ep->iPEndpoint->iLEndpoint = ep; |
|
922 } |
|
923 aIfc->iInterfaceSet->iCurrentInterface = aIfc->iSettingCode; |
|
924 return; |
|
925 } |
|
926 |
|
927 |
|
928 void DUsbClientController::InterfaceSetTeardown(TUsbcInterfaceSet* aIfcSet) |
|
929 { |
|
930 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::InterfaceSetTeardown()")); |
|
931 if (aIfcSet->iInterfaces.Count() == 0) |
|
932 { |
|
933 __KTRACE_OPT(KUSB, Kern::Printf(" No interfaces exist - returning")); |
|
934 return; |
|
935 } |
|
936 RPointerArray<TUsbcLogicalEndpoint>& eps = aIfcSet->CurrentInterface()->iEndpoints; |
|
937 const TInt num_eps = eps.Count(); |
|
938 for (TInt i = 0; i < num_eps; i++) |
|
939 { |
|
940 TUsbcLogicalEndpoint* const ep = eps[i]; |
|
941 const TInt idx = EpAddr2Idx(ep->iPEndpoint->iEndpointAddr); |
|
942 |
|
943 CancelTransferRequests(idx); |
|
944 |
|
945 if (!ep->iPEndpoint->iLEndpoint) |
|
946 { |
|
947 __KTRACE_OPT(KUSB, Kern::Printf(" real ep %d not configured: skipping", idx)); |
|
948 continue; |
|
949 } |
|
950 if (iController.ResetDataToggle(idx) != KErrNone) |
|
951 { |
|
952 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint %d data toggle reset failed", idx)); |
|
953 } |
|
954 if (iController.DeConfigureEndpoint(idx) != KErrNone) |
|
955 { |
|
956 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint %d de-configuration failed", idx)); |
|
957 } |
|
958 |
|
959 __KTRACE_OPT(KUSB, Kern::Printf(" disconnecting real ep & logical ep")); |
|
960 ep->iPEndpoint->iLEndpoint = NULL; |
|
961 } |
|
962 if (aIfcSet->CurrentInterface() != 0) |
|
963 { |
|
964 __KTRACE_OPT(KUSB, Kern::Printf(" Resetting alternate interface setting to 0")); |
|
965 //Add this mutex to protect the interface set data structure |
|
966 if (NKern::CurrentContext() == EThread) |
|
967 { |
|
968 NKern::FMWait(&iMutex); |
|
969 } |
|
970 |
|
971 aIfcSet->iCurrentInterface = 0; |
|
972 if (NKern::CurrentContext() == EThread) |
|
973 { |
|
974 NKern::FMSignal(&iMutex); |
|
975 } |
|
976 } |
|
977 return; |
|
978 } |
|
979 |
|
980 |
|
981 void DUsbClientController::ChangeInterface(TUsbcInterface* aIfc) |
|
982 { |
|
983 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ChangeInterface()")); |
|
984 TUsbcInterfaceSet* ifcset = aIfc->iInterfaceSet; |
|
985 const TUint8 setting = aIfc->iSettingCode; |
|
986 if (ifcset->iCurrentInterface == setting) |
|
987 { |
|
988 __KTRACE_OPT(KUSB, Kern::Printf(" New Ifc == old Ifc: nothing to do")); |
|
989 return; |
|
990 } |
|
991 __KTRACE_OPT(KUSB, Kern::Printf(" Setting new interface setting #%d", setting)); |
|
992 InterfaceSetTeardown(ifcset); |
|
993 InterfaceSetup(aIfc); |
|
994 StatusNotify(static_cast<UsbShai::TUsbPeripheralState>(KUsbAlternateSetting | setting), ifcset->iClientId); |
|
995 } |
|
996 |
|
997 |
|
998 // aFunction gets called, successively, with the endpoint index of every ep in-use as its argument. |
|
999 // (BTW: The declaration "type (class::*name)(params)" makes <name> a "pointer to element function".) |
|
1000 // |
|
1001 TInt DUsbClientController::DoForEveryEndpointInUse(TInt (DUsbClientController::*aFunction)(TInt), TInt& aCount) |
|
1002 { |
|
1003 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DoForEveryEndpointInUse()")); |
|
1004 aCount = 0; |
|
1005 TUsbcConfiguration* const config = CurrentConfig(); |
|
1006 if (!config) |
|
1007 { |
|
1008 __KTRACE_OPT(KUSB, Kern::Printf(" Device is not configured - returning")); |
|
1009 return KErrNone; |
|
1010 } |
|
1011 RPointerArray<TUsbcInterfaceSet>& ifcsets = config->iInterfaceSets; |
|
1012 const TInt num_ifcsets = ifcsets.Count(); |
|
1013 for (TInt i = 0; i < num_ifcsets; i++) |
|
1014 { |
|
1015 RPointerArray<TUsbcLogicalEndpoint>& eps = ifcsets[i]->CurrentInterface()->iEndpoints; |
|
1016 const TInt num_eps = eps.Count(); |
|
1017 for (TInt j = 0; j < num_eps; j++) |
|
1018 { |
|
1019 const TInt ep_num = EpAddr2Idx(eps[j]->iPEndpoint->iEndpointAddr); |
|
1020 const TInt result = (this->*aFunction)(ep_num); |
|
1021 ++aCount; |
|
1022 if (result != KErrNone) |
|
1023 { |
|
1024 return result; |
|
1025 } |
|
1026 } |
|
1027 } |
|
1028 return KErrNone; |
|
1029 } |
|
1030 |
|
1031 // Data Tx is done. |
|
1032 void DUsbClientController::ProcessDataInPacket(TInt aCount,TInt aErrCode) |
|
1033 { |
|
1034 // Clear Error Code |
|
1035 iLastError = KErrNone; |
|
1036 |
|
1037 // For tx, no premature end is allowed. |
|
1038 if(aErrCode != KErrNone) |
|
1039 { |
|
1040 // something wrong in hardware, we can do nothing as remedy |
|
1041 // just stall the endpoint. |
|
1042 iConTransferMgr->StallEndpoint(KEp0_In); |
|
1043 iConTransferMgr->SetupEndpointZeroRead(); |
|
1044 |
|
1045 // set err code to Error general if end point is stalled |
|
1046 iLastError = KErrGeneral; |
|
1047 } |
|
1048 else |
|
1049 { |
|
1050 // no longer a write pending |
|
1051 iEp0WritePending = EFalse; |
|
1052 |
|
1053 // If it was a client who set up this transmission, we report to that client |
|
1054 if (iEp0ClientDataTransmitting) |
|
1055 { |
|
1056 iEp0ClientDataTransmitting = EFalse; |
|
1057 TUsbcRequestCallback* const p = iRequestCallbacks[KEp0_Tx]; |
|
1058 |
|
1059 if (p) |
|
1060 { |
|
1061 __ASSERT_DEBUG((p->iTransferDir == UsbShai::EControllerWrite), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
|
1062 p->iError = aErrCode; |
|
1063 p->iTxBytes = aCount; |
|
1064 |
|
1065 // tell the client that the sending is done |
|
1066 // later, it is possible that a status out packet comes in, |
|
1067 // just ignore it. |
|
1068 ProcessDataTransferDone(*p); |
|
1069 } |
|
1070 else |
|
1071 { |
|
1072 // we should never goes here |
|
1073 iConTransferMgr->StallEndpoint(KEp0_In); |
|
1074 |
|
1075 // request not found |
|
1076 iLastError = KErrNotFound; |
|
1077 } |
|
1078 } |
|
1079 // else |
|
1080 // it is our own who sending the data, no more action needed |
|
1081 } |
|
1082 } |
|
1083 |
|
1084 // Status Rx is done |
|
1085 void DUsbClientController::ProcessStatusOutPacket(TInt aErrCode) |
|
1086 { |
|
1087 // Clear Error Code |
|
1088 iLastError = KErrNone; |
|
1089 |
|
1090 // Dangdang, psl saying a status out packet recieved from |
|
1091 // host, but, we already completed user's writting request, just ignore it. |
|
1092 |
|
1093 // any way, receiving this means no write is pending. |
|
1094 iEp0WritePending = EFalse; |
|
1095 } |
|
1096 |
|
1097 // Data Rx is (partial) done |
|
1098 void DUsbClientController::ProcessDataOutPacket(TInt aCount,TInt aErrCode) |
|
1099 { |
|
1100 // Clear Error Code |
|
1101 iLastError = KErrNone; |
|
1102 |
|
1103 if (aErrCode != KErrNone && aErrCode != KErrPrematureEnd) |
|
1104 { |
|
1105 // something wrong in hardware, we can do nothing as remedy |
|
1106 // just stall the endpoint. |
|
1107 iConTransferMgr->StallEndpoint(KEp0_Out); |
|
1108 iConTransferMgr->SetupEndpointZeroRead(); |
|
1109 |
|
1110 // set err code to Error general if end point is stalled |
|
1111 iLastError = KErrGeneral; |
|
1112 } |
|
1113 else |
|
1114 { |
|
1115 // Trim aCount with iEp0MaxPacketSize per packet |
|
1116 if (aCount > iEp0MaxPacketSize) |
|
1117 { |
|
1118 aCount = iEp0MaxPacketSize; |
|
1119 } |
|
1120 |
|
1121 iEp0DataReceived += aCount; |
|
1122 |
|
1123 if (iEp0ClientId == NULL) |
|
1124 { |
|
1125 // it is us( not an app), who owns this transaction |
|
1126 switch( iConTransferMgr->PktParser().Request()) |
|
1127 { |
|
1128 #ifdef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST |
|
1129 case KUsbRequest_SetDescriptor: |
|
1130 { |
|
1131 memcpy(iEp0_RxCollectionBuf + iEp0DataReceived, iEp0_RxBuf, aCount); |
|
1132 |
|
1133 // Status will be sent in side this function |
|
1134 // if we had recieved enough bytes |
|
1135 ProceedSetDescriptor(); |
|
1136 } |
|
1137 break; |
|
1138 #endif |
|
1139 default: |
|
1140 { |
|
1141 iConTransferMgr->StallEndpoint(KEp0_In); |
|
1142 ResetEp0DataOutVars(); |
|
1143 |
|
1144 // set err code to Error general if end point is stalled |
|
1145 iLastError = KErrGeneral; |
|
1146 } |
|
1147 break; |
|
1148 } |
|
1149 |
|
1150 if (iEp0DataReceived >= iConTransferMgr->PktParser().DataLength()) |
|
1151 { |
|
1152 // all data seems now to be here |
|
1153 ResetEp0DataOutVars(); |
|
1154 } |
|
1155 } |
|
1156 else |
|
1157 { |
|
1158 // it is an application who is requesting this data |
|
1159 // pass the data on to a client |
|
1160 |
|
1161 // it is the client's responsibility of sending a status |
|
1162 // packet back to host to indicate the whole transfer is |
|
1163 // done |
|
1164 |
|
1165 // Find the client Request callback |
|
1166 TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks); |
|
1167 TUsbcRequestCallback* p; |
|
1168 while ((p = iter++) != NULL) |
|
1169 { |
|
1170 if (p->Owner() == iEp0ClientId) |
|
1171 { |
|
1172 memcpy(p->iBufferStart, iEp0_RxBuf, aCount); |
|
1173 p->iError = KErrNone; |
|
1174 *(p->iPacketSize) = aCount; |
|
1175 p->iRxPackets = 1; |
|
1176 *(p->iPacketIndex) = 0; |
|
1177 break; |
|
1178 } |
|
1179 } |
|
1180 |
|
1181 // pass data to client if found one. |
|
1182 if ( p != NULL) |
|
1183 { |
|
1184 ProcessDataTransferDone(*p); |
|
1185 |
|
1186 if (iEp0DataReceived >= iConTransferMgr->PktParser().DataLength()) |
|
1187 { |
|
1188 // all data seems now to be here |
|
1189 ResetEp0DataOutVars(); |
|
1190 } |
|
1191 |
|
1192 iLastError = KErrNone; |
|
1193 |
|
1194 } |
|
1195 else |
|
1196 { |
|
1197 // that's bad, we found a client is request this data |
|
1198 // but no matching request callback found. |
|
1199 |
|
1200 iEp0_RxExtraCount = aCount; |
|
1201 //iEp0_RxExtraData = ETrue; |
|
1202 //iEp0_RxExtraError = aErrCode; |
|
1203 iEp0DataReceived -= aCount; |
|
1204 |
|
1205 // No status packet will be send to host since no client is reading this data, |
|
1206 // waiting client to send a status packet. |
|
1207 |
|
1208 iLastError = KErrNotFound; |
|
1209 } |
|
1210 } |
|
1211 } |
|
1212 } |
|
1213 |
|
1214 // Status Tx is done |
|
1215 void DUsbClientController::ProcessStatusInPacket(TInt aErrCode) |
|
1216 { |
|
1217 // Clear Error Code |
|
1218 iLastError = KErrNone; |
|
1219 |
|
1220 // it is time to start a new read |
|
1221 iEp0WritePending = EFalse; |
|
1222 } |
|
1223 |
|
1224 // |
|
1225 // Setup Rx is done |
|
1226 // |
|
1227 void DUsbClientController::ProcessSetupPacket(TInt aCount,TInt aErrCode) |
|
1228 { |
|
1229 |
|
1230 if (aErrCode != KErrNone) |
|
1231 { |
|
1232 // something wrong in hardware, we can do nothing as remedy |
|
1233 // just stall the endpoint. |
|
1234 iConTransferMgr->StallEndpoint(KEp0_Out); |
|
1235 iConTransferMgr->SetupEndpointZeroRead(); |
|
1236 |
|
1237 // set err code to Error general if end point is stalled |
|
1238 iLastError = KErrGeneral; |
|
1239 } |
|
1240 |
|
1241 TUsbcSetup packet; |
|
1242 Buffer2Setup(iEp0_RxBuf, packet); |
|
1243 |
|
1244 // Clear Error Code |
|
1245 iLastError = KErrNone; |
|
1246 |
|
1247 // If this is a standard request, we can handle it here |
|
1248 // not need to bother app layer |
|
1249 if ((packet.iRequestType & KUsbRequestType_TypeMask) == KUsbRequestType_TypeStd) |
|
1250 { |
|
1251 // Fixme: this may not needed any more |
|
1252 iEp0ReceivedNonStdRequest = EFalse; |
|
1253 ProcessStandardRequest(aCount,packet); |
|
1254 } |
|
1255 else |
|
1256 { |
|
1257 // Fixme: This may not needed anymore |
|
1258 iEp0ReceivedNonStdRequest = ETrue; |
|
1259 ProcessNonStandardRequest(aCount,packet); |
|
1260 } |
|
1261 } |
|
1262 |
|
1263 #define USB_PROCESS_REQUEST(request,param) \ |
|
1264 do \ |
|
1265 { \ |
|
1266 Process ## request(param); \ |
|
1267 if (iLastError != KErrNone) \ |
|
1268 { \ |
|
1269 __KTRACE_OPT(KUSB, \ |
|
1270 Kern::Printf(" ProcessEp0SetupReceived: Stalling Ep0")); \ |
|
1271 iConTransferMgr->StallEndpoint(KEp0_In); \ |
|
1272 } \ |
|
1273 }while(0) |
|
1274 |
|
1275 |
|
1276 // |
|
1277 // Standard request |
|
1278 // Please note that:Macro USB_PROCESS_REQUEST(xxx) will stall endpoint |
|
1279 // if anything wrong during the process, in which case status packet is |
|
1280 // not needed. |
|
1281 // |
|
1282 void DUsbClientController::ProcessStandardRequest(TInt /*aCount*/,const TUsbcSetup& aPacket) |
|
1283 { |
|
1284 switch (aPacket.iRequest) |
|
1285 { |
|
1286 case KUsbRequest_GetStatus: |
|
1287 switch (aPacket.iRequestType & KUsbRequestType_DestMask) |
|
1288 { // Recipient |
|
1289 case KUsbRequestType_DestDevice: |
|
1290 USB_PROCESS_REQUEST(GetDeviceStatus,aPacket); |
|
1291 break; |
|
1292 |
|
1293 case KUsbRequestType_DestIfc: |
|
1294 USB_PROCESS_REQUEST(GetInterfaceStatus,aPacket); |
|
1295 break; |
|
1296 |
|
1297 case KUsbRequestType_DestEp: |
|
1298 USB_PROCESS_REQUEST(GetEndpointStatus,aPacket); |
|
1299 break; |
|
1300 |
|
1301 default: |
|
1302 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: GET STATUS - Other or Unknown recipient")); |
|
1303 __KTRACE_OPT(KPANIC, Kern::Printf(" -> DUsbClientController::ProcessEp0SetupReceived: " |
|
1304 "Stalling Ep0")); |
|
1305 iConTransferMgr->StallEndpoint(KEp0_In); |
|
1306 iLastError = KErrGeneral; |
|
1307 break; |
|
1308 } |
|
1309 break; |
|
1310 |
|
1311 case KUsbRequest_ClearFeature: |
|
1312 case KUsbRequest_SetFeature: |
|
1313 switch (aPacket.iRequestType & KUsbRequestType_DestMask) |
|
1314 { // Recipient |
|
1315 case KUsbRequestType_DestDevice: |
|
1316 USB_PROCESS_REQUEST(SetClearDevFeature,aPacket); |
|
1317 break; |
|
1318 case KUsbRequestType_DestIfc: |
|
1319 // will 100% stall endpoint |
|
1320 USB_PROCESS_REQUEST(SetClearIfcFeature,aPacket); |
|
1321 break; |
|
1322 case KUsbRequestType_DestEp: |
|
1323 USB_PROCESS_REQUEST(SetClearEpFeature,aPacket); |
|
1324 break; |
|
1325 default: |
|
1326 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: SET/CLEAR FEATURE - " |
|
1327 "Other or Unknown recipient")); |
|
1328 __KTRACE_OPT(KPANIC, Kern::Printf(" -> Stalling Ep0")); |
|
1329 iConTransferMgr->StallEndpoint(KEp0_In); |
|
1330 iLastError = KErrGeneral; |
|
1331 break; |
|
1332 } |
|
1333 break; |
|
1334 |
|
1335 case KUsbRequest_SetAddress: |
|
1336 USB_PROCESS_REQUEST(SetAddress,aPacket); |
|
1337 break; |
|
1338 |
|
1339 case KUsbRequest_GetDescriptor: |
|
1340 USB_PROCESS_REQUEST(GetDescriptor,aPacket); |
|
1341 break; |
|
1342 |
|
1343 case KUsbRequest_SetDescriptor: |
|
1344 USB_PROCESS_REQUEST(SetDescriptor,aPacket); |
|
1345 break; |
|
1346 |
|
1347 case KUsbRequest_GetConfig: |
|
1348 USB_PROCESS_REQUEST(GetConfiguration,aPacket); |
|
1349 break; |
|
1350 |
|
1351 case KUsbRequest_SetConfig: |
|
1352 USB_PROCESS_REQUEST(SetConfiguration,aPacket); |
|
1353 break; |
|
1354 |
|
1355 case KUsbRequest_GetInterface: |
|
1356 USB_PROCESS_REQUEST(GetInterface,aPacket); |
|
1357 break; |
|
1358 |
|
1359 case KUsbRequest_SetInterface: |
|
1360 USB_PROCESS_REQUEST(SetInterface,aPacket); |
|
1361 break; |
|
1362 |
|
1363 case KUsbRequest_SynchFrame: |
|
1364 USB_PROCESS_REQUEST(SynchFrame,aPacket); |
|
1365 break; |
|
1366 |
|
1367 default: |
|
1368 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Unknown/unsupported Std Setup Request")); |
|
1369 __KTRACE_OPT(KPANIC, Kern::Printf(" -> Stalling Ep0")); |
|
1370 iConTransferMgr->StallEndpoint(KEp0_In); |
|
1371 iLastError = KErrGeneral; |
|
1372 break; |
|
1373 } |
|
1374 } |
|
1375 |
|
1376 #undef USB_PROCESS_REQUEST |
|
1377 |
|
1378 // |
|
1379 // class- or vendor-specific request |
|
1380 // we dont send back any status to host in PIL for class- or vendor-specific request |
|
1381 // if no client is waiting, stall the endpoint |
|
1382 // if client is not ready, just record them and waiting for client to read them |
|
1383 // (and, send a status packet) |
|
1384 // |
|
1385 void DUsbClientController::ProcessNonStandardRequest(TInt aCount,const TUsbcSetup& aPacket) |
|
1386 { |
|
1387 // Find out which client can handle this request |
|
1388 const DBase* client = FindNonStandardRequestClient(aPacket.iRequestType & KUsbRequestType_DestMask,aPacket); |
|
1389 |
|
1390 // If client is valide |
|
1391 if (client != NULL) |
|
1392 { |
|
1393 // Try to relay aPacket to the real recipient |
|
1394 TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks); |
|
1395 TUsbcRequestCallback* p; |
|
1396 |
|
1397 // Find out the request callback with match the client |
|
1398 // returned from last FindNonStandardRequestClient(). |
|
1399 while ((p = iter++) != NULL) |
|
1400 { |
|
1401 if (p->Owner() == client) |
|
1402 { |
|
1403 __ASSERT_DEBUG((p->iEndpointNum == 0), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
|
1404 __ASSERT_DEBUG((p->iTransferDir == UsbShai::EControllerRead), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
|
1405 __KTRACE_OPT(KUSB, Kern::Printf(" Found Ep0 read request")); |
|
1406 if (aPacket.iLength != 0) |
|
1407 { |
|
1408 if ((aPacket.iRequestType & KUsbRequestType_DirMask) == KUsbRequestType_DirToDev) |
|
1409 { |
|
1410 // Data transfer & direction OUT => there'll be a DATA_OUT stage |
|
1411 __KTRACE_OPT(KUSB, Kern::Printf(" Next is DATA_OUT: setting up DataOutVars")); |
|
1412 SetEp0DataOutVars(client); |
|
1413 } |
|
1414 else if ((aPacket.iRequestType & KUsbRequestType_DirMask) == KUsbRequestType_DirToHost) |
|
1415 { |
|
1416 // For possible later use (ZLP). |
|
1417 iEp0_TxNonStdCount = aPacket.iLength; |
|
1418 } |
|
1419 } |
|
1420 |
|
1421 // Found the request callback, jump out now |
|
1422 break; |
|
1423 } |
|
1424 } |
|
1425 |
|
1426 // if a request callback matching the client is found, |
|
1427 // complete the request |
|
1428 if( p != NULL) |
|
1429 { |
|
1430 __KTRACE_OPT(KUSB, Kern::Printf(" Ep0 read request completed to client")); |
|
1431 memcpy(p->iBufferStart, iEp0_RxBuf, aCount); |
|
1432 p->iError = KErrNone; |
|
1433 *(p->iPacketSize) = aCount; |
|
1434 p->iRxPackets = 1; |
|
1435 *(p->iPacketIndex) = 0; |
|
1436 ProcessDataTransferDone(*p); |
|
1437 } |
|
1438 else |
|
1439 { |
|
1440 __KTRACE_OPT(KUSB, Kern::Printf(" Ep0 read request not found: setting RxExtra vars (Setup)")); |
|
1441 iEp0_RxExtraCount = aCount; |
|
1442 //iEp0_RxExtraData = ETrue; |
|
1443 //iEp0_RxExtraError = aErrCode; |
|
1444 iSetupPacketPending = ETrue; |
|
1445 |
|
1446 // For setup packet,a zero bytes status is always needed |
|
1447 iLastError = KErrNotFound; |
|
1448 } |
|
1449 } |
|
1450 else // if (client == NULL) |
|
1451 { |
|
1452 // Pil don't know how to deal with non-standard request, stall endpoint |
|
1453 __KTRACE_OPT(KPANIC, Kern::Printf(" Ep0 request error: Stalling Ep0")); |
|
1454 iConTransferMgr->StallEndpoint(KEp0_In); |
|
1455 iLastError = KErrGeneral; |
|
1456 } |
|
1457 } |
|
1458 |
|
1459 const DBase* DUsbClientController::FindNonStandardRequestClient(TUint8 aPacketTypeDestination,const TUsbcSetup& aPacket) |
|
1460 { |
|
1461 const DBase* client = NULL; |
|
1462 |
|
1463 switch (aPacketTypeDestination) |
|
1464 { // Recipient |
|
1465 case KUsbRequestType_DestDevice: |
|
1466 { |
|
1467 client = iEp0DeviceControl; |
|
1468 } |
|
1469 break; |
|
1470 |
|
1471 case KUsbRequestType_DestIfc: |
|
1472 { |
|
1473 //Add this mutex to protect the interface set data structure |
|
1474 if (NKern::CurrentContext() == EThread) |
|
1475 { |
|
1476 NKern::FMWait(&iMutex); |
|
1477 } |
|
1478 |
|
1479 if ( iDeviceState < UsbShai::EUsbPeripheralStateConfigured) |
|
1480 { |
|
1481 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
1482 } |
|
1483 else |
|
1484 { |
|
1485 const TUsbcInterfaceSet* const ifcset_ptr = |
|
1486 InterfaceNumber2InterfacePointer(aPacket.iIndex); |
|
1487 |
|
1488 //In some rare case, ifcset_ptr is not NULL but the ifcset_ptr->iInterfaces.Count() is 0, |
|
1489 //so panic will happen when excute the following line. so I add the conditon |
|
1490 //0 != ifcset_ptr->iInterfaces.Count() here. |
|
1491 if (ifcset_ptr && 0 != ifcset_ptr->iInterfaces.Count()) |
|
1492 { |
|
1493 if (ifcset_ptr->CurrentInterface()->iNoEp0Requests) |
|
1494 { |
|
1495 __KTRACE_OPT(KUSB, Kern::Printf(" Recipient says: NoEp0RequestsPlease")); |
|
1496 } |
|
1497 else |
|
1498 { |
|
1499 client = ifcset_ptr->iClientId; |
|
1500 } |
|
1501 } |
|
1502 else |
|
1503 { |
|
1504 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Interface 0x%02x does not exist", |
|
1505 aPacket.iIndex)); |
|
1506 } |
|
1507 } |
|
1508 |
|
1509 if (NKern::CurrentContext() == EThread) |
|
1510 { |
|
1511 NKern::FMSignal(&iMutex); |
|
1512 } |
|
1513 } |
|
1514 break; |
|
1515 |
|
1516 case KUsbRequestType_DestEp: |
|
1517 { |
|
1518 //Add this mutex to protect the interface set data structure |
|
1519 if (NKern::CurrentContext() == EThread) |
|
1520 { |
|
1521 NKern::FMWait(&iMutex); |
|
1522 } |
|
1523 if ( iDeviceState < UsbShai::EUsbPeripheralStateConfigured) |
|
1524 { |
|
1525 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
1526 } |
|
1527 else if (EndpointExists(aPacket.iIndex) == EFalse) |
|
1528 { |
|
1529 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint 0x%02x does not exist", |
|
1530 aPacket.iIndex)); |
|
1531 } |
|
1532 else |
|
1533 { |
|
1534 const TInt idx = EpAddr2Idx(aPacket.iIndex); |
|
1535 const TUsbcInterfaceSet* const ifcset_ptr = |
|
1536 iRealEndpoints[idx].iLEndpoint->iInterface->iInterfaceSet; |
|
1537 if (ifcset_ptr->CurrentInterface()->iNoEp0Requests) |
|
1538 { |
|
1539 __KTRACE_OPT(KUSB, Kern::Printf(" Recipient says: NoEp0RequestsPlease")); |
|
1540 } |
|
1541 else |
|
1542 { |
|
1543 client = ifcset_ptr->iClientId; |
|
1544 } |
|
1545 } |
|
1546 if (NKern::CurrentContext() == EThread) |
|
1547 { |
|
1548 NKern::FMSignal(&iMutex); |
|
1549 } |
|
1550 } |
|
1551 break; |
|
1552 |
|
1553 default: |
|
1554 { |
|
1555 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Other or Unknown recipient")); |
|
1556 break; |
|
1557 } |
|
1558 } |
|
1559 |
|
1560 return client; |
|
1561 } |
|
1562 |
|
1563 TInt DUsbClientController::ProcessSetupEndpointZeroRead() |
|
1564 { |
|
1565 __KTRACE_OPT(KPANIC, Kern::Printf("DUsbClientController:: Read EP0 Issued")); |
|
1566 return iController.SetupEndpointZeroRead(); |
|
1567 } |
|
1568 |
|
1569 TInt DUsbClientController::ProcessSetupEndpointZeroWrite(const TUint8* aBuffer, TInt aLength, TBool aZlpReqd) |
|
1570 { |
|
1571 __KTRACE_OPT(KPANIC, Kern::Printf("DUsbClientController:: Write EP0 Issued")); |
|
1572 return iController.SetupEndpointZeroWrite(aBuffer,aLength,aZlpReqd); |
|
1573 } |
|
1574 |
|
1575 TInt DUsbClientController::ProcessSendEp0ZeroByteStatusPacket() |
|
1576 { |
|
1577 __KTRACE_OPT(KPANIC, Kern::Printf("DUsbClientController:: Zero Status to EP0 Issued")); |
|
1578 return iController.SendEp0ZeroByteStatusPacket(); |
|
1579 } |
|
1580 |
|
1581 TInt DUsbClientController::ProcessStallEndpoint(TInt aRealEndpoint) |
|
1582 { |
|
1583 __KTRACE_OPT(KPANIC, Kern::Printf("DUsbClientController:: EP0(%d) Stall Issued",aRealEndpoint)); |
|
1584 return iController.StallEndpoint(aRealEndpoint); |
|
1585 } |
|
1586 |
|
1587 void DUsbClientController::ProcessEp0SetupPacketProceed() |
|
1588 { |
|
1589 __KTRACE_OPT(KPANIC, Kern::Printf("DUsbClientController:: Missed setup packet procced")); |
|
1590 iController.Ep0ReadSetupPktProceed(); |
|
1591 } |
|
1592 |
|
1593 void DUsbClientController::ProcessEp0DataPacketProceed() |
|
1594 { |
|
1595 __KTRACE_OPT(KPANIC, Kern::Printf("DUsbClientController:: Missed data packet procced")); |
|
1596 iController.Ep0ReadDataPktProceed(); |
|
1597 } |
|
1598 |
|
1599 // -eof- |