Update contrib.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
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.
25 #include <drivers/usbc.h>
28 //#define ENABLE_EXCESSIVE_DEBUG_OUTPUT
31 // The way functions are called after an request has been completed by the PSL:
35 // ------------------------------------------------
37 // ProcessEp0ReceiveDone ProcessEp0TransmitDone
39 // --------------------------------------- |
41 // ProcessEp0SetupReceived ProcessEp0DataReceived ProcessDataTransferDone
43 // --------------------- ---------------
45 // ProcessXXX ProcessDataTransferDone ProceedXXX ProcessDataTransferDone
47 // XXX = Specific_Request
51 // === USB Controller member function implementation - PSL API (protected) ========================
54 /** Used to synchronize the Ep0 state machine between the PSL and PIL.
55 Accepts a SETUP packet and returns the next Ep0 state.
57 @param aSetupBuf The SETUP packet just received by the PSL.
58 @return The next Ep0 state.
60 @publishedPartner @released
62 TUsbcEp0State DUsbClientController::EnquireEp0NextState(const TUint8* aSetupBuf) const
64 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnquireEp0NextState()"));
66 // This function may be called by the PSL from within an ISR -- so we have
67 // to take care what we do here (and also in all functions that get called
70 if (SWAP_BYTES_16((reinterpret_cast<const TUint16*>(aSetupBuf)[3])) == 0) // iLength
72 __KTRACE_OPT(KUSB, Kern::Printf(" --> EEp0StateStatusIn"));
73 return EEp0StateStatusIn; // No-data Control => Status_IN
75 else if ((aSetupBuf[0] & KUsbRequestType_DirMask) == KUsbRequestType_DirToDev)
77 __KTRACE_OPT(KUSB, Kern::Printf(" --> EEp0StateDataOut"));
78 return EEp0StateDataOut; // Control Write => Data_OUT
82 __KTRACE_OPT(KUSB, Kern::Printf(" --> EEp0StateDataIn"));
83 return EEp0StateDataIn; // Control Read => Data_IN
88 TInt DUsbClientController::ProcessEp0ReceiveDone(TInt aCount)
90 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessEp0ReceiveDone()"));
92 if (iEp0DataReceiving == EFalse)
94 // It's obviously a Setup packet, so...
95 r = ProcessEp0SetupReceived(aCount);
99 // If it isn't a Setup, it must be data...
100 // (This is actually not quite true, as it could also be - in theory - a new Setup packet
101 // when the host has abandoned, for whatever reason, the previous one which was still
102 // in progress. However no such case is known to have occurred with this driver, or at
103 // least it didn't lead to problems.
104 // Some UDCs have a dedicated interrupt for Setup packets, but so far this driver hasn't
105 // made use of such a feature (as it would require a PSL/PIL API change).)
106 r = ProcessEp0DataReceived(aCount);
112 TInt DUsbClientController::ProcessEp0TransmitDone(TInt aCount, TInt aError)
114 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessEp0TransmitDone()"));
115 // In any case: there's now no longer a write pending
116 iEp0WritePending = EFalse;
117 // If it was a client who set up this transmission, we report to that client
118 if (iEp0ClientDataTransmitting)
120 iEp0ClientDataTransmitting = EFalse;
121 TUsbcRequestCallback* const p = iRequestCallbacks[KEp0_Tx];
124 __ASSERT_DEBUG((p->iTransferDir == EControllerWrite), Kern::Fault(KUsbPILPanicCat, __LINE__));
126 p->iTxBytes = aCount;
127 ProcessDataTransferDone(*p);
130 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: DUsbClientController::ProcessEpTransmitDone: Stalling Ep0"));
131 StallEndpoint(KEp0_In); // request not found
134 // If _we_ sent the data, we simply do nothing here...
139 #define USB_PROCESS_REQUEST(request) \
140 if (Process ## request(packet) != KErrNone) \
143 Kern::Printf(" ProcessEp0SetupReceived: Stalling Ep0")); \
144 StallEndpoint(KEp0_In); \
147 TInt DUsbClientController::ProcessEp0SetupReceived(TInt aCount)
149 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessEp0SetupReceived()"));
151 if (aCount > iEp0MaxPacketSize)
153 // Fatal error: too much data!
154 aCount = iEp0MaxPacketSize;
157 // first we split the data into meaningful units:
159 Buffer2Setup(iEp0_RxBuf, packet);
161 #if defined(_DEBUG) && defined(ENABLE_EXCESSIVE_DEBUG_OUTPUT)
162 // let's see what we've got:
163 __KTRACE_OPT(KUSB, Kern::Printf(" bmRequestType = 0x%02x", packet.iRequestType));
164 if ((packet.iRequestType & KUsbRequestType_TypeMask) == KUsbRequestType_TypeStd)
166 switch (packet.iRequest)
168 case KUsbRequest_GetStatus:
169 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (GET_STATUS)",
170 KUsbRequest_GetStatus));
172 case KUsbRequest_ClearFeature:
173 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (CLEAR_FEATURE)",
174 KUsbRequest_ClearFeature));
176 case KUsbRequest_SetFeature:
177 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (SET_FEATURE)",
178 KUsbRequest_SetFeature));
180 case KUsbRequest_SetAddress:
181 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (SET_ADDRESS)",
182 KUsbRequest_SetAddress));
184 case KUsbRequest_GetDescriptor:
185 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (GET_DESCRIPTOR)",
186 KUsbRequest_GetDescriptor));
188 case KUsbRequest_SetDescriptor:
189 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (SET_DESCRIPTOR)",
190 KUsbRequest_SetDescriptor));
192 case KUsbRequest_GetConfig:
193 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (GET_CONFIGURATION)",
194 KUsbRequest_GetConfig));
196 case KUsbRequest_SetConfig:
197 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (SET_CONFIGURATION)",
198 KUsbRequest_SetConfig));
200 case KUsbRequest_GetInterface:
201 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (GET_INTERFACE)",
202 KUsbRequest_GetInterface));
204 case KUsbRequest_SetInterface:
205 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (SET_INTERFACE)",
206 KUsbRequest_SetInterface));
208 case KUsbRequest_SynchFrame:
209 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (SYNCH_FRAME)",
210 KUsbRequest_SynchFrame));
213 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: bRequest = 0x%02x (UNKNWON STANDARD REQUEST)",
220 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (NON-STANDARD REQUEST)",
223 __KTRACE_OPT(KUSB, Kern::Printf(" wValue = 0x%04x", packet.iValue));
224 __KTRACE_OPT(KUSB, Kern::Printf(" wIndex = 0x%04x", packet.iIndex));
225 __KTRACE_OPT(KUSB, Kern::Printf(" wLength = 0x%04x", packet.iLength));
226 #endif // defined(_DEBUG) && defined(ENABLE_EXCESSIVE_DEBUG_OUTPUT)
228 // now the actual analysis
229 if ((packet.iRequestType & KUsbRequestType_TypeMask) == KUsbRequestType_TypeStd)
231 iEp0ReceivedNonStdRequest = EFalse;
232 switch (packet.iRequest)
234 case KUsbRequest_GetStatus:
235 switch (packet.iRequestType & KUsbRequestType_DestMask)
237 case KUsbRequestType_DestDevice:
238 USB_PROCESS_REQUEST(GetDeviceStatus);
240 case KUsbRequestType_DestIfc:
241 USB_PROCESS_REQUEST(GetInterfaceStatus);
243 case KUsbRequestType_DestEp:
244 USB_PROCESS_REQUEST(GetEndpointStatus);
247 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: GET STATUS - Other or Unknown recipient"));
248 __KTRACE_OPT(KPANIC, Kern::Printf(" -> DUsbClientController::ProcessEp0SetupReceived: "
250 StallEndpoint(KEp0_In);
254 case KUsbRequest_ClearFeature:
255 case KUsbRequest_SetFeature:
256 switch (packet.iRequestType & KUsbRequestType_DestMask)
258 case KUsbRequestType_DestDevice:
259 USB_PROCESS_REQUEST(SetClearDevFeature);
261 case KUsbRequestType_DestIfc:
262 USB_PROCESS_REQUEST(SetClearIfcFeature);
264 case KUsbRequestType_DestEp:
265 USB_PROCESS_REQUEST(SetClearEpFeature);
268 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: SET/CLEAR FEATURE - "
269 "Other or Unknown recipient"));
270 __KTRACE_OPT(KPANIC, Kern::Printf(" -> Stalling Ep0"));
271 StallEndpoint(KEp0_In);
275 case KUsbRequest_SetAddress:
276 USB_PROCESS_REQUEST(SetAddress);
278 case KUsbRequest_GetDescriptor:
279 USB_PROCESS_REQUEST(GetDescriptor);
281 case KUsbRequest_SetDescriptor:
282 USB_PROCESS_REQUEST(SetDescriptor);
284 case KUsbRequest_GetConfig:
285 USB_PROCESS_REQUEST(GetConfiguration);
287 case KUsbRequest_SetConfig:
288 USB_PROCESS_REQUEST(SetConfiguration);
290 case KUsbRequest_GetInterface:
291 USB_PROCESS_REQUEST(GetInterface);
293 case KUsbRequest_SetInterface:
294 USB_PROCESS_REQUEST(SetInterface);
296 case KUsbRequest_SynchFrame:
297 USB_PROCESS_REQUEST(SynchFrame);
300 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Unknown/unsupported Std Setup Request"));
301 __KTRACE_OPT(KPANIC, Kern::Printf(" -> Stalling Ep0"));
302 StallEndpoint(KEp0_In);
308 // Type mask != KUsbRequestType_TypeStd => class- or vendor-specific request
309 iEp0ReceivedNonStdRequest = ETrue;
310 const DBase* client = NULL;
311 switch (packet.iRequestType & KUsbRequestType_DestMask)
313 case KUsbRequestType_DestDevice:
314 client = iEp0DeviceControl;
316 case KUsbRequestType_DestIfc:
317 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured)
319 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state"));
323 const TUsbcInterfaceSet* const ifcset_ptr =
324 InterfaceNumber2InterfacePointer(packet.iIndex);
327 if (ifcset_ptr->CurrentInterface()->iNoEp0Requests)
329 __KTRACE_OPT(KUSB, Kern::Printf(" Recipient says: NoEp0RequestsPlease"));
333 client = ifcset_ptr->iClientId;
338 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Interface 0x%02x does not exist",
343 case KUsbRequestType_DestEp:
344 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured)
346 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state"));
348 else if (EndpointExists(packet.iIndex) == EFalse)
350 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint 0x%02x does not exist",
355 const TInt idx = EpAddr2Idx(packet.iIndex);
356 const TUsbcInterfaceSet* const ifcset_ptr =
357 iRealEndpoints[idx].iLEndpoint->iInterface->iInterfaceSet;
358 if (ifcset_ptr->CurrentInterface()->iNoEp0Requests)
360 __KTRACE_OPT(KUSB, Kern::Printf(" Recipient says: NoEp0RequestsPlease"));
364 client = ifcset_ptr->iClientId;
369 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Other or Unknown recipient"));
374 // Try to relay packet to the appropriate recipient
375 TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks);
376 TUsbcRequestCallback* p;
377 while ((p = iter++) != NULL)
379 if (p->Owner() == client)
381 __ASSERT_DEBUG((p->iEndpointNum == 0), Kern::Fault(KUsbPILPanicCat, __LINE__));
382 __ASSERT_DEBUG((p->iTransferDir == EControllerRead), Kern::Fault(KUsbPILPanicCat, __LINE__));
383 __KTRACE_OPT(KUSB, Kern::Printf(" Found Ep0 read request"));
384 if (packet.iLength != 0)
386 if ((packet.iRequestType & KUsbRequestType_DirMask) == KUsbRequestType_DirToDev)
388 // Data transfer & direction OUT => there'll be a DATA_OUT stage
389 __KTRACE_OPT(KUSB, Kern::Printf(" Next is DATA_OUT: setting up DataOutVars"));
390 SetEp0DataOutVars(packet, client);
392 else if ((packet.iRequestType & KUsbRequestType_DirMask) == KUsbRequestType_DirToHost)
394 // For possible later use (ZLP).
395 iEp0_TxNonStdCount = packet.iLength;
398 memcpy(p->iBufferStart, iEp0_RxBuf, aCount);
399 p->iError = KErrNone; // if it wasn't 'KErrNone' we wouldn't be here
400 *(p->iPacketSize) = aCount;
402 *(p->iPacketIndex) = 0;
403 ProcessDataTransferDone(*p);
407 __KTRACE_OPT(KUSB, Kern::Printf(" Ep0 read request not found: setting RxExtra vars (Setup)"));
408 iEp0_RxExtraCount = aCount;
409 iEp0_RxExtraData = ETrue;
412 else // if (client == NULL)
414 __KTRACE_OPT(KPANIC, Kern::Printf(" Ep0 request error: Stalling Ep0"));
415 StallEndpoint(KEp0_In);
422 #undef USB_PROCESS_REQUEST
425 TInt DUsbClientController::ProcessEp0DataReceived(TInt aCount)
427 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessEp0DataReceived()"));
429 __KTRACE_OPT(KUSB, Kern::Printf(" : %d bytes", aCount));
431 if (aCount > iEp0MaxPacketSize)
433 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Too much data"));
434 aCount = iEp0MaxPacketSize;
436 iEp0DataReceived += aCount;
437 if (iEp0ClientId == NULL)
439 // it is us (not an app), who owns this transaction
440 switch (iSetup.iRequest)
442 #ifdef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST
443 case KUsbRequest_SetDescriptor:
444 memcpy(iEp0_RxCollectionBuf + iEp0DataReceived, iEp0_RxBuf, aCount);
445 ProceedSetDescriptor();
449 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: invalid request in iSetup"));
450 __KTRACE_OPT(KPANIC, Kern::Printf(" -> DUsbClientController::ProcessEp0DataReceived: Stalling Ep0"));
451 StallEndpoint(KEp0_In);
452 ResetEp0DataOutVars();
458 // pass the data on to a client
459 TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks);
460 TUsbcRequestCallback* p;
461 while ((p = iter++) != NULL)
463 if (p->Owner() == iEp0ClientId)
465 __ASSERT_DEBUG((p->iEndpointNum == 0), Kern::Fault(KUsbPILPanicCat, __LINE__));
466 __ASSERT_DEBUG((p->iTransferDir == EControllerRead), Kern::Fault(KUsbPILPanicCat, __LINE__));
467 __KTRACE_OPT(KUSB, Kern::Printf(" Found Ep0 read request"));
468 memcpy(p->iBufferStart, iEp0_RxBuf, aCount);
469 p->iError = KErrNone; // if it wasn't 'KErrNone' we wouldn't be here
470 *(p->iPacketSize) = aCount;
472 *(p->iPacketIndex) = 0;
473 ProcessDataTransferDone(*p);
477 __KTRACE_OPT(KUSB, Kern::Printf(" Ep0 read request not found: setting RxExtra vars (Data)"));
478 iEp0_RxExtraCount = aCount;
479 iEp0_RxExtraData = ETrue;
480 iEp0DataReceived -= aCount;
484 if (iEp0DataReceived >= iSetup.iLength)
486 // all data seems now to be here
487 ResetEp0DataOutVars();
493 // --- The USB Spec Chapter 9 Standard Endpoint Zero Device Requests ---
495 TInt DUsbClientController::ProcessGetDeviceStatus(const TUsbcSetup& aPacket)
497 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetDeviceStatus()"));
498 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateAddress)
500 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state"));
503 const TUint16 status = ((DeviceSelfPowered() ? KUsbDevStat_SelfPowered : 0) |
504 (iRmWakeupStatus_Enabled ? KUsbDevStat_RemoteWakeup : 0));
505 __KTRACE_OPT(KUSB, Kern::Printf(" Reporting device status: 0x%02x", status));
506 *reinterpret_cast<TUint16*>(iEp0_TxBuf) = SWAP_BYTES_16(status);
507 if (SetupEndpointZeroWrite(iEp0_TxBuf, sizeof(status)) == KErrNone)
509 iEp0WritePending = ETrue;
515 TInt DUsbClientController::ProcessGetInterfaceStatus(const TUsbcSetup& aPacket)
517 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetInterfaceStatus()"));
518 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured)
520 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state"));
523 if (InterfaceExists(aPacket.iIndex) == EFalse)
525 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Interface does not exist"));
528 const TUint16 status = 0x0000; // as of USB Spec 2.0
529 __KTRACE_OPT(KUSB, Kern::Printf(" Reporting interface status: 0x%02x", status));
530 *reinterpret_cast<TUint16*>(iEp0_TxBuf) = SWAP_BYTES_16(status);
531 if (SetupEndpointZeroWrite(iEp0_TxBuf, sizeof(status)) == KErrNone)
533 iEp0WritePending = ETrue;
539 TInt DUsbClientController::ProcessGetEndpointStatus(const TUsbcSetup& aPacket)
541 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetEndpointStatus()"));
542 if (iTrackDeviceState &&
543 ((iDeviceState < EUsbcDeviceStateAddress) ||
544 (iDeviceState == EUsbcDeviceStateAddress && (aPacket.iIndex & KUsbEpAddress_Portmask) != 0)))
546 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state"));
549 if (EndpointExists(aPacket.iIndex) == EFalse)
551 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint does not exist"));
554 const TInt ep = EpAddr2Idx(aPacket.iIndex);
555 const TUint16 status = (iRealEndpoints[ep].iHalt) ? KUsbEpStat_Halt : 0;
556 __KTRACE_OPT(KUSB, Kern::Printf(" Reporting endpoint status 0x%02x for real endpoint %d",
558 *reinterpret_cast<TUint16*>(iEp0_TxBuf) = SWAP_BYTES_16(status);
559 if (SetupEndpointZeroWrite(iEp0_TxBuf, 2) == KErrNone)
561 iEp0WritePending = ETrue;
567 TInt DUsbClientController::ProcessSetClearDevFeature(const TUsbcSetup& aPacket)
569 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetClearDevFeature()"));
570 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateDefault)
572 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state"));
578 if (aPacket.iRequest == KUsbRequest_SetFeature)
580 switch (aPacket.iValue)
582 case KUsbFeature_RemoteWakeup:
583 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateAddress)
585 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state"));
588 iRmWakeupStatus_Enabled = ETrue;
590 case KUsbFeature_TestMode:
593 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only supported in High-Speed mode"));
596 if (LowByte(aPacket.iIndex) != 0)
598 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Lower byte of wIndex must be zero"));
601 test_sel = HighByte(aPacket.iIndex);
602 if ((test_sel < KUsbTestSelector_Test_J) || (test_sel > KUsbTestSelector_Test_Force_Enable))
604 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid test selector: %d", test_sel));
608 case KUsbFeature_B_HnpEnable:
611 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only supported on a OTG device"));
614 if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp))
616 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only valid if OTG device supports HNP"));
619 iOtgFuncMap |= KUsbOtgAttr_B_HnpEnable;
622 case KUsbFeature_A_HnpSupport:
625 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only supported on a OTG device"));
628 if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp))
630 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only valid if OTG device supports HNP"));
633 iOtgFuncMap |= KUsbOtgAttr_A_HnpSupport;
636 case KUsbFeature_A_AltHnpSupport:
639 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only supported on a OTG device"));
642 if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp))
644 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only valid if OTG device supports HNP"));
647 iOtgFuncMap |= KUsbOtgAttr_A_AltHnpSupport;
651 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Unknown feature requested"));
655 else // KUsbRequest_ClearFeature
657 switch (aPacket.iValue)
659 case KUsbFeature_RemoteWakeup:
660 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateAddress)
662 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state"));
665 iRmWakeupStatus_Enabled = EFalse;
668 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Unknown feature requested"));
673 SendEp0ZeroByteStatusPacket(); // success: zero bytes data during status stage
675 // 9.4.9: "The transition to test mode of an upstream facing port must not happen until
676 // after the status stage of the request."
679 __KTRACE_OPT(KPANIC, Kern::Printf(" Entering HS Test Mode %d", test_sel));
680 EnterTestMode(test_sel);
687 TInt DUsbClientController::ProcessSetClearIfcFeature(const TUsbcSetup& aPacket)
689 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetClearIfcFeature()"));
690 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured)
692 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state"));
695 // No interface features defined in USB spec, thus
700 TInt DUsbClientController::ProcessSetClearEpFeature(const TUsbcSetup& aPacket)
702 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetClearEpFeature()"));
703 if (iTrackDeviceState &&
704 ((iDeviceState < EUsbcDeviceStateAddress) ||
705 (iDeviceState == EUsbcDeviceStateAddress && (aPacket.iIndex & KUsbEpAddress_Portmask) != 0)))
707 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state"));
710 if (aPacket.iValue != KUsbFeature_EndpointHalt)
712 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Unknown feature requested"));
715 if (EndpointExists(aPacket.iIndex) == EFalse)
717 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint does not exist"));
720 const TInt ep = EpAddr2Idx(aPacket.iIndex);
721 if (iRealEndpoints[ep].iLEndpoint->iInfo.iType == KUsbEpTypeControl ||
722 iRealEndpoints[ep].iLEndpoint->iInfo.iType == KUsbEpTypeIsochronous)
724 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint is Control or Isochronous"));
727 SetClearHaltFeature(ep, aPacket.iRequest);
728 SendEp0ZeroByteStatusPacket(); // success: zero bytes data during status stage
733 TInt DUsbClientController::ProcessSetAddress(const TUsbcSetup& aPacket)
735 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetAddress()"));
736 if (iTrackDeviceState && iDeviceState > EUsbcDeviceStateAddress)
738 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state"));
741 const TUint16 addr = aPacket.iValue;
744 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Bad address value: %d (>127)", addr));
749 // Enter Default state (from Default or Address)
750 NextDeviceState(EUsbcDeviceStateDefault);
752 __KTRACE_OPT(KUSB, Kern::Printf(" USB address: %d", addr));
753 // The spec says, under section 9.4.6:
754 // "Stages after the initial Setup packet assume the same device address as the Setup packet. The USB
755 // device does not change its device address until after the Status stage of this request is completed
756 // successfully. Note that this is a difference between this request and all other requests. For all other
757 // requests, the operation indicated must be completed before the Status stage."
758 // Therefore, here we first send the status packet and only then actually execute the request.
759 SendEp0ZeroByteStatusPacket();
760 SetDeviceAddress(addr);
765 TInt DUsbClientController::ProcessGetDescriptor(const TUsbcSetup& aPacket)
767 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetDescriptor()"));
768 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateDefault)
770 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state"));
774 // Make sure we assume the correct speed
775 __ASSERT_DEBUG((iHighSpeed == CurrentlyUsingHighSpeed()), Kern::Fault(KUsbPILPanicCat, __LINE__));
778 const TInt result = iDescriptors.FindDescriptor(HighByte(aPacket.iValue), // Type
779 LowByte(aPacket.iValue), // Index
780 aPacket.iIndex, // Language ID
783 if ((result != KErrNone) || (size == 0))
785 // This doesn't have to be an error - protocol-wise it's OK.
786 __KTRACE_OPT(KUSB, Kern::Printf(" Couldn't retrieve descriptor"));
790 __KTRACE_OPT(KUSB, Kern::Printf(" Descriptor found, size: %d (requested: %d)",
791 size, aPacket.iLength));
792 if (size > KUsbcBufSz_Ep0Tx)
794 // This should actually not be possible (i.e. we should never get here).
795 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Ep0_Tx buffer too small"));
797 if (size > aPacket.iLength)
799 // Send only as much data as requested by the host
800 size = aPacket.iLength;
803 #ifdef ENABLE_EXCESSIVE_DEBUG_OUTPUT
805 Kern::Printf(" Data: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x ...",
806 iEp0_TxBuf[0], iEp0_TxBuf[1], iEp0_TxBuf[2], iEp0_TxBuf[3],
807 iEp0_TxBuf[4], iEp0_TxBuf[5], iEp0_TxBuf[6], iEp0_TxBuf[7]));
809 // If we're about to send less bytes than expected by the host AND our number is a
810 // multiple of the packet size, in order to indicate the end of the control transfer,
811 // we must finally send a zero length data packet (ZLP):
812 const TBool zlp = ((size < aPacket.iLength) && (size % iEp0MaxPacketSize == 0));
813 if (SetupEndpointZeroWrite(iEp0_TxBuf, size, zlp) == KErrNone)
815 iEp0WritePending = ETrue;
822 TInt DUsbClientController::ProcessSetDescriptor(const TUsbcSetup& aPacket)
824 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetDescriptor()"));
825 #ifndef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST
828 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateAddress)
830 // Error: Invalid device state!
833 if (aPacket.iLength > KUsbcBufSz_Ep0Rx)
835 // Error: Our Rx buffer is too small! (Raise a defect to make it larger)
836 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Ep0_Rx buffer too small"));
839 SetEp0DataOutVars(aPacket);
840 SetupEndpointZeroRead();
846 TInt DUsbClientController::ProcessGetConfiguration(const TUsbcSetup& aPacket)
848 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetConfiguration()"));
849 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateAddress)
851 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state"));
854 if (iTrackDeviceState && iDeviceState == EUsbcDeviceStateAddress && iCurrentConfig != 0)
856 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: DeviceState Address && Config != 0"));
859 if (iTrackDeviceState && iDeviceState == EUsbcDeviceStateConfigured && iCurrentConfig == 0)
861 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: DeviceState Configured && Config == 0"));
864 if (aPacket.iLength != 1) // "unspecified behavior"
866 __KTRACE_OPT(KUSB, Kern::Printf(" Warning: wLength != 1 (= %d)", aPacket.iLength));
868 __KTRACE_OPT(KUSB, Kern::Printf(" Reporting configuration value %d", iCurrentConfig));
869 if (SetupEndpointZeroWrite(&iCurrentConfig, sizeof(iCurrentConfig)) == KErrNone)
871 iEp0WritePending = ETrue;
877 /** Changes the device's configuration value, including interface setup and/or
878 teardown and state change notification of higher-layer clients.
879 May also be called by the PSL in special cases - therefore publishedPartner.
881 @param aPacket The received Ep0 SET_CONFIGURATION setup request packet.
882 @return KErrGeneral in case of a protocol error, KErrNone otherwise.
884 @publishedPartner @released
886 TInt DUsbClientController::ProcessSetConfiguration(const TUsbcSetup& aPacket)
888 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetConfiguration()"));
890 // This function may be called by the PSL from within an ISR -- so we have
891 // to take care what we do here (and also in all functions that get called
894 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateAddress)
896 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state"));
899 const TUint16 value = aPacket.iValue;
900 if (value > 1) // we support only one configuration
902 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Configuration value too large: %d", value));
906 __KTRACE_OPT(KUSB, Kern::Printf(" Configuration value: %d", value));
907 ChangeConfiguration(value);
909 // In 9.4.5 under GET_STATUS we read, that after SET_CONFIGURATION the HALT feature
910 // for all endpoints is reset to zero.
912 (TAny) DoForEveryEndpointInUse(&DUsbClientController::ClearHaltFeature, num);
913 __KTRACE_OPT(KUSB, Kern::Printf(" Called ClearHaltFeature() for %d endpoints", num));
914 SendEp0ZeroByteStatusPacket(); // success: zero bytes data during status stage
919 TInt DUsbClientController::ProcessGetInterface(const TUsbcSetup& aPacket)
921 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetInterface()"));
922 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured)
924 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state"));
927 if (iCurrentConfig == 0)
929 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Device not configured"));
932 const TInt number = aPacket.iIndex;
933 if (!InterfaceExists(number))
935 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Bad interface index: %d", number));
938 // Send alternate setting code of iCurrentInterface of Interface(set) <number> of the current
939 // config (iCurrentConfig).
940 const TUint8 setting = InterfaceNumber2InterfacePointer(number)->iCurrentInterface;
941 __KTRACE_OPT(KUSB, Kern::Printf(" Reporting interface setting %d", setting));
942 if (SetupEndpointZeroWrite(&setting, 1) == KErrNone)
944 iEp0WritePending = ETrue;
950 TInt DUsbClientController::ProcessSetInterface(const TUsbcSetup& aPacket)
952 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetInterface()"));
953 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured)
955 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state"));
958 if (iCurrentConfig == 0)
960 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Device not configured"));
963 const TInt number = aPacket.iIndex;
964 if (!InterfaceExists(number))
966 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Bad interface index: %d", number));
969 const TInt setting = aPacket.iValue;
970 TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(number);
971 RPointerArray<TUsbcInterface>& ifcs = ifcset_ptr->iInterfaces;
972 if (setting >= ifcs.Count())
974 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Alt Setting >= bNumAltSettings: %d", setting));
977 __KTRACE_OPT(KUSB, Kern::Printf(" Interface setting:: %d", setting));
978 // Set iCurrentInterface of Interface(set) <number> of the current config
979 // (iCurrentConfig) to alternate setting <setting>.
980 ChangeInterface(ifcs[setting]);
981 // In 9.4.5 under GET_STATUS we read, that after SET_INTERFACE the HALT feature
982 // for all endpoints (of the now current interface setting) is reset to zero.
983 RPointerArray<TUsbcLogicalEndpoint>& eps = ifcset_ptr->CurrentInterface()->iEndpoints;
984 const TInt num_eps = eps.Count();
985 for (TInt i = 0; i < num_eps; i++)
987 const TInt ep_num = EpAddr2Idx(eps[i]->iPEndpoint->iEndpointAddr);
988 (TAny) ClearHaltFeature(ep_num);
990 SendEp0ZeroByteStatusPacket(); // success: zero bytes data during status stage
995 TInt DUsbClientController::ProcessSynchFrame(const TUsbcSetup& aPacket)
997 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSynchFrame()"));
998 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured)
1000 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state"));
1003 const TInt ep = aPacket.iIndex;
1004 if (EndpointExists(ep) == EFalse)
1006 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint does not exist"));
1009 if (iRealEndpoints[EpAddr2Idx(ep)].iLEndpoint->iInfo.iType != KUsbEpTypeIsochronous)
1011 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint is not isochronous"));
1014 // We always send 0:
1015 *reinterpret_cast<TUint16*>(iEp0_TxBuf) = 0x00;
1016 if (SetupEndpointZeroWrite(iEp0_TxBuf, 2) == KErrNone)
1018 iEp0WritePending = ETrue;
1024 #ifdef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST
1025 void DUsbClientController::ProceedSetDescriptor()
1027 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProceedSetDescriptor()"));
1028 // iEp0DataReceived already reflects the current buffer state
1029 if (iEp0DataReceived < iSetup.iLength)
1031 // Not yet all data received => proceed
1034 if (iEp0DataReceived > iSetup.iLength)
1036 // Error: more data received than expected
1037 // but we don't care...
1039 // at this point: iEp0DataReceived == iSetup.iLength
1040 const TUint8 type = HighByte(iSetup.iValue);
1041 if (type == KUsbDescType_String)
1043 // set/add new string descriptor
1047 // set/add new ordinary descriptor
1049 TUint8 index = LowByte(iSetup.iValue);
1050 TUint16 langid = iSetup.iIndex;
1051 TUint16 length_total = iSetup.iLength;
1056 // --- Secondary (Helper) Functions
1058 void DUsbClientController::SetClearHaltFeature(TInt aRealEndpoint, TUint8 aRequest)
1060 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetClearHaltFeature()"));
1061 if (aRequest == KUsbRequest_SetFeature)
1063 if (iRealEndpoints[aRealEndpoint].iHalt)
1065 // (This condition is not really an error)
1066 __KTRACE_OPT(KUSB, Kern::Printf(" Warning: HALT feature already set"));
1069 __KTRACE_OPT(KUSB, Kern::Printf(" setting HALT feature for real endpoint %d",
1071 StallEndpoint(aRealEndpoint);
1072 iRealEndpoints[aRealEndpoint].iHalt = ETrue;
1074 else // KUsbRequest_ClearFeature
1076 if (iRealEndpoints[aRealEndpoint].iHalt == EFalse)
1078 // In this case, before we return, the data toggles are reset to DATA0.
1079 __KTRACE_OPT(KUSB, Kern::Printf(" Warning: HALT feature already cleared"));
1080 ResetDataToggle(aRealEndpoint);
1083 __KTRACE_OPT(KUSB, Kern::Printf(" clearing HALT feature for real endpoint %d",
1085 ResetDataToggle(aRealEndpoint);
1086 ClearStallEndpoint(aRealEndpoint);
1087 iRealEndpoints[aRealEndpoint].iHalt = EFalse;
1089 EpStatusNotify(aRealEndpoint); // only called if actually something changed
1093 TInt DUsbClientController::ClearHaltFeature(TInt aRealEndpoint)
1095 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ClearHaltFeature()"));
1096 if (iRealEndpoints[aRealEndpoint].iHalt != EFalse)
1098 ClearStallEndpoint(aRealEndpoint);
1099 iRealEndpoints[aRealEndpoint].iHalt = EFalse;
1105 void DUsbClientController::ChangeConfiguration(TUint16 aValue)
1107 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ChangeConfiguration()"));
1108 // New configuration is the same as the old one: 0
1109 if (iCurrentConfig == 0 && aValue == 0)
1112 __KTRACE_OPT(KUSB, Kern::Printf(" Configuration: New == Old == 0 --> exiting"));
1115 // New configuration is the same as the old one (but not 0)
1116 if (iCurrentConfig == aValue)
1119 __KTRACE_OPT(KUSB, Kern::Printf(" Configuration: New == Old == %d --> exiting", aValue));
1122 // Device is already configured
1123 if (iCurrentConfig != 0)
1125 __KTRACE_OPT(KUSB, Kern::Printf(" Device was configured: %d", iCurrentConfig));
1126 // Tear down all interface(set)s of the old configuration
1127 RPointerArray<TUsbcInterfaceSet>& ifcsets = CurrentConfig()->iInterfaceSets;
1128 for (TInt i = 0; i < ifcsets.Count(); ++i)
1130 __KTRACE_OPT(KUSB, Kern::Printf(" Tearing down InterfaceSet %d", i));
1131 InterfaceSetTeardown(ifcsets[i]);
1134 // Enter Address state (from Configured)
1135 if (iDeviceState == EUsbcDeviceStateConfigured)
1136 NextDeviceState(EUsbcDeviceStateAddress);
1138 // Device gets a new configuration
1141 __KTRACE_OPT(KUSB, Kern::Printf(" Device gets new configuration..."));
1142 // Setup all alternate settings 0 of all interfaces
1143 // (Don't separate the next two lines of code.)
1144 iCurrentConfig = aValue;
1145 RPointerArray<TUsbcInterfaceSet>& ifcsets = CurrentConfig()->iInterfaceSets;
1146 const TInt n = ifcsets.Count();
1147 for (TInt i = 0; i < n; ++i)
1149 __KTRACE_OPT(KUSB, Kern::Printf(" Setting up InterfaceSet %d", i));
1150 InterfaceSetup(ifcsets[i]->iInterfaces[0]);
1152 // Enter Configured state (from Address or Configured)
1153 NextDeviceState(EUsbcDeviceStateConfigured);
1155 __KTRACE_OPT(KUSB, Kern::Printf(" New configuration: %d", iCurrentConfig));
1160 void DUsbClientController::InterfaceSetup(TUsbcInterface* aIfc)
1162 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::InterfaceSetup()"));
1163 const TInt num_eps = aIfc->iEndpoints.Count();
1164 for (TInt i = 0; i < num_eps; i++)
1166 // Prepare this endpoint for I/O
1167 TUsbcLogicalEndpoint* const ep = aIfc->iEndpoints[i];
1168 // (TUsbcLogicalEndpoint's FS/HS endpoint sizes and interval values got
1169 // adjusted in its constructor.)
1172 __KTRACE_OPT(KUSB, Kern::Printf(" Setting Ep info size to %d (HS)", ep->iEpSize_Hs));
1173 ep->iInfo.iSize = ep->iEpSize_Hs;
1177 __KTRACE_OPT(KUSB, Kern::Printf(" Setting Ep info size to %d (FS)", ep->iEpSize_Fs));
1178 ep->iInfo.iSize = ep->iEpSize_Fs;
1180 const TInt idx = EpAddr2Idx(ep->iPEndpoint->iEndpointAddr);
1181 if (ConfigureEndpoint(idx, ep->iInfo) != KErrNone)
1183 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint %d configuration failed", idx));
1186 // Should there be a problem with it then we could try resetting the ep
1187 // data toggle at this point (or before the Configure) as well.
1188 __KTRACE_OPT(KUSB, Kern::Printf(" Connecting real ep addr 0x%02x & logical ep #%d",
1189 ep->iPEndpoint->iEndpointAddr, ep->iLEndpointNum));
1190 ep->iPEndpoint->iLEndpoint = ep;
1192 aIfc->iInterfaceSet->iCurrentInterface = aIfc->iSettingCode;
1197 void DUsbClientController::InterfaceSetTeardown(TUsbcInterfaceSet* aIfcSet)
1199 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::InterfaceSetTeardown()"));
1200 if (aIfcSet->iInterfaces.Count() == 0)
1202 __KTRACE_OPT(KUSB, Kern::Printf(" No interfaces exist - returning"));
1205 RPointerArray<TUsbcLogicalEndpoint>& eps = aIfcSet->CurrentInterface()->iEndpoints;
1206 const TInt num_eps = eps.Count();
1207 for (TInt i = 0; i < num_eps; i++)
1209 TUsbcLogicalEndpoint* const ep = eps[i];
1210 const TInt idx = EpAddr2Idx(ep->iPEndpoint->iEndpointAddr);
1212 CancelTransferRequests(idx);
1214 if (!ep->iPEndpoint->iLEndpoint)
1216 __KTRACE_OPT(KUSB, Kern::Printf(" real ep %d not configured: skipping", idx));
1219 if (ResetDataToggle(idx) != KErrNone)
1221 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint %d data toggle reset failed", idx));
1223 if (DeConfigureEndpoint(idx) != KErrNone)
1225 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint %d de-configuration failed", idx));
1228 __KTRACE_OPT(KUSB, Kern::Printf(" disconnecting real ep & logical ep"));
1229 ep->iPEndpoint->iLEndpoint = NULL;
1231 if (aIfcSet->CurrentInterface() != 0)
1233 __KTRACE_OPT(KUSB, Kern::Printf(" Resetting alternate interface setting to 0"));
1234 aIfcSet->iCurrentInterface = 0;
1240 void DUsbClientController::ChangeInterface(TUsbcInterface* aIfc)
1242 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ChangeInterface()"));
1243 TUsbcInterfaceSet* ifcset = aIfc->iInterfaceSet;
1244 const TUint8 setting = aIfc->iSettingCode;
1245 if (ifcset->iCurrentInterface == setting)
1247 __KTRACE_OPT(KUSB, Kern::Printf(" New Ifc == old Ifc: nothing to do"));
1250 __KTRACE_OPT(KUSB, Kern::Printf(" Setting new interface setting #%d", setting));
1251 InterfaceSetTeardown(ifcset);
1252 InterfaceSetup(aIfc);
1253 StatusNotify(static_cast<TUsbcDeviceState>(KUsbAlternateSetting | setting), ifcset->iClientId);
1257 // aFunction gets called, successively, with the endpoint index of every ep in-use as its argument.
1258 // (BTW: The declaration "type (class::*name)(params)" makes <name> a "pointer to element function".)
1260 TInt DUsbClientController::DoForEveryEndpointInUse(TInt (DUsbClientController::*aFunction)(TInt), TInt& aCount)
1262 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DoForEveryEndpointInUse()"));
1264 TUsbcConfiguration* const config = CurrentConfig();
1267 __KTRACE_OPT(KUSB, Kern::Printf(" Device is not configured - returning"));
1270 RPointerArray<TUsbcInterfaceSet>& ifcsets = config->iInterfaceSets;
1271 const TInt num_ifcsets = ifcsets.Count();
1272 for (TInt i = 0; i < num_ifcsets; i++)
1274 RPointerArray<TUsbcLogicalEndpoint>& eps = ifcsets[i]->CurrentInterface()->iEndpoints;
1275 const TInt num_eps = eps.Count();
1276 for (TInt j = 0; j < num_eps; j++)
1278 const TInt ep_num = EpAddr2Idx(eps[j]->iPEndpoint->iEndpointAddr);
1279 const TInt result = (this->*aFunction)(ep_num);
1281 if (result != KErrNone)