First public contribution.
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/ps_usbc.cpp
15 // Platform independent layer (PIL) of the USB Device controller driver (PDD).
16 // Interface to the USB LDD.
25 #include <drivers/usbc.h>
29 TUsbcInterfaceSet and TUsbcInterface
30 ====================================
32 TUsbcInterfaceSet represents a 'USB Interface' and TUsbcInterface
33 represents an 'Alternate Setting of a USB Interface'.
35 Since every LDD governs exactly one interface, the above distinction is
36 made only within the USB implementation. At the LDD API, there is/are
37 simply one or more settings for this single interface, numbered from '0'
38 (the default) to 'n', and specified by the parameter 'TInt aInterfaceNum'.
40 Within the PDD implementation, for a TUsbcInterfaceSet number the parameter
41 'TInt aIfcSet' is used (local variable ifcset); for a TUsbcInterface number
42 the parameter 'TInt aIfc' is used (local variable ifc).
45 iConfigs[0] and CurrentConfig()
46 ===============================
48 One problem with this file is that it always uses iConfigs[0] and not
49 CurrentConfig(). This is mainly because the API to the LDD doesn't know
50 about the concept of multiple configurations, and thus always assumes one
51 single configuration (which is also always active: a further problem).
53 In the file chapter9.cpp this issue doesn't exist, since there we always
54 have to obey the USB protocol, and in this way will use the configuration
55 which is selected by the host (which will then again currently always be
59 iEp0ClientId and iEp0DataReceiving
60 ==================================
62 The purpose of these two members of class DUsbClientController is the
65 They are used only during Ep0 control transactions which have an OUT (Rx)
66 data stage. The special problem with these transactions is twofold. For one
67 thing we have to know that what we are receiving is data and not a Setup
68 packet. Furthermore we cannot deduce from the received data itself to whom
69 it is addressed (that's because of the shared nature of Ep0).
71 So in order to recognize data packets we use iEp0DataReceiving. This
72 variable is set to TRUE either 1) upon processing a standard request which
73 has a DATA_OUT phase (only SET_DESCRIPTOR), or 2) if we have identified a
74 class-specific request which has a DATA_OUT phase and we have also found
75 the recipient for that request.
77 In order to be able to tell whether received Ep0 data is to be processed by
78 the PIL or a LDD, we use iEp0ClientId. iEp0ClientId is usually NULL, which
79 means it is our data. However it is set to the client ID of an LDD in case
80 2) above. That way we can subsequently hand over received data to the
83 iEp0DataReceived tracks the amount of data already received - it is used to
84 determine the end of the DATA_OUT phase, irrespective of the owner of the
85 data. The total amount that is to be received can be obtained via
86 iSetup.iLength. (iSetup holds in that case the Setup packet of the current
89 iEp0ClientDataTransmitting is only set to TRUE if a client sets up an Ep0
90 write. After that transmission has completed we use this value to decide
91 whether we have to report the completion to a client or not. (If this
92 variable is FALSE, we did set up the write and thus no client notification
98 // === Global and Local Variables ==================================================================
101 GLDEF_D DUsbClientController* DUsbClientController::UsbClientController[] = {NULL, NULL};
103 static const TInt KUsbReconnectDelay = 500; // milliseconds
104 static const TInt KUsbCableStatusDelay = 500; // milliseconds
108 // === USB Controller member function implementations - LDD API (public) ===========================
112 /** The class destructor.
114 This rarely gets called, except, for example when something goes
115 wrong during construction.
117 It's not exported because it is virtual.
119 DUsbClientController::~DUsbClientController()
121 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::~DUsbClientController()"));
124 iPowerHandler->Remove();
125 delete iPowerHandler;
127 // ResetAndDestroy() will call for every array element the destructor of the pointed-to object,
128 // before deleting the element itself, and closing the array.
129 iConfigs.ResetAndDestroy();
130 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::~DUsbClientController(): Done."));
134 /** To be called by the OTG/Host stack in an OTG setup to disable USB device
137 The OTG stack calls this function when VBus is no longer valid, when the
138 B-device swaps out of peripheral mode, or when moving out of the
141 The Client stack will disable the D+ pull-up immediately when the function
144 During DisableClientStack() the Client stack will notify its registered
145 applications on the user-side (including the USB Manager) about a USB
146 device state change event, a transition to the "Undefined" state.
148 EXPORT_C void DUsbClientController::DisableClientStack()
150 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DisableClientStack()"));
153 __KTRACE_OPT(KUSB, Kern::Printf(" Already disabled - returning"));
156 iOtgClientConnect = EFalse;
157 TInt r = EvaluateOtgConnectFlags(); // will disconnect UDC
160 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: EvaluateOtgConnectFlags() failed: %d", r));
163 // Reset OTG features, leave attributes as is (just as in USB Reset case)
164 // (OTG spec 1.3 sections 6.5.x all say "... on a bus reset or at the end
165 // of a session." VBus drop is the end of a session.)
166 iOtgFuncMap &= KUsbOtgAttr_SrpSupp | KUsbOtgAttr_HnpSupp;
168 // Tear down the current configuration (if any)
169 ChangeConfiguration(0);
171 if (iDeviceState != EUsbcDeviceStateUndefined)
173 // Not being in state UNDEFINED implies that the cable is inserted.
174 if (iHardwareActivated)
176 NextDeviceState(EUsbcDeviceStatePowered);
178 // (If the hardware is NOT activated at this point, we can only be in
179 // state EUsbcDeviceStateAttached, so we don't have to move to it.)
181 DeActivateHardwareController(); // turn off UDC altogether
182 iStackIsActive = EFalse;
183 // Complete all pending requests, returning KErrDisconnected
184 RunClientCallbacks();
185 // Notify registered clients on the user side about a USB device state
186 // change event and a transition to the "Undefined" state.
187 NextDeviceState(EUsbcDeviceStateUndefined);
191 /** To be called by the OTG/Host stack in an OTG setup to enable USB device
194 Once called, the function will return quickly, but it will by then not
195 necessarily have enabled the D+ pull-up*. The Client stack can enable the D+
196 pull-up (via the transceiver) from that moment on and as long as the OTG
197 stack doesn't call DisableClientStack().
199 *) It will enable the D+ pull-up immediately if the user-side USB support
200 has already been loaded. This should always be the case when the OTG stack
201 is calling this function during the transition to the A_PERIPHERAL state,
202 i.e. when acting as an A-device.
204 EXPORT_C void DUsbClientController::EnableClientStack()
206 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnableClientStack()"));
209 __KTRACE_OPT(KUSB, Kern::Printf(" Already enabled - returning"));
212 iStackIsActive = ETrue;
213 // If the UDC is still off, we switch it on here.
214 TInt r = ActivateHardwareController();
217 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: ActivateHardwareController() failed: %d", r));
219 iOtgClientConnect = ETrue;
220 r = EvaluateOtgConnectFlags(); // may connect UDC
223 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: EvaluateOtgConnectFlags() failed: %d", r));
228 /** Called by LDD to see if controller is usable.
230 @return ETrue if controller is in normal state, EFalse if it is disabled.
232 EXPORT_C TBool DUsbClientController::IsActive()
234 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::IsActive()"));
235 return iStackIsActive;
239 /** Called by LDD to register client callbacks.
241 @return KErrNone if successful, KErrAlreadyExists callback exists.
243 EXPORT_C TInt DUsbClientController::RegisterClientCallback(TUsbcClientCallback& aCallback)
245 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterClientCallback()"));
246 if (iClientCallbacks.Elements() == KUsbcMaxListLength)
248 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Maximum list length reached: %d",
249 KUsbcMaxListLength));
252 TSglQueIter<TUsbcClientCallback> iter(iClientCallbacks);
253 TUsbcClientCallback* p;
254 while ((p = iter++) != NULL)
257 __KTRACE_OPT(KUSB, Kern::Printf(" Error: ClientCallback @ 0x%x already registered", &aCallback));
258 return KErrAlreadyExists;
260 iClientCallbacks.AddLast(aCallback);
265 /** Returns a pointer to the USB client controller object.
267 This function is static.
269 @param aUdc The number of the UDC (0..n) for which the pointer is to be returned.
271 @return A pointer to the USB client controller object.
273 EXPORT_C DUsbClientController* DUsbClientController::UsbcControllerPointer(TInt aUdc)
275 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::UsbcControllerPointer()"));
276 if (aUdc < 0 || aUdc > 1)
278 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: aUdc out of range (%d)", aUdc));
281 return UsbClientController[aUdc];
285 /** Fills the buffer passed in as an argument with endpoint capability information.
287 @see DUsbClientController::DeviceCaps()
288 @see TUsbcEndpointData
291 @param aClientId A pointer to the LDD making the enquiry.
292 @param aCapsBuf A reference to a descriptor buffer, which, on return, contains an array of
293 TUsbcEndpointData elements; there are TUsbDeviceCaps::iTotalEndpoints elements in the array;
294 call DeviceCaps() to get the number of elements required.
296 EXPORT_C void DUsbClientController::EndpointCaps(const DBase* aClientId, TDes8& aCapsBuf) const
298 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EndpointCaps()"));
299 // Here we do not simply call DUsbClientController::DeviceEndpointCaps(),
300 // because that function fills an array which comprises of _all_ endpoints,
301 // whereas this function omits ep0 and all unusable endpoints.
302 // Apart from that, we have to fill an array of TUsbcEndpointData, not TUsbcEndpointCaps.
303 TUsbcEndpointData data[KUsbcMaxEndpoints];
304 const TInt ifcset_num = ClientId2InterfaceNumber(aClientId);
305 for (TInt i = 2, j = 0; i < iDeviceTotalEndpoints; ++i)
307 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::Caps: RealEndpoint #%d", i));
308 if (iRealEndpoints[i].iCaps.iTypesAndDir != KUsbEpNotAvailable)
310 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::Caps: --> UsableEndpoint #%d", j));
311 data[j].iCaps = iRealEndpoints[i].iCaps;
314 // If this LDD doesn't own an interface, but the Ep points to one,
315 // then that must be the interface of a different LDD. Hence the Ep
316 // is not available for this LDD.
317 data[j].iInUse = (iRealEndpoints[i].iIfcNumber != NULL);
321 // If this LDD does already own an interface, and the Ep also points to one,
322 // then the Ep is not available for this LDD only if that interface is owned
323 // by a different LDD (i.e. if the interface number is different).
324 // Reason: Even though the endpoint might already be part of an interface setting,
325 // it is still available for a different alternate setting of the same interface.
326 data[j].iInUse = ((iRealEndpoints[i].iIfcNumber != NULL) &&
327 (*(iRealEndpoints[i].iIfcNumber) != ifcset_num));
332 // aCapsBuf resides in userland
333 TPtrC8 des((TUint8*)data, sizeof(data));
334 const TInt r = Kern::ThreadDesWrite((reinterpret_cast<const DLddUsbcChannel*>(aClientId))->Client(),
335 &aCapsBuf, des, 0, KChunkShiftBy0, NULL);
338 Kern::ThreadKill((reinterpret_cast<const DLddUsbcChannel*>(aClientId))->Client(),
339 EExitPanic, r, KUsbPILKillCat);
344 /** Fills the buffer passed in as an argument with device capability information.
347 @see TUsbDeviceCapsV01
349 @param aClientId A pointer to the LDD making the enquiry.
350 @param aCapsBuf A reference to a descriptor buffer which, on return, contains
351 a TUsbDeviceCaps structure.
353 EXPORT_C void DUsbClientController::DeviceCaps(const DBase* aClientId, TDes8& aCapsBuf) const
355 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeviceCaps()"));
357 caps().iTotalEndpoints = iDeviceUsableEndpoints; // not DeviceTotalEndpoints()!
358 caps().iConnect = SoftConnectCaps();
359 caps().iSelfPowered = iSelfPowered;
360 caps().iRemoteWakeup = iRemoteWakeup;
361 caps().iHighSpeed = DeviceHighSpeedCaps();
362 caps().iFeatureWord1 = CableDetectWithoutPowerCaps() ?
363 caps().iFeatureWord1 | KUsbDevCapsFeatureWord1_CableDetectWithoutPower :
364 caps().iFeatureWord1 & ~KUsbDevCapsFeatureWord1_CableDetectWithoutPower;
365 caps().iFeatureWord1 = DeviceResourceAllocV2Caps() ?
366 caps().iFeatureWord1 | KUsbDevCapsFeatureWord1_EndpointResourceAllocV2 :
367 caps().iFeatureWord1 & ~KUsbDevCapsFeatureWord1_EndpointResourceAllocV2;
368 caps().iReserved = 0;
370 // aCapsBuf resides in userland
371 const TInt r = Kern::ThreadDesWrite((reinterpret_cast<const DLddUsbcChannel*>(aClientId))->Client(),
372 &aCapsBuf, caps, 0, KChunkShiftBy0, NULL);
375 Kern::ThreadKill((reinterpret_cast<const DLddUsbcChannel*>(aClientId))->Client(),
376 EExitPanic, r, KUsbPILKillCat);
381 TUsbcEndpointInfoArray::TUsbcEndpointInfoArray(const TUsbcEndpointInfo* aData, TInt aDataSize)
383 iType = EUsbcEndpointInfo;
384 iData = (TUint8*) aData;
386 iDataSize = aDataSize;
388 iDataSize = sizeof(TUsbcEndpointInfo);
392 inline TUsbcEndpointInfo& TUsbcEndpointInfoArray::operator[](TInt aIndex) const
394 return *(TUsbcEndpointInfo*) &iData[aIndex * iDataSize];
398 EXPORT_C TInt DUsbClientController::SetInterface(const DBase* aClientId, DThread* aThread,
399 TInt aInterfaceNum, TUsbcClassInfo& aClass,
400 TDesC8* aString, TInt aTotalEndpointsUsed,
401 const TUsbcEndpointInfo aEndpointData[],
402 TInt (*aRealEpNumbers)[6], TUint32 aFeatureWord)
404 TUsbcEndpointInfoArray endpointData = TUsbcEndpointInfoArray(aEndpointData);
405 return SetInterface(aClientId, aThread, aInterfaceNum, aClass, aString, aTotalEndpointsUsed,
406 endpointData, (TInt*) aRealEpNumbers, aFeatureWord);
410 /** Creates a new USB interface (one setting), complete with endpoints, descriptors, etc.,
411 and chains it into the internal device configuration tree.
413 @param aClientId A pointer to the LDD owning the new interface.
414 @param aThread A pointer to the thread the owning LDD is running in.
415 @param aInterfaceNum The interface setting number of the new interface setting. This must be 0
416 if it is the first setting of the interface that gets created, or 1 more than the last setting
417 that was created for this interface.
418 @param aClass Contains information about the device class this interface might belong to.
419 @param aString A pointer to a string that is used for the string descriptor of this interface.
420 @param aTotalEndpointsUsed The number of endpoints used by this interface (and also the number of
421 elements of the following array).
422 @param aEndpointData An array with aTotalEndpointsUsed elements, containing information about the
423 endpoints of this interface.
425 @return KErrNotSupported if Control endpoints are requested by the LDD but aren't supported by the PIL,
426 KErrInUse if at least one requested endpoint is - temporarily or permanently - not available for use,
427 KErrNoMemory if (endpoint, interface, string) descriptor allocation fails, KErrGeneral if something else
428 goes wrong during endpoint or interface or descriptor creation, KErrNone if interface successfully set up.
430 EXPORT_C TInt DUsbClientController::SetInterface(const DBase* aClientId, DThread* aThread,
431 TInt aInterfaceNum, TUsbcClassInfo& aClass,
432 TDesC8* aString, TInt aTotalEndpointsUsed,
433 const TUsbcEndpointInfoArray aEndpointData,
434 TInt aRealEpNumbers[], TUint32 aFeatureWord)
436 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetInterface()"));
437 if (aInterfaceNum != 0)
439 __KTRACE_OPT(KUSB, Kern::Printf(" alternate interface setting request: #%d", aInterfaceNum));
441 #ifndef USB_SUPPORTS_CONTROLENDPOINTS
442 for (TInt i = 0; i < aTotalEndpointsUsed; ++i)
444 if (aEndpointData[i].iType == KUsbEpTypeControl)
446 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: control endpoints not supported"));
447 return KErrNotSupported;
451 // Check for endpoint availability & check those endpoint's capabilities
452 const TInt ifcset_num = ClientId2InterfaceNumber(aClientId);
453 // The passed-in ifcset_num may be -1 now, but that's intended.
454 if (!CheckEpAvailability(aTotalEndpointsUsed, aEndpointData, ifcset_num))
456 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: endpoints not (all) available"));
459 // Create & setup new interface
460 TUsbcInterface* ifc = CreateInterface(aClientId, aInterfaceNum, aFeatureWord);
463 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: ifc == NULL"));
466 // Create logical endpoints
467 TInt r = CreateEndpoints(ifc, aTotalEndpointsUsed, aEndpointData, aRealEpNumbers);
470 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: CreateEndpoints() != KErrNone"));
471 DeleteInterface(ifc->iInterfaceSet->iInterfaceNumber, aInterfaceNum);
474 // Create & setup interface, string, and endpoint descriptors
475 r = SetupIfcDescriptor(ifc, aClass, aThread, aString, aEndpointData);
484 /** Releases an existing USB interface (one setting), complete with endpoints, descriptors, etc.,
485 and removes it from the internal device configuration tree.
487 @param aClientId A pointer to the LDD owning the interface.
488 @param aInterfaceNum The setting number of the interface setting to be deleted. This must be
489 the highest numbered (or 'last') setting for this interface.
491 @return KErrNotFound if interface (not setting) for some reason cannot be found, KErrArgument if an
492 invalid interface setting number is specified (not existing or existing but too small), KErrNone if
493 interface successfully released or if this client doesn't own any interface.
495 EXPORT_C TInt DUsbClientController::ReleaseInterface(const DBase* aClientId, TInt aInterfaceNum)
497 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ReleaseInterface(..., %d)", aInterfaceNum));
498 const TInt ifcset = ClientId2InterfaceNumber(aClientId);
501 __KTRACE_OPT(KUSB, Kern::Printf(" interface not found")); // no error
504 TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
507 __KTRACE_OPT(KUSB, Kern::Printf(" Error: interface number %d doesn't exist", ifcset));
510 const TInt setting_count = ifcset_ptr->iInterfaces.Count();
511 if ((setting_count - 1) != aInterfaceNum)
514 Kern::Printf(" > Error: interface settings must be released in descending order:\n\r"
515 " %d setting(s) exist, #%d was requested to be released.\n\r"
516 " (#%d has to be released first)",
517 setting_count, aInterfaceNum, setting_count - 1));
520 // Tear down current setting (invalidate configured state)
521 __KTRACE_OPT(KUSB, Kern::Printf(" > tearing down InterfaceSet %d", ifcset));
522 // Cancel all transfers on the current setting of this interface and deconfigure all its endpoints.
523 InterfaceSetTeardown(ifcset_ptr);
524 // 'Setting 0' means: delete all existing settings.
525 if (aInterfaceNum == 0)
527 TInt m = ifcset_ptr->iInterfaces.Count();
531 // Ground the physical endpoints' logical_endpoint_pointers
532 const TInt n = ifcset_ptr->iInterfaces[m]->iEndpoints.Count();
533 for (TInt i = 0; i < n; ++i)
535 TUsbcPhysicalEndpoint* ptr = const_cast<TUsbcPhysicalEndpoint*>
536 (ifcset_ptr->iInterfaces[m]->iEndpoints[i]->iPEndpoint);
537 ptr->iLEndpoint = NULL;
539 // Delete the setting itself + its ifc & ep descriptors
540 DeleteInterface(ifcset, m);
541 iDescriptors.DeleteIfcDescriptor(ifcset, m);
546 // Ground the physical endpoints' logical_endpoint_pointers
547 const TInt n = ifcset_ptr->iInterfaces[aInterfaceNum]->iEndpoints.Count();
548 for (TInt i = 0; i < n; ++i)
550 TUsbcPhysicalEndpoint* ptr = const_cast<TUsbcPhysicalEndpoint*>
551 (ifcset_ptr->iInterfaces[aInterfaceNum]->iEndpoints[i]->iPEndpoint);
552 ptr->iLEndpoint = NULL;
554 // Delete the setting itself + its ifc & ep descriptors
555 DeleteInterface(ifcset, aInterfaceNum);
556 iDescriptors.DeleteIfcDescriptor(ifcset, aInterfaceNum);
558 // Delete the whole interface if all settings are gone
559 if (ifcset_ptr->iInterfaces.Count() == 0)
561 DeleteInterfaceSet(ifcset);
563 // We now no longer have a valid current configuration
565 if (iDeviceState == EUsbcDeviceStateConfigured)
567 NextDeviceState(EUsbcDeviceStateAddress);
569 // If it was the last interface(set)...
570 if (iConfigs[0]->iInterfaceSets.Count() == 0)
572 __KTRACE_OPT(KUSB, Kern::Printf(" No ifc left -> turning off UDC"));
573 // First disconnect the device from the bus
575 DeActivateHardwareController();
576 // (this also disables endpoint zero; we cannot have a USB device w/o interface, see 9.6.3)
582 /** Enforces a USB re-enumeration by disconnecting the UDC from the bus (if it is currently connected) and
585 This only works if the PSL supports it, i.e. if SoftConnectCaps() returns ETrue.
587 EXPORT_C TInt DUsbClientController::ReEnumerate()
589 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ReEnumerate()"));
590 // If, in an OTG setup, the client stack is disabled, there's no point in
591 // trying to reenumerate the device. In fact, we then don't even want to
592 // turn on the UDC via ActivateHardwareController().
595 __KTRACE_OPT(KUSB, Kern::Printf(" Client stack disabled -> returning here"));
598 // We probably don't check here whether SoftConnectCaps() is ETrue, and
599 // return if not, because we might still want to execute
600 // ActivateHardwareController(). UsbConnect() and UsbDisconnect() should be
601 // no-ops if not supported by the PSL.
602 if (iConfigs[0]->iInterfaceSets.Count() == 0)
604 __KTRACE_OPT(KUSB, Kern::Printf(" > No interface registered -> no need to re-enumerate"));
607 if (!iHardwareActivated)
609 // If the UDC is still off, we switch it on here.
610 const TInt r = ActivateHardwareController();
613 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: ActivateHardwareController() failed: %d", r));
616 // Finally connect the device to the bus
622 // Now we have to wait a certain amount of time, in order to give the host the opportunity
623 // to come to terms with the new situation.
624 // (The ETrue parameter makes the callback get called in DFC instead of in ISR context.)
625 iReconnectTimer.OneShot(KUsbReconnectDelay, ETrue);
631 /** Powers up the UDC if one or more interfaces exist.
633 @return KErrNone if UDC successfully powered up, KErrNotReady if no
634 interfaces have been registered yet, KErrHardwareNotAvailable if UDC
635 couldn't be activated.
637 EXPORT_C TInt DUsbClientController::PowerUpUdc()
639 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::PowerUpUdc()"));
640 // If, in an OTG setup, the client stack is disabled, we mustn't turn on
641 // the UDC via ActivateHardwareController() as that would already configure
645 __KTRACE_OPT(KUSB, Kern::Printf(" Client stack disabled -> returning here"));
648 if (iConfigs[0]->iInterfaceSets.Count() == 0)
650 __KTRACE_OPT(KUSB, Kern::Printf(" > No interface registered -> won't power up UDC"));
653 // If the UDC is still off, we switch it on here.
654 const TInt r = ActivateHardwareController();
657 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: ActivateHardwareController() failed: %d", r));
663 /** Connects the UDC to the bus.
665 This only works if the PSL supports it, i.e. if SoftConnectCaps() returns ETrue.
667 @return KErrNone if UDC successfully connected, KErrGeneral if there was an error.
669 EXPORT_C TInt DUsbClientController::UsbConnect()
671 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::UsbConnect()"));
672 #ifdef USB_OTG_CLIENT
673 iClientSupportReady = ETrue;
674 const TInt r = EvaluateOtgConnectFlags();
675 const TInt irq = NKern::DisableAllInterrupts();
676 if (iUsbResetDeferred) // implies (iOtgHnpHandledByHw == ETrue)
678 __KTRACE_OPT(KUSB, Kern::Printf(" Resetting USB Reset 'defer' flag"));
679 iUsbResetDeferred = EFalse;
680 (void) ProcessResetEvent(EFalse);
682 NKern::RestoreInterrupts(irq);
684 const TInt r = UdcConnect();
685 #endif // USB_OTG_CLIENT
690 /** Disconnects the UDC from the bus.
692 This only works if the PSL supports it, i.e. if SoftConnectCaps() returns ETrue.
694 @return KErrNone if UDC successfully disconnected, KErrGeneral if there was an error.
696 EXPORT_C TInt DUsbClientController::UsbDisconnect()
698 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::UsbDisconnect()"));
699 #ifdef USB_OTG_CLIENT
700 iClientSupportReady = EFalse;
701 const TInt r = EvaluateOtgConnectFlags();
703 const TInt r = UdcDisconnect();
704 #endif // USB_OTG_CLIENT
705 // There won't be any notification by the PSL about this,
706 // so we have to notify the LDD/user ourselves:
707 if ((r == KErrNone) && (iDeviceState != EUsbcDeviceStateUndefined))
709 // Not being in state UNDEFINED implies that the cable is inserted.
710 if (iHardwareActivated)
712 NextDeviceState(EUsbcDeviceStatePowered);
714 // (If the hardware is NOT activated at this point, we can only be in
715 // state EUsbcDeviceStateAttached, so we don't have to move to it.)
721 /** Registers a notification callback for changes of the USB device state.
723 In the event of a device state change, the callback's state member gets updated (using SetState) with a
724 new TUsbcDeviceState value, and then the callback is executed (DoCallback). 'USB device state' here refers
725 to the Visible Device States as defined in chapter 9 of the USB specification.
727 @param aCallback A reference to a properly filled in status callback structure.
729 @return KErrNone if callback successfully registered, KErrGeneral if this callback is already registered
730 (it won't be registered twice).
732 EXPORT_C TInt DUsbClientController::RegisterForStatusChange(TUsbcStatusCallback& aCallback)
734 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterForStatusChange()"));
735 if (iStatusCallbacks.Elements() == KUsbcMaxListLength)
737 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Maximum list length reached: %d",
738 KUsbcMaxListLength));
741 if (IsInTheStatusList(aCallback))
743 __KTRACE_OPT(KUSB, Kern::Printf(" Error: StatusCallback @ 0x%x already registered", &aCallback));
746 const TInt irq = NKern::DisableAllInterrupts();
747 iStatusCallbacks.AddLast(aCallback);
748 NKern::RestoreInterrupts(irq);
753 /** De-registers (removes from the list of pending requests) a notification callback for the USB device
756 @param aClientId A pointer to the LDD owning the status change callback.
758 @return KErrNone if callback successfully unregistered, KErrNotFound if the callback couldn't be found.
760 EXPORT_C TInt DUsbClientController::DeRegisterForStatusChange(const DBase* aClientId)
762 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForStatusChange()"));
763 __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
764 const TInt irq = NKern::DisableAllInterrupts();
765 TSglQueIter<TUsbcStatusCallback> iter(iStatusCallbacks);
766 TUsbcStatusCallback* p;
767 while ((p = iter++) != NULL)
769 if (p->Owner() == aClientId)
771 __KTRACE_OPT(KUSB, Kern::Printf(" removing StatusCallback @ 0x%x", p));
772 iStatusCallbacks.Remove(*p);
773 NKern::RestoreInterrupts(irq);
777 __KTRACE_OPT(KUSB, Kern::Printf(" client not found"));
778 NKern::RestoreInterrupts(irq);
783 /** Registers a notification callback for changes of the state of endpoints.
785 In the event of a state change of an endpoint that is spart of an interface which is owned by the LDD
786 specified in the callback structure, the callback's state member gets updated (using SetState) with a new
787 value, and the callback is executed (DoCallback). 'Endpoint state' here refers to the state of the
788 ENDPOINT_HALT feature of an endpoint as described in chapter 9 of the USB specification. The contents of
789 the state variable reflects the state of the halt features for all endpoints of the current interface
790 setting: bit 0 represents endpoint 1, bit 1 endpoint 2, etc. A set bit means 'endpoint halted', a cleared
791 bit 'endpoint not halted'.
793 @param aCallback A reference to a properly filled in endpoint status callback structure.
795 @return KErrNone if callback successfully registered, KErrGeneral if this callback is already registered
796 (it won't be registered twice).
798 EXPORT_C TInt DUsbClientController::RegisterForEndpointStatusChange(TUsbcEndpointStatusCallback& aCallback)
800 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterForEndpointStatusChange()"));
801 if (iEpStatusCallbacks.Elements() == KUsbcMaxListLength)
803 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Maximum list length reached: %d",
804 KUsbcMaxListLength));
807 if (IsInTheEpStatusList(aCallback))
809 __KTRACE_OPT(KUSB, Kern::Printf(" Error: EpStatusCallback @ 0x%x already registered", &aCallback));
812 const TInt irq = NKern::DisableAllInterrupts();
813 iEpStatusCallbacks.AddLast(aCallback);
814 NKern::RestoreInterrupts(irq);
819 /** De-registers (removes from the list of pending requests) a notification callback for changes of the state
822 @param aClientId A pointer to the LDD owning the endpoint status change callback.
824 @return KErrNone if callback successfully unregistered, KErrNotFound if the callback couldn't be found.
826 EXPORT_C TInt DUsbClientController::DeRegisterForEndpointStatusChange(const DBase* aClientId)
828 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForEndpointStatusChange()"));
829 __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
830 const TInt irq = NKern::DisableAllInterrupts();
831 TSglQueIter<TUsbcEndpointStatusCallback> iter(iEpStatusCallbacks);
832 TUsbcEndpointStatusCallback* p;
833 while ((p = iter++) != NULL)
835 if (p->Owner() == aClientId)
837 __KTRACE_OPT(KUSB, Kern::Printf(" removing EpStatusCallback @ 0x%x", p));
838 iEpStatusCallbacks.Remove(*p);
839 NKern::RestoreInterrupts(irq);
843 __KTRACE_OPT(KUSB, Kern::Printf(" client not found"));
844 NKern::RestoreInterrupts(irq);
849 /** Returns the number of the currently active alternate interface setting for this interface.
851 @param aClientId A pointer to the LDD owning the interface.
852 @param aInterfaceNum Here the interface gets written to.
854 @return KErrNotFound if an interface for this client couldn't be found, KErrNone if setting value was
855 successfully written.
857 EXPORT_C TInt DUsbClientController::GetInterfaceNumber(const DBase* aClientId, TInt& aInterfaceNum) const
859 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetInterfaceNumber()"));
860 const TInt ifcset = ClientId2InterfaceNumber(aClientId);
863 __KTRACE_OPT(KPANIC, Kern::Printf(" Error (ifc < 0)"));
866 const TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
869 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: interface number %d doesn't exist", ifcset));
872 aInterfaceNum = ifcset_ptr->iCurrentInterface;
877 /** This is normally called once by an LDD's destructor, either after a Close() on the user side,
878 or during general cleanup.
880 It might also be called by the LDD when some internal unrecoverable error occurs.
883 - de-registers a possibly pending device state change notification request,
884 - de-registers a possibly pending endpoint state change notification request,
885 - releases all interfaces + settings owned by this LDD,
886 - cancels all remaining (if any) read/write requests.
888 @param aClientId A pointer to the LDD to be unregistered.
892 EXPORT_C TInt DUsbClientController::DeRegisterClient(const DBase* aClientId)
894 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterClient(0x%x)", aClientId));
895 // Cancel all device state notification requests
896 DeRegisterForStatusChange(aClientId);
897 // Cancel all endpoint state notification requests
898 DeRegisterForEndpointStatusChange(aClientId);
899 DeRegisterForOtgFeatureChange(aClientId);
900 DeRegisterClientCallback(aClientId);
901 // Delete the interface including all its alternate settings which might exist.
902 // (If we release the default setting (0), all alternate settings are deleted as well.)
903 const TInt r = ReleaseInterface(aClientId, 0);
904 // Cancel all remaining (if any) read/write requests
905 DeleteRequestCallbacks(aClientId);
906 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterClient: Done."));
911 /** Returns the currently used Ep0 max packet size.
913 @return The currently used Ep0 max packet size.
915 EXPORT_C TInt DUsbClientController::Ep0PacketSize() const
917 const TUsbcLogicalEndpoint* const ep = iRealEndpoints[0].iLEndpoint;
920 __KTRACE_OPT(KUSB, Kern::Printf(" Ep0 size = %d (HS)", ep->iEpSize_Hs));
921 return ep->iEpSize_Hs;
925 __KTRACE_OPT(KUSB, Kern::Printf(" Ep0 size = %d (FS)", ep->iEpSize_Fs));
926 return ep->iEpSize_Fs;
933 @param aClientId A pointer to the LDD wishing to stall Ep0 (this is for PIL internal purposes only).
935 @return KErrNone if endpoint zero successfully stalled, KErrGeneral otherwise.
937 EXPORT_C TInt DUsbClientController::Ep0Stall(const DBase* aClientId)
939 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::Ep0Stall()"));
940 if (aClientId == iEp0ClientId)
942 ResetEp0DataOutVars();
944 const TInt err = StallEndpoint(KEp0_Out);
950 return StallEndpoint(KEp0_In);
954 /** Sends a zero-byte status packet on Ep0.
956 @param aClientId A pointer to the LDD wishing to send the status packet (not used at present).
958 EXPORT_C void DUsbClientController::SendEp0StatusPacket(const DBase* /* aClientId */)
960 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SendEp0StatusPacket()"));
961 SendEp0ZeroByteStatusPacket();
965 /** Returns the current USB device state.
967 'USB device state' here refers to the Visible Device States as defined in chapter 9 of the USB
970 @return The current USB device state, or EUsbcDeviceStateUndefined if the UDC doesn't allow device state
971 tracking (PSL's DeviceStateChangeCaps() returns EFalse).
973 EXPORT_C TUsbcDeviceState DUsbClientController::GetDeviceStatus() const
975 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetDeviceStatus()"));
980 /** Returns the state of an endpoint.
982 'Endpoint state' here refers to the state of the ENDPOINT_HALT feature of
983 an endpoint as described in chapter 9 of the USB specification.
985 @param aClientId A pointer to the LDD owning the interface which contains the endpoint to be queried.
986 @param aEndpointNum The number of the endpoint to be queried.
988 @return The current endpoint state, or EEndpointStateUnknown if the endpoint couldn't be found.
990 EXPORT_C TEndpointState DUsbClientController::GetEndpointStatus(const DBase* aClientId, TInt aEndpointNum) const
992 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetEndpointStatus()"));
993 return EndpointStallStatus(aEndpointNum) ?
994 EEndpointStateStalled :
995 EEndpointStateNotStalled;
999 /** Sets up a data read request for an endpoint.
1001 @param aCallback A reference to a properly filled in data transfer request callback structure.
1003 @return KErrNone if callback successfully registered or if this callback is already registered
1004 (but it won't be registered twice), KErrNotFound if the endpoint couldn't be found, KErrArgument if
1005 endpoint number invalid (PSL), KErrGeneral if something else goes wrong.
1007 EXPORT_C TInt DUsbClientController::SetupReadBuffer(TUsbcRequestCallback& aCallback)
1009 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetupReadBuffer()"));
1010 const TInt ep = aCallback.iRealEpNum;
1011 __KTRACE_OPT(KUSB, Kern::Printf(" logical ep: #%d", aCallback.iEndpointNum));
1012 __KTRACE_OPT(KUSB, Kern::Printf(" real ep: #%d", ep));
1013 TInt err = KErrGeneral;
1016 if (iRequestCallbacks[ep])
1018 __KTRACE_OPT(KPANIC, Kern::Printf(" Warning: RequestCallback already registered for that ep"));
1019 if (iRequestCallbacks[ep] == &aCallback)
1021 __KTRACE_OPT(KPANIC, Kern::Printf(" (this same RequestCallback @ 0x%x)", &aCallback));
1025 __KTRACE_OPT(KPANIC, Kern::Printf(" (a different RequestCallback @ 0x%x)", &aCallback));
1029 // This may seem awkward:
1030 // First we add a callback, and then, in case of an error, we remove it again.
1031 // However this is necessary because the transfer request might complete (through
1032 // an ISR) _before_ the SetupEndpointRead function returns. Since we don't know the
1033 // outcome, we have to provide the callback before making the setup call.
1035 __KTRACE_OPT(KUSB, Kern::Printf(" adding RequestCallback[%d] @ 0x%x", ep, &aCallback));
1036 iRequestCallbacks[ep] = &aCallback;
1037 if ((err = SetupEndpointRead(ep, aCallback)) != KErrNone)
1039 __KTRACE_OPT(KPANIC, Kern::Printf(" removing RequestCallback @ 0x%x (due to error)",
1041 iRequestCallbacks[ep] = NULL;
1046 if (iEp0ReadRequestCallbacks.Elements() == KUsbcMaxListLength)
1048 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Maximum list length reached: %d",
1049 KUsbcMaxListLength));
1052 if (IsInTheRequestList(aCallback))
1054 __KTRACE_OPT(KUSB, Kern::Printf(" RequestCallback @ 0x%x already registered", &aCallback));
1057 // Ep0 reads don't need to be prepared - there's always one pending
1058 __KTRACE_OPT(KUSB, Kern::Printf(" adding RequestCallback @ 0x%x (ep0)", &aCallback));
1059 TInt irq = NKern::DisableAllInterrupts();
1060 iEp0ReadRequestCallbacks.AddLast(aCallback);
1061 NKern::RestoreInterrupts(irq);
1063 if (iEp0_RxExtraData)
1065 __KTRACE_OPT(KUSB, Kern::Printf(" iEp0_RxExtraData: trying again..."));
1066 const TBool rx_data = iEp0DataReceiving;
1067 const TInt irq = NKern::DisableAllInterrupts();
1068 err = ProcessEp0ReceiveDone(iEp0_RxExtraCount);
1069 NKern::RestoreInterrupts(irq);
1070 if (err == KErrNone)
1072 iEp0_RxExtraData = EFalse;
1073 // Queue a new Ep0 read (because xxxProceed only re-enables the interrupt)
1074 SetupEndpointZeroRead();
1077 Ep0ReceiveProceed();
1081 Ep0ReadSetupPktProceed();
1083 __KTRACE_OPT(KUSB, Kern::Printf(" :-)"));
1087 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: :-("));
1097 /** Sets up a data write request for an endpoint.
1099 @param aCallback A reference to a properly filled in data transfer request callback structure.
1101 @return KErrNone if callback successfully registered or if this callback is already registered
1102 (but it won't be registered twice), KErrNotFound if the endpoint couldn't be found, KErrArgument if
1103 endpoint number invalid (PSL), KErrGeneral if something else goes wrong.
1105 EXPORT_C TInt DUsbClientController::SetupWriteBuffer(TUsbcRequestCallback& aCallback)
1107 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetupWriteBuffer()"));
1108 TInt ep = aCallback.iRealEpNum;
1109 __KTRACE_OPT(KUSB, Kern::Printf(" logical ep: #%d", aCallback.iEndpointNum));
1110 __KTRACE_OPT(KUSB, Kern::Printf(" real ep: #%d", ep));
1111 if (iRequestCallbacks[ep])
1113 __KTRACE_OPT(KPANIC, Kern::Printf(" Warning: RequestCallback already registered for that ep"));
1114 if (iRequestCallbacks[ep] == &aCallback)
1116 __KTRACE_OPT(KPANIC, Kern::Printf(" (this same RequestCallback @ 0x%x)", &aCallback));
1121 __KTRACE_OPT(KPANIC, Kern::Printf(" (a different RequestCallback @ 0x%x - poss. error)",
1128 if (iEp0_TxNonStdCount)
1130 if (iEp0_TxNonStdCount > aCallback.iLength)
1132 __KTRACE_OPT(KPANIC, Kern::Printf(" Warning: Ep0 is sending less data than requested"));
1133 if ((aCallback.iLength % iEp0MaxPacketSize == 0) && !aCallback.iZlpReqd)
1135 __KTRACE_OPT(KPANIC, Kern::Printf(" Warning: Zlp should probably be requested"));
1138 else if (iEp0_TxNonStdCount < aCallback.iLength)
1140 __KTRACE_OPT(KPANIC, Kern::Printf(" Warning: Ep0 is sending more data than requested"));
1142 iEp0_TxNonStdCount = 0;
1144 // Ep0 IN needs to be adjusted: the LDD uses 0 for both Ep0 directions.
1147 // This may seem awkward:
1148 // First we add a callback, and then, in case of an error, we remove it again.
1149 // However this is necessary because the transfer request might complete (through
1150 // an ISR) _before_ the SetupEndpointWrite function returns. Since we don't know the
1151 // outcome, we have to provide the callback before making the setup call.
1153 __KTRACE_OPT(KUSB, Kern::Printf(" adding RequestCallback[%d] @ 0x%x", ep, &aCallback));
1154 iRequestCallbacks[ep] = &aCallback;
1157 iEp0ClientDataTransmitting = ETrue; // this must be set before calling SetupEndpointZeroWrite
1158 if (SetupEndpointZeroWrite(aCallback.iBufferStart, aCallback.iLength, aCallback.iZlpReqd) != KErrNone)
1160 __KTRACE_OPT(KPANIC, Kern::Printf(" removing RequestCallback @ 0x%x (due to error)", &aCallback));
1161 iRequestCallbacks[ep] = NULL;
1162 iEp0ClientDataTransmitting = EFalse;
1165 else if (SetupEndpointWrite(ep, aCallback) != KErrNone)
1167 __KTRACE_OPT(KPANIC, Kern::Printf(" removing RequestCallback @ 0x%x (due to error)", &aCallback));
1168 iRequestCallbacks[ep] = NULL;
1174 /** Cancels a data read request for an endpoint.
1176 The request callback will be removed from the queue and the
1177 callback function won't be executed.
1179 @param aClientId A pointer to the LDD owning the interface which contains the endpoint.
1180 @param aRealEndpoint The number of the endpoint for which the transfer request is to be cancelled.
1182 EXPORT_C void DUsbClientController::CancelReadBuffer(const DBase* aClientId, TInt aRealEndpoint)
1184 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CancelReadBuffer(%d)", aRealEndpoint));
1185 if (aRealEndpoint < 0)
1187 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: ep # < 0: %d", aRealEndpoint));
1190 // Note that we here don't cancel Ep0 read requests at the PSL level!
1191 if (aRealEndpoint > 0)
1193 CancelEndpointRead(aRealEndpoint);
1195 DeleteRequestCallback(aClientId, aRealEndpoint, EControllerRead);
1199 /** Cancels a data write request for an endpoint.
1201 It cannot be guaranteed that the data is not sent nonetheless, as some UDCs don't permit a flushing of a
1202 TX FIFO once it has been filled. The request callback will be removed from the queue in any case and the
1203 callback function won't be executed.
1205 @param aClientId A pointer to the LDD owning the interface which contains the endpoint.
1206 @param aRealEndpoint The number of the endpoint for which the transfer request is to be cancelled.
1208 EXPORT_C void DUsbClientController::CancelWriteBuffer(const DBase* aClientId, TInt aRealEndpoint)
1210 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CancelWriteBuffer(%d)", aRealEndpoint));
1211 if (aRealEndpoint < 0)
1213 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: ep # < 0: %d", aRealEndpoint));
1216 if (aRealEndpoint == 0)
1218 // Ep0 IN needs to be adjusted: the LDD uses 0 for both Ep0 directions.
1219 aRealEndpoint = KEp0_Tx;
1221 CancelEndpointWrite(aRealEndpoint);
1222 if (aRealEndpoint == KEp0_Tx)
1224 // Since Ep0 is shared among clients, we don't have to care about the client id.
1225 iEp0WritePending = EFalse;
1227 DeleteRequestCallback(aClientId, aRealEndpoint, EControllerWrite);
1231 /** Halts (stalls) an endpoint (but not Ep0).
1233 @param aClientId A pointer to the LDD owning the interface which contains the endpoint to be stalled.
1234 @param aEndpointNum The number of the endpoint.
1236 @return KErrNotFound if endpoint couldn't be found (includes Ep0), KErrNone if endpoint successfully
1237 stalled, KErrGeneral otherwise.
1239 EXPORT_C TInt DUsbClientController::HaltEndpoint(const DBase* aClientId, TInt aEndpointNum)
1241 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::HaltEndpoint(%d)", aEndpointNum));
1242 const TInt r = StallEndpoint(aEndpointNum);
1245 iRealEndpoints[aEndpointNum].iHalt = ETrue;
1247 else if (r == KErrArgument)
1249 return KErrNotFound;
1255 /** Clears the halt condition of an endpoint (but not Ep0).
1257 @param aClientId A pointer to the LDD owning the interface which contains the endpoint to be un-stalled.
1258 @param aEndpointNum The number of the endpoint.
1260 @return KErrNotFound if endpoint couldn't be found (includes Ep0), KErrNone if endpoint successfully
1261 stalled, KErrGeneral otherwise.
1263 EXPORT_C TInt DUsbClientController::ClearHaltEndpoint(const DBase* aClientId, TInt aEndpointNum)
1265 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ClearHaltEndpoint(%d)", aEndpointNum));
1266 const TInt r = ClearStallEndpoint(aEndpointNum);
1269 iRealEndpoints[aEndpointNum].iHalt = EFalse;
1271 else if (r == KErrArgument)
1273 return KErrNotFound;
1279 /** This function requests 'device control' for an LDD.
1281 Class or vendor specific Ep0 requests addressed to the USB device as a whole (Recipient field in
1282 bmRequestType byte of a Setup packet set to zero) are delivered to the LDD that owns device control. For
1283 obvious reasons only one USB LDD can have device control at any given time.
1285 @param aClientId A pointer to the LDD requesting device control.
1287 @return KErrNone if device control successfully claimed or if this LDD already owns it, KErrGeneral if
1288 device control already owned by a different client.
1290 EXPORT_C TInt DUsbClientController::SetDeviceControl(const DBase* aClientId)
1292 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetDeviceControl()"));
1293 if (iEp0DeviceControl)
1295 if (iEp0DeviceControl == aClientId)
1297 __KTRACE_OPT(KPANIC, Kern::Printf(" Warning: Device Control already owned by this client"));
1300 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Device Control already claimed by a different client"));
1303 iEp0DeviceControl = aClientId;
1308 /** This function releases device control for an LDD.
1310 @see DUsbClientController::SetDeviceControl()
1312 @param aClientId A pointer to the LDD releasing device control.
1314 @return KErrNone if device control successfully released, KErrGeneral if device control owned by a
1315 different client or by no client at all.
1317 EXPORT_C TInt DUsbClientController::ReleaseDeviceControl(const DBase* aClientId)
1319 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ReleaseDeviceControl()"));
1320 if (iEp0DeviceControl)
1322 if (iEp0DeviceControl == aClientId)
1324 __KTRACE_OPT(KUSB, Kern::Printf(" Releasing Device Control"));
1325 iEp0DeviceControl = NULL;
1328 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Device Control owned by a different client"));
1332 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Device Control not owned by any client"));
1338 /** Returns all available (configurable) max packet sizes for Ep0.
1340 The information is coded as bitwise OR'ed values of KUsbEpSizeXXX constants (the bitmap format used for
1341 TUsbcEndpointCaps.iSupportedSizes).
1343 @return All available (configurable) max packet sizes for Ep0.
1345 EXPORT_C TUint DUsbClientController::EndpointZeroMaxPacketSizes() const
1347 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EndpointZeroMaxPacketSizes()"));
1348 return iRealEndpoints[0].iCaps.iSizes;
1352 /** Sets (configures) the max packet size for Ep0.
1354 For available sizes as returned by DUsbClientController::EndpointZeroMaxPacketSizes()
1356 Note that for HS operation the Ep0 size cannot be chosen, but is fixed at 64 bytes.
1358 @return KErrNotSupported if invalid size specified, KErrNone if new max packet size successfully set or
1359 requested size was already set.
1361 EXPORT_C TInt DUsbClientController::SetEndpointZeroMaxPacketSize(TInt aMaxPacketSize)
1363 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetEndpointZeroMaxPacketSize(%d)",
1366 if (DeviceHighSpeedCaps())
1368 // We're not going to mess with this on a HS device.
1372 if (!(iRealEndpoints[0].iCaps.iSizes & PacketSize2Mask(aMaxPacketSize)))
1374 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: invalid size"));
1375 return KErrNotSupported;
1377 if (iRealEndpoints[0].iLEndpoint->iEpSize_Fs == aMaxPacketSize)
1379 __KTRACE_OPT(KUSB, Kern::Printf(" this packet size already set -> returning"));
1382 const TUsbcLogicalEndpoint* const ep0_0 = iRealEndpoints[0].iLEndpoint;
1383 const TUsbcLogicalEndpoint* const ep0_1 = iRealEndpoints[1].iLEndpoint;
1384 const_cast<TUsbcLogicalEndpoint*>(ep0_0)->iEpSize_Fs = aMaxPacketSize;
1385 const_cast<TUsbcLogicalEndpoint*>(ep0_1)->iEpSize_Fs = aMaxPacketSize;
1387 // @@@ We should probably modify the device descriptor here as well...
1389 if (iHardwareActivated)
1391 // De-configure endpoint zero
1392 DeConfigureEndpoint(KEp0_Out);
1393 DeConfigureEndpoint(KEp0_In);
1394 // Re-configure endpoint zero
1395 const_cast<TUsbcLogicalEndpoint*>(ep0_0)->iInfo.iSize = ep0_0->iEpSize_Fs;
1396 const_cast<TUsbcLogicalEndpoint*>(ep0_1)->iInfo.iSize = ep0_1->iEpSize_Fs;
1397 ConfigureEndpoint(0, ep0_0->iInfo);
1398 ConfigureEndpoint(1, ep0_1->iInfo);
1399 iEp0MaxPacketSize = ep0_0->iInfo.iSize;
1405 /** Returns the current USB Device descriptor.
1407 @param aThread A pointer to the thread the LDD requesting the descriptor is running in.
1408 @param aDeviceDescriptor A reference to a buffer into which the requested descriptor should be written
1409 (most likely located user-side).
1411 @return The return value of the thread write operation, Kern::ThreadWrite(), when writing to the target
1414 EXPORT_C TInt DUsbClientController::GetDeviceDescriptor(DThread* aThread, TDes8& aDeviceDescriptor)
1416 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetDeviceDescriptor()"));
1417 return iDescriptors.GetDeviceDescriptorTC(aThread, aDeviceDescriptor);
1421 /** Sets a new USB Device descriptor.
1423 @param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
1424 @param aDeviceDescriptor A reference to a buffer which contains the descriptor to be set (most likely
1427 @return The return value of the thread read operation, Kern::ThreadRead(), when reading from the source
1428 buffer in case of a failure, KErrNone if the new descriptor was successfully set.
1430 EXPORT_C TInt DUsbClientController::SetDeviceDescriptor(DThread* aThread, const TDes8& aDeviceDescriptor)
1432 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetDeviceDescriptor()"));
1433 return iDescriptors.SetDeviceDescriptorTC(aThread, aDeviceDescriptor);
1437 /** Returns the current USB Device descriptor size.
1439 @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
1440 @param aSize A reference to a buffer into which the requested descriptor size should be written
1441 (most likely located user-side).
1443 @return The return value of the thread write operation, Kern::ThreadWrite(), when writing to the target
1446 EXPORT_C TInt DUsbClientController::GetDeviceDescriptorSize(DThread* aThread, TDes8& aSize)
1448 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetDeviceDescriptorSize()"));
1449 // We do not really enquire here....
1450 const TPtrC8 size(reinterpret_cast<const TUint8*>(&KUsbDescSize_Device), sizeof(KUsbDescSize_Device));
1451 return Kern::ThreadDesWrite(aThread, &aSize, size, 0);
1455 /** Returns the current USB configuration descriptor.
1457 @param aThread A pointer to the thread the LDD requesting the descriptor is running in.
1458 @param aConfigurationDescriptor A reference to a buffer into which the requested descriptor should be
1459 written (most likely located user-side).
1461 @return The return value of the thread write operation, Kern::ThreadWrite(), when writing to the target
1464 EXPORT_C TInt DUsbClientController::GetConfigurationDescriptor(DThread* aThread, TDes8& aConfigurationDescriptor)
1466 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetConfigurationDescriptor()"));
1467 return iDescriptors.GetConfigurationDescriptorTC(aThread, aConfigurationDescriptor);
1471 /** Sets a new USB configuration descriptor.
1473 @param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
1474 @param aConfigurationDescriptor A reference to a buffer which contains the descriptor to be set (most
1475 likely located user-side).
1477 @return The return value of the thread read operation, Kern::ThreadRead() when reading from the source
1478 buffer in case of a failure, KErrNone if the new descriptor was successfully set.
1480 EXPORT_C TInt DUsbClientController::SetConfigurationDescriptor(DThread* aThread,
1481 const TDes8& aConfigurationDescriptor)
1483 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetConfigurationDescriptor()"));
1484 return iDescriptors.SetConfigurationDescriptorTC(aThread, aConfigurationDescriptor);
1488 /** Returns the current USB configuration descriptor size.
1490 @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
1491 @param aSize A reference to a buffer into which the requested descriptor size should be written
1492 (most likely located user-side).
1494 @return The return value of the thread write operation, Kern::ThreadWrite(), when writing to the target
1497 EXPORT_C TInt DUsbClientController::GetConfigurationDescriptorSize(DThread* aThread, TDes8& aSize)
1499 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetConfigurationDescriptorSize()"));
1500 // We do not really enquire here....
1501 const TPtrC8 size(reinterpret_cast<const TUint8*>(&KUsbDescSize_Config), sizeof(KUsbDescSize_Config));
1502 return Kern::ThreadDesWrite(aThread, &aSize, size, 0);
1506 /** Returns the current USB OTG descriptor.
1508 @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
1509 @param aOtgDesc A reference to a buffer into which the requested descriptor should be
1510 written (most likely located user-side).
1512 @return KErrNotSupported or the return value of the thread write operation, Kern::ThreadDesWrite(),
1513 when writing to the target buffer.
1515 EXPORT_C TInt DUsbClientController::GetOtgDescriptor(DThread* aThread, TDes8& aOtgDesc) const
1517 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetOtgDescriptor()"));
1520 return KErrNotSupported;
1522 return iDescriptors.GetOtgDescriptorTC(aThread, aOtgDesc);
1526 /** Sets a new OTG descriptor.
1528 @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
1529 @param aOtgDesc A reference to a buffer which contains new OTG descriptor.
1531 @return KErrNotSupported or the return value of the thread read operation, Kern::ThreadDesRead().
1533 EXPORT_C TInt DUsbClientController::SetOtgDescriptor(DThread* aThread, const TDesC8& aOtgDesc)
1535 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetOtgDescriptor()"));
1538 return KErrNotSupported;
1540 TBuf8<KUsbDescSize_Otg> otg;
1541 const TInt r = Kern::ThreadDesRead(aThread, &aOtgDesc, otg, 0);
1546 // Check descriptor validity
1547 if (otg[0] != KUsbDescSize_Otg || otg[1] != KUsbDescType_Otg || otg[2] > 3)
1549 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid OTG descriptor"));
1552 __KTRACE_OPT(KUSB, Kern::Printf(" iOtgFuncMap before: 0x%x", iOtgFuncMap));
1553 // Update value in controller as well
1554 const TUint8 hnp = otg[2] & KUsbOtgAttr_HnpSupp;
1555 const TUint8 srp = otg[2] & KUsbOtgAttr_SrpSupp;
1558 __KTRACE_OPT(KPANIC, Kern::Printf(" Warning: Invalid OTG attribute combination (HNP && !SRP"));
1560 if (hnp && !(iOtgFuncMap & KUsbOtgAttr_HnpSupp))
1562 __KTRACE_OPT(KUSB, Kern::Printf(" Setting attribute KUsbOtgAttr_HnpSupp"));
1563 iOtgFuncMap |= KUsbOtgAttr_HnpSupp;
1565 else if (!hnp && (iOtgFuncMap & KUsbOtgAttr_HnpSupp))
1567 __KTRACE_OPT(KUSB, Kern::Printf(" Removing attribute KUsbOtgAttr_HnpSupp"));
1568 iOtgFuncMap &= ~KUsbOtgAttr_HnpSupp;
1570 if (srp && !(iOtgFuncMap & KUsbOtgAttr_SrpSupp))
1572 __KTRACE_OPT(KUSB, Kern::Printf(" Setting attribute KUsbOtgAttr_SrpSupp"));
1573 iOtgFuncMap |= KUsbOtgAttr_SrpSupp;
1575 else if (!srp && (iOtgFuncMap & KUsbOtgAttr_SrpSupp))
1577 __KTRACE_OPT(KUSB, Kern::Printf(" Removing attribute KUsbOtgAttr_SrpSupp"));
1578 iOtgFuncMap &= ~KUsbOtgAttr_SrpSupp;
1580 __KTRACE_OPT(KUSB, Kern::Printf(" iOtgFuncMap after: 0x%x", iOtgFuncMap));
1581 return iDescriptors.SetOtgDescriptor(otg);
1585 /** Returns current OTG features of USB device.
1587 @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
1588 @param aFeatures A reference to a buffer into which the requested OTG features should be written.
1590 @return KErrNotSupported or the return value of the thread write operation, Kern::ThreadDesWrite().
1592 EXPORT_C TInt DUsbClientController::GetOtgFeatures(DThread* aThread, TDes8& aFeatures) const
1594 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetOtgFeatures()"));
1597 return KErrNotSupported;
1599 TBuf8<1> features(1);
1600 features[0] = iOtgFuncMap & 0x1C;
1601 return Kern::ThreadDesWrite(aThread, &aFeatures, features, 0);
1605 /** Returns current OTG features of USB device. This function is intended to be
1606 called only from kernel side.
1608 @param aFeatures The reference to which the current features should be set at.
1609 @return KErrNone if successful, KErrNotSupported if OTG is unavailable.
1611 EXPORT_C TInt DUsbClientController::GetCurrentOtgFeatures(TUint8& aFeatures) const
1613 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetCurrentOtgFeatures()"));
1616 return KErrNotSupported;
1618 aFeatures = iOtgFuncMap & 0x1C;
1623 /** Registers client request for OTG feature change. Client is notified when any OTG
1626 @see KUsbOtgAttr_B_HnpEnable, KUsbOtgAttr_A_HnpSupport, KUsbOtgAttr_A_AltHnpSupport
1628 @param aCallback Callback function. Gets called when OTG features change
1630 @return KErrNone if successful, KErrAlreadyExists if aCallback is already in the queue.
1632 EXPORT_C TInt DUsbClientController::RegisterForOtgFeatureChange(TUsbcOtgFeatureCallback& aCallback)
1634 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterForOtgFeatureChange()"));
1635 if (iOtgCallbacks.Elements() == KUsbcMaxListLength)
1637 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Maximum list length reached: %d",
1638 KUsbcMaxListLength));
1641 if (IsInTheOtgFeatureList(aCallback))
1643 __KTRACE_OPT(KUSB, Kern::Printf(" Error: OtgFeatureCallback @ 0x%x already registered", &aCallback));
1644 return KErrAlreadyExists;
1646 const TInt irq = NKern::DisableAllInterrupts();
1647 iOtgCallbacks.AddLast(aCallback);
1648 NKern::RestoreInterrupts(irq);
1653 /** De-registers (removes from the list of pending requests) a notification callback for
1656 @param aClientId A pointer to the LDD owning the endpoint status change callback.
1658 @return KErrNone if callback successfully unregistered, KErrNotFound if the callback couldn't be found.
1660 EXPORT_C TInt DUsbClientController::DeRegisterForOtgFeatureChange(const DBase* aClientId)
1662 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForOtgFeatureChange()"));
1663 __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
1664 const TInt irq = NKern::DisableAllInterrupts();
1665 TSglQueIter<TUsbcOtgFeatureCallback> iter(iOtgCallbacks);
1666 TUsbcOtgFeatureCallback* p;
1667 while ((p = iter++) != NULL)
1669 if (!aClientId || p->Owner() == aClientId)
1671 __KTRACE_OPT(KUSB, Kern::Printf(" removing OtgFeatureCallback @ 0x%x", p));
1672 iOtgCallbacks.Remove(*p);
1673 NKern::RestoreInterrupts(irq);
1677 __KTRACE_OPT(KUSB, Kern::Printf(" client not found"));
1678 NKern::RestoreInterrupts(irq);
1679 return KErrNotFound;
1683 /** Returns a specific standard USB interface descriptor.
1685 @param aThread A pointer to the thread the LDD requesting the descriptor is running in.
1686 @param aClientId A pointer to the LDD requesting the descriptor.
1687 @param aSettingNum The setting number of the interface for which the descriptor is requested.
1688 @param aInterfaceDescriptor A reference to a buffer into which the requested descriptor should be written
1689 (most likely located user-side).
1691 @return KErrNotFound if the specified interface couldn't be found, otherwise the return value of the thread
1692 write operation, Kern::ThreadWrite(), when writing to the target buffer.
1694 EXPORT_C TInt DUsbClientController::GetInterfaceDescriptor(DThread* aThread, const DBase* aClientId,
1695 TInt aSettingNum, TDes8& aInterfaceDescriptor)
1697 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetInterfaceDescriptor(x, 0x%08x, %d, y)",
1698 aClientId, aSettingNum));
1699 const TInt ifcset = ClientId2InterfaceNumber(aClientId);
1702 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Interface not found from client ID"));
1703 return KErrNotFound;
1705 return iDescriptors.GetInterfaceDescriptorTC(aThread, aInterfaceDescriptor, ifcset, aSettingNum);
1709 /** Sets a new standard USB interface descriptor.
1711 This function can also be used, by the user, and under certain conditions, to change an interface's number
1712 (reported as bInterfaceNumber in the descriptor). The conditions are: 1) We cannot accept a number that is
1713 already used by another interface, 2) We allow the interface number to be changed only when it's still the
1714 only setting, and 3) We allow the interface number to be changed only for the default setting (0). (All
1715 alternate settings created for that interface thereafter will inherit the new, changed number.)
1717 @param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
1718 @param aClientId A pointer to the LDD requesting the setting of the descriptor.
1719 @param aSettingNum The setting number of the interface for which the descriptor is to be set.
1720 @param aInterfaceDescriptor A reference to a buffer which contains the descriptor to be set (most
1721 likely located user-side).
1723 @return KErrNotFound if the specified interface couldn't be found, the return value of the thread read
1724 operation, Kern::ThreadRead(), when reading from the source buffer in case of a failure, KErrArgument if the
1725 interface number is to be changed (via bInterfaceNumber in the descriptor) and either the requested
1726 interface number is already used by another interface or the interface has more than one setting. KErrNone
1727 if the new descriptor was successfully set.
1729 EXPORT_C TInt DUsbClientController::SetInterfaceDescriptor(DThread* aThread, const DBase* aClientId,
1730 TInt aSettingNum, const TDes8& aInterfaceDescriptor)
1732 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetInterfaceDescriptor(x, 0x%08x, %d, y)",
1733 aClientId, aSettingNum));
1734 const TInt ifcset = ClientId2InterfaceNumber(aClientId);
1737 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Interface not found from client ID"));
1738 return KErrNotFound;
1740 TBuf8<KUsbDescSize_Interface> new_ifc;
1741 TInt r = Kern::ThreadDesRead(aThread, &aInterfaceDescriptor, new_ifc, 0);
1744 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Copying interface descriptor buffer failed (%d)", r));
1747 const TInt ifcset_new = new_ifc[2];
1748 const TBool ifc_num_changes = (ifcset != ifcset_new);
1749 TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
1752 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: interface number %d doesn't exist", ifcset));
1753 return KErrNotFound;
1755 if (ifc_num_changes)
1757 // If the user wants to change the interface number, we need to do some sanity checks:
1758 if (InterfaceExists(ifcset_new))
1760 // Obviously we cannot accept a number that is already used by another interface.
1761 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: interface number %d already in use", ifcset_new));
1762 return KErrArgument;
1764 if (ifcset_ptr->iInterfaces.Count() > 1)
1766 // We allow the interface number to be changed only when it's the only setting.
1767 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: interface has more than one alternate setting"));
1768 return KErrArgument;
1770 if (aSettingNum != 0)
1772 // We allow the interface number to be changed only when it's the default setting.
1773 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: interface number can only be changed for setting 0"));
1774 return KErrArgument;
1777 if ((r = iDescriptors.SetInterfaceDescriptor(new_ifc, ifcset, aSettingNum)) != KErrNone)
1779 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: iDescriptors.SetInterfaceDescriptorfailed"));
1782 if (ifc_num_changes)
1784 // Alright then, let's do it...
1785 __KTRACE_OPT(KUSB, Kern::Printf(" about to change interface number from %d to %d",
1786 ifcset, ifcset_new));
1787 ifcset_ptr->iInterfaceNumber = ifcset_new;
1793 /** Returns the size of a specific standard USB interface descriptor.
1795 @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
1796 @param aClientId A pointer to the LDD requesting the descriptor size.
1797 @param aSettingNum The setting number of the interface for which the descriptor size is requested.
1798 @param aSize A reference to a buffer into which the requested descriptor size should be written (most
1799 likely located user-side).
1801 @return KErrNotFound if the specified interface couldn't be found, otherwise the return value of the thread
1802 write operation, Kern::ThreadWrite(), when writing to the target buffer.
1804 EXPORT_C TInt DUsbClientController::GetInterfaceDescriptorSize(DThread* aThread, const DBase* aClientId,
1805 TInt /*aSettingNum*/, TDes8& aSize)
1807 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetInterfaceDescriptorSize()"));
1808 const TInt ifcset = ClientId2InterfaceNumber(aClientId);
1811 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Interface not found from client ID"));
1812 return KErrNotFound;
1814 // Actually, we do not really enquire here....
1815 const TPtrC8 size(reinterpret_cast<const TUint8*>(&KUsbDescSize_Interface), sizeof(KUsbDescSize_Interface));
1816 Kern::ThreadDesWrite(aThread, &aSize, size, 0);
1821 /** Returns a specific standard USB endpoint descriptor.
1823 @param aThread A pointer to the thread the LDD requesting the descriptor is running in.
1824 @param aClientId A pointer to the LDD requesting the descriptor.
1825 @param aSettingNum The setting number of the interface that contains the endpoint for which the
1826 descriptor is requested.
1827 @param aEndpointNum The endpoint for which the descriptor is requested.
1828 @param aEndpointDescriptor A reference to a buffer into which the requested descriptor should be written
1829 (most likely located user-side).
1831 @return KErrNotFound if the specified interface or endpoint couldn't be found, otherwise the return value
1832 of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
1834 EXPORT_C TInt DUsbClientController::GetEndpointDescriptor(DThread* aThread, const DBase* aClientId,
1835 TInt aSettingNum, TInt aEndpointNum,
1836 TDes8& aEndpointDescriptor)
1838 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetEndpointDescriptor(x, 0x%08x, %d, %d, y)",
1839 aClientId, aSettingNum, aEndpointNum));
1840 const TInt ifcset = ClientId2InterfaceNumber(aClientId);
1843 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Interface not found from client ID"));
1844 return KErrNotFound;
1846 return iDescriptors.GetEndpointDescriptorTC(aThread, aEndpointDescriptor, ifcset,
1847 aSettingNum, EpIdx2Addr(aEndpointNum));
1851 /** Sets a new standard USB endpoint descriptor.
1853 @param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
1854 @param aClientId A pointer to the LDD requesting the setting of the descriptor.
1855 @param aSettingNum The setting number of the interface that contains the endpoint for which the
1856 descriptor is to be set.
1857 @param aEndpointNum The endpoint for which the descriptor is to be set.
1858 @param aEndpointDescriptor A reference to a buffer which contains the descriptor to be set (most
1859 likely located user-side).
1861 @return KErrNotFound if the specified interface or endpoint couldn't be found, the return value of the
1862 thread read operation, Kern::ThreadRead(), when reading from the source buffer in case of a read failure,
1863 KErrNone if the new descriptor was successfully set.
1865 EXPORT_C TInt DUsbClientController::SetEndpointDescriptor(DThread* aThread, const DBase* aClientId,
1866 TInt aSettingNum, TInt aEndpointNum,
1867 const TDes8& aEndpointDescriptor)
1869 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetEndpointDescriptor(x, 0x%08x, %d, %d, y)",
1870 aClientId, aSettingNum, aEndpointNum));
1871 const TInt ifcset = ClientId2InterfaceNumber(aClientId);
1874 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Interface not found from client ID"));
1875 return KErrNotFound;
1877 return iDescriptors.SetEndpointDescriptorTC(aThread, aEndpointDescriptor, ifcset,
1878 aSettingNum, EpIdx2Addr(aEndpointNum));
1882 /** Returns the size of a specific standard USB endpoint descriptor.
1884 @param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
1885 @param aClientId A pointer to the LDD requesting the descriptor size.
1886 @param aSettingNum The setting number of the interface that contains the endpoint for which the
1887 descriptor size is requested.
1888 @param aEndpointNum The endpoint for which the descriptor size is requested.
1889 @param aEndpointDescriptor A reference to a buffer into which the requested descriptor size should be
1890 written (most likely located user-side).
1892 @return KErrNotFound if the specified interface or endpoint couldn't be found, otherwise the return value
1893 of the thread write operation, kern::ThreadWrite(), when writing to the target buffer.
1895 EXPORT_C TInt DUsbClientController::GetEndpointDescriptorSize(DThread* aThread, const DBase* aClientId,
1896 TInt aSettingNum, TInt aEndpointNum,
1899 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetEndpointDescriptorSize(x, 0x%08x, %d, %d, y)",
1900 aClientId, aSettingNum, aEndpointNum));
1901 const TInt ifcset = ClientId2InterfaceNumber(aClientId);
1904 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Interface not found from client ID"));
1905 return KErrNotFound;
1908 TInt r = iDescriptors.GetEndpointDescriptorSize(ifcset, aSettingNum,
1909 EpIdx2Addr(aEndpointNum), s);
1912 TPtrC8 size(reinterpret_cast<const TUint8*>(&s), sizeof(s));
1913 r = Kern::ThreadDesWrite(aThread, &aSize, size, 0);
1917 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: endpoint descriptor not found"));
1923 /** Returns the current Device_Qualifier descriptor. On a USB device which doesn't support high-speed
1924 operation this function will return an error. Note that the contents of the descriptor depend on
1925 the current device speed (full-speed or high-speed).
1927 @param aThread A pointer to the thread the LDD requesting the descriptor is running in.
1928 @param aDeviceQualifierDescriptor A reference to a buffer into which the requested descriptor
1929 should be written (most likely located user-side).
1931 @return KErrNotSupported if this descriptor is not supported, otherwise the return value of the thread
1932 write operation, Kern::ThreadWrite(), when writing to the target buffer.
1934 EXPORT_C TInt DUsbClientController::GetDeviceQualifierDescriptor(DThread* aThread,
1935 TDes8& aDeviceQualifierDescriptor)
1937 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetDeviceQualifierDescriptor()"));
1938 return iDescriptors.GetDeviceQualifierDescriptorTC(aThread, aDeviceQualifierDescriptor);
1942 /** Sets a new Device_Qualifier descriptor. On a USB device which doesn't support high-speed
1943 operation this function will return an error. Note that the contents of the descriptor should take
1944 into account the current device speed (full-speed or high-speed) as it is dependent on it.
1946 @param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
1947 @param aDeviceQualifierDescriptor A reference to a buffer which contains the descriptor to be set (most
1948 likely located user-side).
1950 @return KErrNotSupported if this descriptor is not supported, otherwise the return value of the thread
1951 read operation, Kern::ThreadRead(), when reading from the source buffer in case of a failure, KErrNone if
1952 the new descriptor was successfully set.
1954 EXPORT_C TInt DUsbClientController::SetDeviceQualifierDescriptor(DThread* aThread,
1955 const TDes8& aDeviceQualifierDescriptor)
1957 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetDeviceQualifierDescriptor()"));
1958 return iDescriptors.SetDeviceQualifierDescriptorTC(aThread, aDeviceQualifierDescriptor);
1962 /** Returns the current Other_Speed_Configuration descriptor. On a USB device which doesn't support high-speed
1963 operation this function will return an error. Note that the contents of the descriptor depend on the
1964 current device speed (full-speed or high-speed).
1966 @param aThread A pointer to the thread the LDD requesting the descriptor is running in.
1967 @param aConfigurationDescriptor A reference to a buffer into which the requested descriptor
1968 should be written (most likely located user-side).
1970 @return KErrNotSupported if this descriptor is not supported, otherwise the return value of the thread
1971 write operation, Kern::ThreadWrite(), when writing to the target buffer.
1973 EXPORT_C TInt DUsbClientController::GetOtherSpeedConfigurationDescriptor(DThread* aThread,
1974 TDes8& aConfigurationDescriptor)
1976 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetOtherSpeedConfigurationDescriptor()"));
1977 return iDescriptors.GetOtherSpeedConfigurationDescriptorTC(aThread, aConfigurationDescriptor);
1981 /** Sets a new Other_Speed_Configuration descriptor. On a USB device which doesn't support high-speed
1982 operation this function will return an error. Note that the contents of the descriptor should take
1983 into account the current device speed (full-speed or high-speed) as it is dependent on it.
1985 @param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
1986 @param aConfigurationDescriptor A reference to a buffer which contains the descriptor to be set (most
1987 likely located user-side).
1989 @return KErrNotSupported if this descriptor is not supported, otherwise the return value of the thread
1990 read operation, Kern::ThreadRead(), when reading from the source buffer in case of a failure, KErrNone if
1991 the new descriptor was successfully set.
1993 EXPORT_C TInt DUsbClientController::SetOtherSpeedConfigurationDescriptor(DThread* aThread,
1994 const TDes8& aConfigurationDescriptor)
1996 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetOtherSpeedConfigurationDescriptor()"));
1997 return iDescriptors.SetOtherSpeedConfigurationDescriptorTC(aThread, aConfigurationDescriptor);
2001 /** Returns a block of all available non-standard (class-specific) interface descriptors for a specific
2004 @param aThread A pointer to the thread the LDD requesting the descriptor block is running in.
2005 @param aClientId A pointer to the LDD requesting the descriptor block.
2006 @param aSettingNum The setting number of the interface for which the descriptor block is requested.
2007 @param aInterfaceDescriptor A reference to a buffer into which the requested descriptor(s) should be
2008 written (most likely located user-side).
2010 @return KErrNotFound if the specified interface couldn't be found, otherwise the return value of the thread
2011 write operation, Kern::ThreadWrite(), when writing to the target buffer.
2013 EXPORT_C TInt DUsbClientController::GetCSInterfaceDescriptorBlock(DThread* aThread, const DBase* aClientId,
2015 TDes8& aInterfaceDescriptor)
2017 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetCSInterfaceDescriptorBlock(x, 0x%08x, %d, y)",
2018 aClientId, aSettingNum));
2019 const TInt ifcset = ClientId2InterfaceNumber(aClientId);
2022 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Interface not found from client ID"));
2023 return KErrNotFound;
2025 return iDescriptors.GetCSInterfaceDescriptorTC(aThread, aInterfaceDescriptor, ifcset, aSettingNum);
2029 /** Sets a block of (i.e. one or more) non-standard (class-specific) interface descriptors for a specific
2032 @param aThread A pointer to the thread the LDD requesting the setting of the descriptor block is running
2034 @param aClientId A pointer to the LDD requesting the setting of the descriptor block.
2035 @param aSettingNum The setting number of the interface for which the setting of the descriptor block is
2037 @param aInterfaceDescriptor A reference to a buffer which contains the descriptor block to be set (most
2038 likely located user-side).
2039 @param aSize The size of the descriptor block to be set.
2041 @return KErrNotFound if the specified interface couldn't be found, KErrArgument if aSize is less than 2,
2042 KErrNoMemory if enough memory for the new descriptor(s) couldn't be allocated, otherwise the return value
2043 of the thread read operation, Kern::ThreadRead(), when reading from the source buffer.
2045 EXPORT_C TInt DUsbClientController::SetCSInterfaceDescriptorBlock(DThread* aThread, const DBase* aClientId,
2047 const TDes8& aInterfaceDescriptor, TInt aSize)
2050 Kern::Printf("DUsbClientController::SetCSInterfaceDescriptorBlock(x, 0x%08x, %d, y, %d)",
2051 aClientId, aSettingNum, aSize));
2052 const TInt ifcset = ClientId2InterfaceNumber(aClientId);
2055 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Interface not found from client ID"));
2056 return KErrNotFound;
2060 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: aSize < 2 (%d)", aSize));
2061 return KErrArgument;
2063 return iDescriptors.SetCSInterfaceDescriptorTC(aThread, aInterfaceDescriptor, ifcset, aSettingNum, aSize);
2067 /** Returns the total size all non-standard (class-specific) interface descriptors for a specific interface.
2069 @param aThread A pointer to the thread the LDD requesting the descriptor block size is running in.
2070 @param aClientId A pointer to the LDD requesting the descriptor block size.
2071 @param aSettingNum The setting number of the interface for which the descriptor block size is
2073 @param aSize A reference to a buffer into which the requested descriptor block size should be written (most
2074 likely located user-side).
2076 @return KErrNotFound if the specified interface couldn't be found, otherwise the return value of the thread
2077 write operation, Kern::ThreadWrite(), when writing to the target buffer.
2079 EXPORT_C TInt DUsbClientController::GetCSInterfaceDescriptorBlockSize(DThread* aThread, const DBase* aClientId,
2080 TInt aSettingNum, TDes8& aSize)
2083 Kern::Printf("DUsbClientController::GetCSInterfaceDescriptorBlockSize(x, 0x%08x, %d, y)",
2084 aClientId, aSettingNum));
2085 const TInt ifcset = ClientId2InterfaceNumber(aClientId);
2088 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Interface not found from client ID"));
2089 return KErrNotFound;
2092 const TInt r = iDescriptors.GetCSInterfaceDescriptorSize(ifcset, aSettingNum, s);
2095 const TPtrC8 size(reinterpret_cast<const TUint8*>(&s), sizeof(s));
2096 Kern::ThreadDesWrite(aThread, &aSize, size, 0);
2100 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: cs interface descriptor not found"));
2106 /** Returns a block of all available non-standard (class-specific) endpoint descriptors for a specific endpoint.
2108 @param aThread A pointer to the thread the LDD requesting the descriptor block is running in.
2109 @param aClientId A pointer to the LDD requesting the descriptor block.
2110 @param aSettingNum The setting number of the interface that contains the endpoint for which the
2111 descriptor block is requested.
2112 @param aEndpointNum The endpoint for which the descriptor block is requested.
2113 @param aEndpointDescriptor A reference to a buffer into which the requested descriptor(s) should be written
2114 (most likely located user-side).
2116 @return KErrNotFound if the specified interface or endpoint couldn't be found, otherwise the return value
2117 of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
2119 EXPORT_C TInt DUsbClientController::GetCSEndpointDescriptorBlock(DThread* aThread, const DBase* aClientId,
2120 TInt aSettingNum, TInt aEndpointNum,
2121 TDes8& aEndpointDescriptor)
2124 Kern::Printf("DUsbClientController::GetCSEndpointDescriptorBlock(x, 0x%08x, %d, %d, y)",
2125 aClientId, aSettingNum, aEndpointNum));
2126 const TInt ifcset = ClientId2InterfaceNumber(aClientId);
2129 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Interface not found from client ID"));
2130 return KErrNotFound;
2132 return iDescriptors.GetCSEndpointDescriptorTC(aThread, aEndpointDescriptor, ifcset,
2133 aSettingNum, EpIdx2Addr(aEndpointNum));
2137 /** Sets a block of (i.e. one or more) non-standard (class-specific) endpoint descriptors for a specific
2140 @param aThread A pointer to the thread the LDD requesting the setting of the descriptor block is running
2142 @param aClientId A pointer to the LDD requesting the setting of the descriptor block.
2143 @param aSettingNum The setting number of the interface that contains the endpoint for which the
2144 descriptor block is to be set.
2145 @param aEndpointNum The endpoint for which the descriptor block is to be set.
2146 @param aEndpointDescriptor A reference to a buffer which contains the descriptor block to be set (most
2147 likely located user-side).
2148 @param aSize The size of the descriptor block to be set.
2150 @return KErrNotFound if the specified interface or endpoint couldn't be found, KErrArgument if aSize is
2151 less than 2, KErrNoMemory if enough memory for the new descriptor(s) couldn't be allocated, otherwise the
2152 return value of the thread read operation, Kern::ThreadRead(), when reading from the source buffer.
2154 EXPORT_C TInt DUsbClientController::SetCSEndpointDescriptorBlock(DThread* aThread, const DBase* aClientId,
2155 TInt aSettingNum, TInt aEndpointNum,
2156 const TDes8& aEndpointDescriptor, TInt aSize)
2159 Kern::Printf("DUsbClientController::SetCSEndpointDescriptorBlock(x, 0x%08x, %d, %d, y)",
2160 aClientId, aSettingNum, aEndpointNum));
2161 const TInt ifcset = ClientId2InterfaceNumber(aClientId);
2164 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Interface not found from client ID"));
2165 return KErrNotFound;
2169 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: aSize < 2 (%d)", aSize));
2170 return KErrArgument;
2172 return iDescriptors.SetCSEndpointDescriptorTC(aThread, aEndpointDescriptor, ifcset,
2173 aSettingNum, EpIdx2Addr(aEndpointNum), aSize);
2177 /** Returns the total size all non-standard (class-specific) endpoint descriptors for a specific endpoint.
2179 @param aThread A pointer to the thread the LDD requesting the descriptor block size is running in.
2180 @param aClientId A pointer to the LDD requesting the descriptor block size.
2181 @param aSettingNum The setting number of the interface for which the descriptor block size is
2183 @param aEndpointNum The endpoint for which the descriptor block size is requested.
2184 @param aSize A reference to a buffer into which the requested descriptor block size should be written (most
2185 likely located user-side).
2187 @return KErrNotFound if the specified interface or endpoint couldn't be found, otherwise the return value
2188 of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
2190 EXPORT_C TInt DUsbClientController::GetCSEndpointDescriptorBlockSize(DThread* aThread, const DBase* aClientId,
2191 TInt aSettingNum, TInt aEndpointNum,
2195 Kern::Printf("DUsbClientController::GetCSEndpointDescriptorBlockSize(x, 0x%08x, %d, %d, y)",
2196 aClientId, aSettingNum, aEndpointNum));
2197 const TInt ifcset = ClientId2InterfaceNumber(aClientId);
2200 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Interface not found from client ID"));
2201 return KErrNotFound;
2204 const TInt r = iDescriptors.GetCSEndpointDescriptorSize(ifcset, aSettingNum,
2205 EpIdx2Addr(aEndpointNum), s);
2208 const TPtrC8 size(reinterpret_cast<const TUint8*>(&s), sizeof(s));
2209 Kern::ThreadDesWrite(aThread, &aSize, size, 0);
2213 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: cs endpoint descriptor not found"));
2219 /** Returns the currently set string descriptor language ID (LANGID) code.
2221 @param aThread A pointer to the thread the LDD requesting the LANGID is running in.
2222 @param aLangId A reference to a buffer into which the requested code should be written (most likely
2225 @return The return value of the thread write operation, Kern::ThreadDesWrite(),
2226 when writing to the target buffer.
2228 EXPORT_C TInt DUsbClientController::GetStringDescriptorLangId(DThread* aThread, TDes8& aLangId)
2230 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetStringDescriptorLangId()"));
2231 return iDescriptors.GetStringDescriptorLangIdTC(aThread, aLangId);
2235 /** Sets the string descriptor language ID (LANGID) code.
2237 @param aLangId The langauge ID code to be written.
2241 EXPORT_C TInt DUsbClientController::SetStringDescriptorLangId(TUint16 aLangId)
2243 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetStringDescriptorLangId()"));
2244 return iDescriptors.SetStringDescriptorLangId(aLangId);
2248 /** Returns the currently set Manufacturer string (which is referenced by the iManufacturer field in the device
2251 (Thus, the function should actually be called either 'GetManufacturerString'
2252 or 'GetManufacturerStringDescriptorString'.)
2254 @param aThread A pointer to the thread the LDD requesting the string is running in.
2255 @param aString A reference to a buffer into which the requested string should be written (most likely
2258 @return KErrNotFound if the string descriptor couldn't be found (PIL internal error), otherwise the return
2259 value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
2261 EXPORT_C TInt DUsbClientController::GetManufacturerStringDescriptor(DThread* aThread, TDes8& aString)
2263 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetManufacturerStringDescriptor()"));
2264 return iDescriptors.GetManufacturerStringDescriptorTC(aThread, aString);
2268 /** Sets a new Manufacturer string in the Manufacturer string descriptor (which is referenced by the
2269 iManufacturer field in the device descriptor).
2271 (Thus, the function should actually be called either
2272 'SetManufacturerString' or 'SetManufacturerStringDescriptorString'.)
2274 @param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
2275 @param aString A reference to a buffer which contains the string to be set (most likely located
2278 @return KErrNoMemory if not enough memory for the new descriptor or the string could be allocated, the
2279 return value of the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong,
2280 KErrNone if new string descriptor successfully set.
2282 EXPORT_C TInt DUsbClientController::SetManufacturerStringDescriptor(DThread* aThread, const TDes8& aString)
2284 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetManufacturerStringDescriptor()"));
2285 return iDescriptors.SetManufacturerStringDescriptorTC(aThread, aString);
2289 /** Removes (deletes) the Manufacturer string descriptor (which is referenced by the
2290 iManufacturer field in the device descriptor).
2292 @return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found
2294 EXPORT_C TInt DUsbClientController::RemoveManufacturerStringDescriptor()
2296 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveManufacturerStringDescriptor()"));
2297 return iDescriptors.RemoveManufacturerStringDescriptor();
2301 /** Returns the currently set Product string (which is referenced by the iProduct field in the device
2304 (Thus, the function should actually be called either 'GetProductString' or
2305 'GetProductStringDescriptorString'.)
2307 @param aThread A pointer to the thread the LDD requesting the string is running in.
2308 @param aString A reference to a buffer into which the requested string should be written (most likely
2311 @return KErrNotFound if the string descriptor couldn't be found (PIL internal error), otherwise the return
2312 value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
2314 EXPORT_C TInt DUsbClientController::GetProductStringDescriptor(DThread* aThread, TDes8& aString)
2316 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetProductStringDescriptor()"));
2317 return iDescriptors.GetProductStringDescriptorTC(aThread, aString);
2321 /** Sets a new Product string in the Product string descriptor (which is referenced by the iProduct field in
2322 the device descriptor).
2324 (Thus, the function should actually be called either 'SetProductString' or
2325 'SetProductStringDescriptorString'.)
2327 @param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
2328 @param aString A reference to a buffer which contains the string to be set (most likely located
2331 @return KErrNoMemory if not enough memory for the new descriptor or the string could be allocated, the
2332 return value of the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong,
2333 KErrNone if new string descriptor successfully set.
2335 EXPORT_C TInt DUsbClientController::SetProductStringDescriptor(DThread* aThread, const TDes8& aString)
2337 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetProductStringDescriptor()"));
2338 return iDescriptors.SetProductStringDescriptorTC(aThread, aString);
2342 /** Removes (deletes) the Product string descriptor (which is referenced by the
2343 iProduct field in the device descriptor).
2345 @return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found
2347 EXPORT_C TInt DUsbClientController::RemoveProductStringDescriptor()
2349 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveProductStringDescriptor()"));
2350 return iDescriptors.RemoveProductStringDescriptor();
2354 /** Returns the currently set SerialNumber string (which is referenced by the iSerialNumber field in the device
2357 (Thus, the function should actually be called either 'GetSerialNumberString' or
2358 'GetSerialNumberStringDescriptorString'.)
2360 @param aThread A pointer to the thread the LDD requesting the string is running in.
2361 @param aString A reference to a buffer into which the requested string should be written (most likely
2364 @return KErrNotFound if the string descriptor couldn't be found (PIL internal error), otherwise the return
2365 value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
2367 EXPORT_C TInt DUsbClientController::GetSerialNumberStringDescriptor(DThread* aThread, TDes8& aString)
2369 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetSerialNumberStringDescriptor()"));
2370 return iDescriptors.GetSerialNumberStringDescriptorTC(aThread, aString);
2374 /** Sets a new SerialNumber string in the SerialNumber string descriptor (which is referenced by the
2375 iSerialNumber field in the device descriptor).
2377 (Thus, the function should actually be called either
2378 'SetSerialNumberString' or 'SetSerialNumberStringDescriptorString'.)
2380 @param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
2381 @param aString A reference to a buffer which contains the string to be set (most likely located
2384 @return KErrNoMemory if not enough memory for the new descriptor or the string could be allocated, the
2385 return value of the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong,
2386 KErrNone if new string descriptor successfully set.
2388 EXPORT_C TInt DUsbClientController::SetSerialNumberStringDescriptor(DThread* aThread, const TDes8& aString)
2390 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetSerialNumberStringDescriptor()"));
2391 return iDescriptors.SetSerialNumberStringDescriptorTC(aThread, aString);
2395 /** Removes (deletes) the Serial Number string descriptor (which is referenced by the
2396 iSerialNumber field in the device descriptor).
2398 @return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found
2400 EXPORT_C TInt DUsbClientController::RemoveSerialNumberStringDescriptor()
2402 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveSerialNumberStringDescriptor()"));
2403 return iDescriptors.RemoveSerialNumberStringDescriptor();
2407 /** Returns the currently set Configuration string (which is referenced by the iConfiguration field in the
2408 configuration descriptor).
2410 (Thus, the function should actually be called either 'GetConfigurationString' or
2411 'GetConfigurationStringDescriptorString'.)
2413 @param aThread A pointer to the thread the LDD requesting the string is running in.
2414 @param aString A reference to a buffer into which the requested string should be written (most likely
2417 @return KErrNotFound if the string descriptor couldn't be found (PIL internal error), otherwise the return
2418 value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
2420 EXPORT_C TInt DUsbClientController::GetConfigurationStringDescriptor(DThread* aThread, TDes8& aString)
2422 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetConfigurationStringDescriptor()"));
2423 return iDescriptors.GetConfigurationStringDescriptorTC(aThread, aString);
2427 /** Sets a new Configuration string in the Configuration string descriptor (which is referenced by the
2428 iConfiguration field in the configuration descriptor).
2430 (Thus, the function should actually be called either
2431 'SetConfigurationString' or 'SetConfigurationStringDescriptorString'.)
2433 @param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
2434 @param aString A reference to a buffer which contains the string to be set (most likely located
2437 @return KErrNoMemory if not enough memory for the new descriptor or the string could be allocated, the
2438 return value of the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong,
2439 KErrNone if new string descriptor successfully set.
2441 EXPORT_C TInt DUsbClientController::SetConfigurationStringDescriptor(DThread* aThread, const TDes8& aString)
2443 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetConfigurationStringDescriptor()"));
2444 return iDescriptors.SetConfigurationStringDescriptorTC(aThread, aString);
2448 /** Removes (deletes) the Configuration string descriptor (which is referenced by the
2449 iConfiguration field in the configuration descriptor).
2451 @return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found.
2453 EXPORT_C TInt DUsbClientController::RemoveConfigurationStringDescriptor()
2455 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveConfigurationStringDescriptor()"));
2456 return iDescriptors.RemoveConfigurationStringDescriptor();
2460 /** Copies the string descriptor at the specified index in the string descriptor array into
2461 the aString argument.
2463 @param aIndex The position of the string descriptor in the string descriptor array.
2464 @param aThread A pointer to the thread the LDD requesting the string is running in.
2465 @param aString A reference to a buffer into which the requested string should be written (most likely
2468 @return KErrNone if successful, KErrNotFound if no string descriptor exists at the specified index, or the
2469 return value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
2471 EXPORT_C TInt DUsbClientController::GetStringDescriptor(DThread* aThread, TUint8 aIndex, TDes8& aString)
2473 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetStringDescriptor(%d)", aIndex));
2474 return iDescriptors.GetStringDescriptorTC(aThread, aIndex, aString);
2478 /** Sets the aString argument to be a string descriptor at the specified index in the string
2479 descriptor array. If a string descriptor already exists at that position then it will be replaced.
2481 @param aIndex The position of the string descriptor in the string descriptor array.
2482 @param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
2483 @param aString A reference to a buffer which contains the string to be set (most likely located
2486 @return KErrNone if successful, KErrArgument if aIndex is invalid, KErrNoMemory if no memory is available
2487 to store the new string (an existing descriptor at that index will be preserved), or the return value of
2488 the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong.
2490 EXPORT_C TInt DUsbClientController::SetStringDescriptor(DThread* aThread, TUint8 aIndex, const TDes8& aString)
2492 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetStringDescriptor(%d)", aIndex));
2493 return iDescriptors.SetStringDescriptorTC(aThread, aIndex, aString);
2497 /** Removes (deletes) the string descriptor at the specified index in the string descriptor array.
2499 @param aIndex The position of the string descriptor in the string descriptor array.
2501 @return KErrNone if successful, KErrNotFound if no string descriptor exists at the specified index.
2503 EXPORT_C TInt DUsbClientController::RemoveStringDescriptor(TUint8 aIndex)
2505 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveStringDescriptor(%d)", aIndex));
2506 return iDescriptors.RemoveStringDescriptor(aIndex);
2510 /** Allocates an endpoint resource.
2512 If the resource gets successfully allocated, it will be used from when the current bus transfer
2515 @param aClientId A pointer to the LDD requesting the endpoint resource.
2516 @param aEndpointNum The number of the endpoint.
2517 @param aResource The endpoint resource to be allocated.
2519 @return KErrNone if the resource has been successfully allocated, KErrNotSupported if the endpoint
2520 does not support the resource requested, and KErrInUse if the resource is already consumed and
2521 cannot be allocated. KErrArgument if the endpoint number is invalid.
2523 EXPORT_C TInt DUsbClientController::AllocateEndpointResource(const DBase* /*aClientId*/, TInt aEndpointNum,
2524 TUsbcEndpointResource aResource)
2526 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::AllocateEndpointResource()"));
2527 return AllocateEndpointResource(aEndpointNum, aResource);
2531 /** Deallocates (frees) an endpoint resource.
2533 The resource will be removed from when the current bus transfer has been completed.
2535 @param aClientId A pointer to the LDD requesting the freeing of the endpoint resource.
2536 @param aEndpointNum The number of the endpoint.
2537 @param aResource The endpoint resource to be deallocated.
2539 @return KErrNone if the resource has been successfully deallocated, KErrNotSupported if the endpoint
2540 does not support the resource requested. KErrArgument if the endpoint number is invalid.
2542 EXPORT_C TInt DUsbClientController::DeAllocateEndpointResource(const DBase* /*aClientId*/, TInt aEndpointNum,
2543 TUsbcEndpointResource aResource)
2545 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeAllocateEndpointResource()"));
2546 return DeAllocateEndpointResource(aEndpointNum, aResource);
2550 /** Queries the use of and endpoint resource.
2552 If the resource gets successfully allocated, it will be used from when the current bus transfer
2555 @param aClientId A pointer to the LDD querying the endpoint resource.
2556 @param aEndpointNum The number of the endpoint.
2557 @param aResource The endpoint resource to be queried.
2559 @return ETrue if the specified resource is in use at the endpoint, EFalse if not or if there was any error
2560 during the execution of the function.
2562 EXPORT_C TBool DUsbClientController::QueryEndpointResource(const DBase* /*aClientId*/, TInt aEndpointNum,
2563 TUsbcEndpointResource aResource)
2565 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::QueryEndpointResource()"));
2566 return QueryEndpointResource(aEndpointNum, aResource);
2570 EXPORT_C TInt DUsbClientController::EndpointPacketSize(const DBase* aClientId, TInt aEndpointNum)
2572 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EndpointPacketSize(0x%08x, %d)",
2573 aClientId, aEndpointNum));
2575 const TUsbcInterfaceSet* const ifcset_ptr = ClientId2InterfacePointer(aClientId);
2578 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: interface or clientid not found"));
2581 const TUsbcInterface* const ifc_ptr = ifcset_ptr->iInterfaces[ifcset_ptr->iCurrentInterface];
2582 const RPointerArray<TUsbcLogicalEndpoint>& ep_array = ifc_ptr->iEndpoints;
2583 const TInt n = ep_array.Count();
2584 for (TInt i = 0; i < n; i++)
2586 const TUsbcLogicalEndpoint* const ep = ep_array[i];
2587 if (EpAddr2Idx(ep->iPEndpoint->iEndpointAddr) == static_cast<TUint>(aEndpointNum))
2589 __KTRACE_OPT(KUSB, Kern::Printf(" Endpoint packet sizes: FS = %d HS = %d",
2590 ep->iEpSize_Fs, ep->iEpSize_Hs));
2591 const TInt size = iHighSpeed ? ep->iEpSize_Hs : ep->iEpSize_Fs;
2592 __KTRACE_OPT(KUSB, Kern::Printf(" Returning %d", size));
2596 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: endpoint not found"));
2602 // === USB Controller member function implementations - LDD API (public) ===========================
2605 EXPORT_C TBool DUsbClientController::CurrentlyUsingHighSpeed()
2607 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CurrentlyUsingHighSpeed()"));
2613 // === USB Controller member function implementations - PSL API (public) ===========================
2616 /** Gets called by the PSL to register a newly created derived class controller object.
2618 @param aUdc The number of the new UDC. It should be 0 for the first (or only) UDC in the system, 1 for the
2619 second one, and so forth. KUsbcMaxUdcs determines how many UDCs are supported.
2621 @return A pointer to the controller if successfully registered, NULL if aUdc out of (static) range.
2623 @publishedPartner @released
2625 DUsbClientController* DUsbClientController::RegisterUdc(TInt aUdc)
2627 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterUdc()"));
2628 if (aUdc < 0 || aUdc > (KUsbcMaxUdcs - 1))
2630 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: aUdc out of range (%d)", aUdc));
2633 return UsbClientController[aUdc] = this;
2638 // === USB Controller member function implementations - PSL API (protected) ========================
2641 /** Initialises an instance of this class, which is the base class of the derived class (= PSL, which is
2642 supposed to call this function).
2644 It does the following things:
2646 - disconnects the UDC from the bus,
2647 - initialises the USB descriptor pool, uses data from the PSL (see function argument list)
2648 - creates and initialises the basic USB device configuration
2649 - initialises the array of physical endpoints
2650 - initialises Ep0 structures (but doesn't configure & enable Ep0 yet)
2651 - creates and installs the USB power handler
2653 @param aDeviceDesc A pointer to a valid standard USB device descriptor or NULL. The values initially
2654 required in the descriptor follow from its constructor. The descriptor is not copied over, but rather this
2655 pointer is queued directly into the descriptor pool. Must be writable memory.
2657 @param aConfigDesc A pointer to a valid standard USB configuration descriptor or NULL. The values
2658 initially required in the descriptor follow from its constructor. The descriptor is not copied over, but
2659 rather this pointer is queued directly into the descriptor pool. Must be writable memory.
2661 @param aLangId A pointer to a valid USB language ID (string) descriptor. The values initially required in
2662 the descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
2663 queued directly into the descriptor pool. Must be writable memory. Other than the remaining four string
2664 descriptors, this one is not optional. The reason is that the USB spec mandates a LangId descriptor as
2665 soon as a single string descriptor gets returned by the device. So, even though the device might omit the
2666 Manufacturer, Product, SerialNumber, and Configuration string descriptors, it is at this point not known
2667 whether there will be any Interface string descriptors. Since any USB API user can create an interface
2668 with an Interface string descriptor, we have to insist here on the provision of a LangId string
2669 descriptor. (The PIL decides at run-time whether or not to return the LangId string descriptor to the
2670 host, depending on whether there exist any string descriptors at that time.)
2672 @param aManufacturer A pointer to a valid USB string descriptor or NULL. The values initially required in
2673 the descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
2674 queued directly into the descriptor pool. Must be writable memory. This descriptor will be referenced by
2675 the iManufacturer field in the device descriptor.
2677 @param aProduct A pointer to a valid USB string descriptor or NULL. The values initially required in the
2678 descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
2679 queued directly into the descriptor pool. Must be writable memory. This descriptor will be referenced by
2680 the iProduct field in the device descriptor.
2682 @param aSerialNum A pointer to a valid USB string descriptor or NULL. The values initially required in the
2683 descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
2684 queued directly into the descriptor pool. Must be writable memory. This descriptor will be referenced by
2685 the iSerialNumber field in the device descriptor.
2687 @param aConfig A pointer to a valid USB string descriptor or NULL. The values initially required in the
2688 descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
2689 queued directly into the descriptor pool. Must be writable memory. This descriptor will be referenced by
2690 the iConfiguration field in the configuration descriptor.
2692 @param aOtgDesc A pointer to a valid USB OTG descriptor (if OTG is supported by this device and is to be
2693 supported by the driver) or NULL. The values initially required in the descriptor follow from its
2694 constructor. The descriptor is not copied over, but rather this pointer is queued directly into the
2695 descriptor pool. Must be writable memory.
2697 @return EFalse, if USB descriptor pool initialisation fails, or if configuration creation fails, or if the
2698 PSL reports more endpoints than the constant KUsbcMaxEndpoints permits, or if the Ep0 logical endpoint
2699 creation fails, or if the creation of the power handler fails; ETrue, if base class object successfully
2702 @publishedPartner @released
2704 TBool DUsbClientController::InitialiseBaseClass(TUsbcDeviceDescriptor* aDeviceDesc,
2705 TUsbcConfigDescriptor* aConfigDesc,
2706 TUsbcLangIdDescriptor* aLangId,
2707 TUsbcStringDescriptor* aManufacturer,
2708 TUsbcStringDescriptor* aProduct,
2709 TUsbcStringDescriptor* aSerialNum,
2710 TUsbcStringDescriptor* aConfig,
2711 TUsbcOtgDescriptor* aOtgDesc)
2713 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::InitialiseBaseClass()"));
2714 // We don't want the host to see us (at least not yet):
2717 // Initialise USB descriptor pool
2718 if (iDescriptors.Init(aDeviceDesc, aConfigDesc, aLangId, aManufacturer, aProduct,
2719 aSerialNum, aConfig, aOtgDesc) != KErrNone)
2721 __KTRACE_OPT(KUSB, Kern::Printf(" Error: Descriptor initialization failed"));
2727 iOtgSupport = ETrue;
2728 iOtgFuncMap = aOtgDesc->DescriptorData()[2];
2729 // We're only interested in the following capability if this is
2730 // actually an OTG device.
2731 iOtgHnpHandledByHw = DeviceHnpHandledByHardwareCaps();
2734 // Some member variables
2735 iSelfPowered = aConfigDesc->Byte(7) & (1 << 6); // Byte 7: bmAttributes
2736 iRemoteWakeup = aConfigDesc->Byte(7) & (1 << 5);
2737 iRmWakeupStatus_Enabled = EFalse; // default
2739 if (DeviceHighSpeedCaps())
2741 if (iDescriptors.InitHs() != KErrNone)
2747 // Create and initialise our first (and only) configuration
2748 TUsbcConfiguration* config = new TUsbcConfiguration(1);
2753 iConfigs.Append(config);
2755 // Some variable initializations (needed here because of the goto's)
2756 const TUsbcEndpointCaps* caps = NULL;
2757 TUsbcEndpointInfo info(KUsbEpTypeControl, KUsbEpDirOut, 0);
2758 TUsbcLogicalEndpoint* ep = NULL;
2760 // Initialise the array of physical endpoints
2761 iDeviceTotalEndpoints = DeviceTotalEndpoints();
2762 __KTRACE_OPT(KUSB, Kern::Printf(" DeviceTotalEndpoints: %d", iDeviceTotalEndpoints));
2763 // KUsbcMaxEndpoints doesn't include ep 0
2764 if ((iDeviceTotalEndpoints > (KUsbcMaxEndpoints + 2)) ||
2765 ((iDeviceTotalEndpoints * sizeof(TUsbcPhysicalEndpoint)) > sizeof(iRealEndpoints)))
2767 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: too many endpoints! (change KUsbcMaxEndpoints: %d)",
2768 KUsbcMaxEndpoints));
2771 caps = DeviceEndpointCaps();
2772 for (TInt i = 0; i < iDeviceTotalEndpoints; ++i)
2774 iRealEndpoints[i].iEndpointAddr = EpIdx2Addr(i);
2775 __KTRACE_OPT(KUSB, Kern::Printf(" Caps[%02d] - iTypes: 0x%08x iSizes: 0x%08x",
2776 i, caps[i].iTypesAndDir, caps[i].iSizes));
2777 iRealEndpoints[i].iCaps = caps[i];
2778 iRealEndpoints[i].iCaps.iReserved[0] = 0;
2779 iRealEndpoints[i].iCaps.iReserved[1] = 0;
2780 if ((i > 1) && (caps[i].iTypesAndDir != KUsbEpNotAvailable))
2782 __KTRACE_OPT(KUSB, Kern::Printf(" --> UsableEndpoint: #%d", i));
2783 iDeviceUsableEndpoints++;
2787 // Initialise Ep0 structures (logical endpoints are numbered 1..KMaxEndpointsPerClient,
2788 // and virtual 0 is real 0):
2790 iEp0MaxPacketSize = caps[0].MaxPacketSize();
2791 __KTRACE_OPT(KUSB, Kern::Printf(" using Ep0 maxpacketsize of %d bytes", iEp0MaxPacketSize));
2792 info.iSize = iEp0MaxPacketSize;
2793 ep = new TUsbcLogicalEndpoint(this, 0, info, NULL, &iRealEndpoints[KEp0_Out]);
2798 __KTRACE_OPT(KUSB, Kern::Printf(" creating ep: mapping real ep %d --> logical ep 0", KEp0_Out));
2799 iRealEndpoints[KEp0_Out].iLEndpoint = ep;
2801 info.iDir = KUsbEpDirIn;
2802 ep = new TUsbcLogicalEndpoint(this, 0, info, NULL, &iRealEndpoints[KEp0_In]);
2807 __KTRACE_OPT(KUSB, Kern::Printf(" creating ep: mapping real ep %d --> logical ep 0", KEp0_In));
2808 iRealEndpoints[KEp0_In].iLEndpoint = ep;
2810 // Create the power handler
2811 iPowerHandler = new DUsbcPowerHandler(this);
2816 iPowerHandler->Add();
2819 iTrackDeviceState = DeviceStateChangeCaps();
2820 if (!iTrackDeviceState)
2822 // There shouldn't really be any PSL that doesn't support Device State
2823 // tracking, but we cannot simply enforce it as we have to preserve
2824 // backwards compatibility.
2825 __KTRACE_OPT(KUSB, Kern::Printf(" Warning: USB Device State tracking not supported by PSL"));
2831 delete iRealEndpoints[KEp0_In].iLEndpoint;
2833 delete iRealEndpoints[KEp0_Out].iLEndpoint;
2835 iConfigs.ResetAndDestroy();
2841 /** The standard constructor for this class.
2843 @publishedPartner @released
2845 DUsbClientController::DUsbClientController()
2846 : iEp0ReceivedNonStdRequest(EFalse),
2847 iRmWakeupStatus_Enabled(EFalse),
2849 iDeviceTotalEndpoints(0),
2850 iDeviceUsableEndpoints(0),
2851 iDeviceState(EUsbcDeviceStateUndefined),
2852 iDeviceStateB4Suspend(EUsbcDeviceStateUndefined),
2853 iSelfPowered(EFalse),
2854 iRemoteWakeup(EFalse),
2855 iTrackDeviceState(EFalse),
2856 iHardwareActivated(EFalse),
2857 iOtgSupport(EFalse),
2858 iOtgHnpHandledByHw(EFalse),
2862 iEp0MaxPacketSize(0),
2864 iEp0DataReceived(0),
2865 iEp0DataReceiving(EFalse),
2866 iEp0WritePending(EFalse),
2867 iEp0ClientDataTransmitting(EFalse),
2868 iEp0DeviceControl(NULL),
2869 iDescriptors(iEp0_TxBuf),
2874 iEp0_RxExtraCount(0),
2875 iEp0_RxExtraData(EFalse),
2876 iEp0_TxNonStdCount(0),
2877 iEp0ReadRequestCallbacks(_FOFF(TUsbcRequestCallback, iLink)),
2878 iClientCallbacks(_FOFF(TUsbcClientCallback, iLink)),
2879 iStatusCallbacks(_FOFF(TUsbcStatusCallback, iLink)),
2880 iEpStatusCallbacks(_FOFF(TUsbcEndpointStatusCallback, iLink)),
2881 iOtgCallbacks(_FOFF(TUsbcOtgFeatureCallback, iLink)),
2882 iReconnectTimer(ReconnectTimerCallback, this),
2883 iCableStatusTimer(CableStatusTimerCallback, this),
2884 iPowerUpDfc(PowerUpDfc, this, 3),
2885 iPowerDownDfc(PowerDownDfc, this, 3),
2887 #ifdef USB_OTG_CLIENT
2888 // In the OTG case the device starts out disabled
2889 iStackIsActive(EFalse),
2891 iStackIsActive(ETrue),
2892 #endif // USB_OTG_CLIENT
2893 iOtgClientConnect(EFalse),
2894 iClientSupportReady(EFalse),
2895 iDPlusEnabled(EFalse),
2896 iUsbResetDeferred(EFalse),
2897 iEnablePullUpOnDPlus(NULL),
2898 iDisablePullUpOnDPlus(NULL),
2901 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DUsbClientController()"));
2903 #ifndef SEPARATE_USB_DFC_QUEUE
2904 iPowerUpDfc.SetDfcQ(Kern::DfcQue0());
2905 iPowerDownDfc.SetDfcQ(Kern::DfcQue0());
2906 #endif // SEPARATE_USB_DFC_QUEUE
2908 for (TInt i = 0; i < KUsbcEpArraySize; i++)
2909 iRequestCallbacks[i] = NULL;
2913 /** This function gets called by the PSL upon detection of either of the following events:
2915 - USB Suspend event,
2916 - USB Resume signalling,
2917 - The USB cable has been attached (inserted) or detached (removed).
2919 @param anEvent An enum denoting the event that has occured.
2921 @return KErrArgument if the event is not recognized, otherwise KErrNone.
2923 @publishedPartner @released
2925 TInt DUsbClientController::DeviceEventNotification(TUsbcDeviceEvent anEvent)
2927 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeviceEventNotification()"));
2929 // This function may be called by the PSL from within an ISR -- so we have
2930 // to take care what we do here (and also in all functions that get called
2935 case EUsbEventSuspend:
2936 return ProcessSuspendEvent();
2937 case EUsbEventResume:
2938 return ProcessResumeEvent();
2939 case EUsbEventReset:
2940 return ProcessResetEvent();
2941 case EUsbEventCableInserted:
2942 return ProcessCableInsertEvent();
2943 case EUsbEventCableRemoved:
2944 return ProcessCableRemoveEvent();
2946 return KErrArgument;
2950 /** This function gets called by the PSL upon completion of a pending data transfer request.
2952 This function is not to be used for endpoint zero completions (use Ep0RequestComplete instead).
2954 @param aCallback A pointer to a data transfer request callback structure which was previously passed to
2955 the PSL in a SetupReadBuffer() or SetupWriteBuffer() call.
2957 @publishedPartner @released
2959 void DUsbClientController::EndpointRequestComplete(TUsbcRequestCallback* aCallback)
2961 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EndpointRequestComplete(%p)", aCallback));
2963 // This function may be called by the PSL from within an ISR -- so we have
2964 // to take care what we do here (and also in all functions that get called
2967 // We don't test aCallback for NULL here (and therefore risk a crash)
2968 // because the PSL should never give us a NULL argument. If it does it
2969 // means the PSL is buggy and ought to be fixed.
2970 ProcessDataTransferDone(*aCallback);
2974 /** This function should be called by the PSL after reception of an Ep0
2975 SET_FEATURE request with a feature selector of either {b_hnp_enable,
2976 a_hnp_support, a_alt_hnp_support}, but only when that Setup packet is not
2977 handed up to the PIL (for instance because it is auto-decoded and
2978 'swallowed' by the UDC hardware).
2980 @param aHnpState A bitmask indicating the present state of the three OTG
2981 feature selectors as follows:
2983 bit.0 == a_alt_hnp_support
2984 bit.1 == a_hnp_support
2985 bit.2 == b_hnp_enable
2987 @see DUsbClientController::ProcessSetClearDevFeature()
2989 @publishedPartner @released
2991 void DUsbClientController::HandleHnpRequest(TInt aHnpState)
2992 // This function is called by the PSL from within an ISR -- so we have to take care what we do here
2993 // (and also in all functions that get called from here).
2995 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::HandleHnpRequest(%d)", aHnpState));
2999 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only supported on a OTG device"));
3002 if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp))
3004 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only valid if OTG device supports HNP"));
3007 // (case KUsbFeature_B_HnpEnable:)
3008 if (aHnpState & 0x04)
3010 iOtgFuncMap |= KUsbOtgAttr_B_HnpEnable;
3012 // (case KUsbFeature_A_HnpSupport:)
3013 if (aHnpState & 0x02)
3015 iOtgFuncMap |= KUsbOtgAttr_A_HnpSupport;
3017 // (case KUsbFeature_A_AltHnpSupport:)
3018 if (aHnpState & 0x01)
3020 iOtgFuncMap |= KUsbOtgAttr_A_AltHnpSupport;
3022 OtgFeaturesNotify();
3026 /** This function gets called by the PSL upon completion of a pending endpoint zero data transfer request.
3028 @param aRealEndpoint Either 0 for Ep0 OUT (= Read), or 1 for Ep0 IN (= Write).
3029 @param aCount The number of bytes received or transmitted, respectively.
3030 @param aError The error status of the completed transfer request. Can be KErrNone if no error, KErrCancel
3031 if transfer was cancelled, or KErrPrematureEnd if a premature status end was encountered.
3033 @return KErrNone if no error during transfer completion processing, KErrGeneral if the request was a read &
3034 a Setup packet was received & the recipient for that packet couldn't be found (invalid packet: Ep0 has been
3035 stalled), KErrNotFound if the request was a read & the recipient for that packet (Setup or data) _was_
3036 found - however no read had been set up by that recipient (this case should be used by the PSL to disable
3037 the Ep0 interrupt at that point and give the LDD time to set up a new Ep0 read; once the 'missing' read
3038 was set up either Ep0ReceiveProceed or Ep0ReadSetupPktProceed will be called by the PIL).
3040 @publishedPartner @released
3042 TInt DUsbClientController::Ep0RequestComplete(TInt aRealEndpoint, TInt aCount, TInt aError)
3044 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::Ep0RequestComplete(%d)", aRealEndpoint));
3046 // This function may be called by the PSL from within an ISR -- so we have
3047 // to take care what we do here (and also in all functions that get called
3050 __ASSERT_DEBUG((aRealEndpoint < 2), Kern::Fault(KUsbPILPanicCat, __LINE__));
3051 if (aError != KErrNone && aError != KErrPrematureEnd)
3053 __KTRACE_OPT(KUSB, Kern::Printf(" Error: Ep0 request failed (code %d). "
3054 "Setting up new Read request.", aError));
3055 if (aRealEndpoint == KEp0_Rx)
3057 __KTRACE_OPT(KUSB, Kern::Printf(" (RX request failed)"));
3058 StallEndpoint(KEp0_Out);
3062 __KTRACE_OPT(KUSB, Kern::Printf(" (TX request failed)"));
3063 iEp0WritePending = EFalse;
3064 StallEndpoint(KEp0_In);
3066 // our only remedy: set up a new read request
3067 SetupEndpointZeroRead();
3071 if (aRealEndpoint & 0x01)
3073 r = ProcessEp0TransmitDone(aCount, aError);
3077 r = ProcessEp0ReceiveDone(aCount);
3078 if (r == KErrNotFound)
3080 // Don't set up new read yet if data weren't delivered.
3081 // (The PSL is supposed, upon encountering this return value,
3082 // to turn off Ep0's interrupt.)
3086 if (iEp0WritePending == EFalse)
3088 // we're done & no write request has been set up.
3089 // so: setup an Ep0 read again
3090 __KTRACE_OPT(KUSB, Kern::Printf(" Setting up new Ep0 read request."));
3091 SetupEndpointZeroRead();
3097 /** This function should be called by the PSL once the UDC (and thus the USB device) is in the Address state.
3099 @publishedPartner @released
3101 void DUsbClientController::MoveToAddressState()
3103 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::MoveToAddressState()"));
3105 // This function may be called by the PSL from within an ISR -- so we have
3106 // to take care what we do here (and also in all functions that get called
3109 NextDeviceState(EUsbcDeviceStateAddress);
3113 /** This function should be called by the PSL before certain UDC operations to inform the power model about
3114 the electrical current requirements.
3116 (The exact use of this function is currently not quite clear, so not calling it probably won't harm.)
3118 @param aCurrent The required electrical current.
3120 @publishedPartner @released
3122 void DUsbClientController::SetCurrent(TInt aCurrent)
3124 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetCurrent(%d)", aCurrent));
3126 // Not much for the moment... (What should we do here?)
3132 // === Platform Specific Layer (PSL) - private/virtual =============================================
3135 TInt DUsbClientController::OpenDmaChannel(TInt aRealEndpoint)
3137 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::OpenDmaChannel(%d)", aRealEndpoint));
3142 void DUsbClientController::CloseDmaChannel(TInt aRealEndpoint)
3144 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CloseDmaChannel(%d)", aRealEndpoint));
3148 TBool DUsbClientController::CableDetectWithoutPowerCaps() const
3150 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CableDetectWithoutPowerCaps()"));
3151 // Should be overridden in PSL if applicable.
3156 TBool DUsbClientController::DeviceHighSpeedCaps() const
3158 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeviceHighSpeedCaps()"));
3159 // Should be overridden in PSL if applicable.
3164 TBool DUsbClientController::DeviceResourceAllocV2Caps() const
3166 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeviceResourceAllocV2Caps()"));
3167 // Should be overridden in PSL if applicable.
3172 TBool DUsbClientController::DeviceHnpHandledByHardwareCaps() const
3174 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeviceHnpHandledByHardwareCaps()"));
3175 // Should be overridden in PSL if applicable.
3180 TInt DUsbClientController::EnterTestMode(TInt aTestSelector)
3182 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnterTestMode(%d)", aTestSelector));
3183 // Should be overridden in PSL if applicable.
3184 return KErrNotSupported;
3188 TBool DUsbClientController::PowerDownWhenActive() const
3190 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::PowerDownWhenActive()"));
3195 TInt DUsbClientController::PowerDown()
3197 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::PowerDown()"));
3202 TInt DUsbClientController::PowerUp()
3204 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::PowerUp()"));
3209 TInt DUsbClientController::OtgEnableUdc()
3211 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::OtgEnableUdc()"));
3216 TInt DUsbClientController::OtgDisableUdc()
3218 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::OtgDisableUdc()"));
3224 // === USB Controller member function implementations - Internal utility functions (private) =======
3227 TInt DUsbClientController::DeRegisterClientCallback(const DBase* aClientId)
3229 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterClientCallback()"));
3230 __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
3231 TSglQueIter<TUsbcClientCallback> iter(iClientCallbacks);
3232 TUsbcClientCallback* p;
3233 while ((p = iter++) != NULL)
3234 if (p->Owner() == aClientId)
3236 __KTRACE_OPT(KUSB, Kern::Printf(" removing ClientCallback @ 0x%x", p));
3237 iClientCallbacks.Remove(*p);
3240 __KTRACE_OPT(KUSB, Kern::Printf(" Client not found"));
3241 return KErrNotFound;
3245 TBool DUsbClientController::CheckEpAvailability(TInt aEndpointsUsed,
3246 const TUsbcEndpointInfoArray& aEndpointData,
3247 TInt aIfcNumber) const
3249 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CheckEpAvailability()"));
3250 if (aEndpointsUsed > KMaxEndpointsPerClient)
3252 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: too many endpoints claimed (%d)", aEndpointsUsed));
3255 TBool reserve[KUsbcEpArraySize]; // iDeviceTotalEndpoints can be equal to 32
3256 memset(reserve, EFalse, sizeof(reserve)); // reset the array
3257 for (TInt i = 0; i < aEndpointsUsed; ++i)
3259 __KTRACE_OPT(KUSB, Kern::Printf(" checking for (user) endpoint #%d availability...", i + 1));
3261 while (j < iDeviceTotalEndpoints)
3263 if ((iRealEndpoints[j].EndpointSuitable(&aEndpointData[i], aIfcNumber)) &&
3264 (reserve[j] == EFalse))
3266 __KTRACE_OPT(KUSB, Kern::Printf(" ---> found suitable endpoint: RealEndpoint #%d", j));
3267 reserve[j] = ETrue; // found one: mark this ep as reserved
3270 __KTRACE_OPT(KUSB, Kern::Printf(" -> endpoint not suitable: RealEndpoint #%d", j));
3273 if (j == iDeviceTotalEndpoints)
3282 TUsbcInterface* DUsbClientController::CreateInterface(const DBase* aClientId, TInt aIfc, TUint32 aFeatureWord)
3283 // We know that 9.2.3 says: "Interfaces are numbered from zero to one less than the number of
3284 // concurrent interfaces supported by the configuration." But since we permit the user to
3285 // change interface numbers, we can neither assume nor enforce anything about them here.
3287 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CreateInterface(x, aIfc=%d)", aIfc));
3288 TUsbcInterfaceSet* ifcset_ptr = NULL;
3289 TInt ifcset = ClientId2InterfaceNumber(aClientId);
3293 // New interface(set), so we need to find a number for it.
3295 const TInt num_ifcsets = iConfigs[0]->iInterfaceSets.Count();
3296 if (num_ifcsets == 255)
3298 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Too many interfaces already exist: 255"));
3301 // Find the smallest interface number that has not yet been used.
3302 for (ifcset = 0; ifcset < 256; ++ifcset)
3304 TBool n_used = EFalse;
3305 for (TInt i = 0; i < num_ifcsets; ++i)
3307 if ((iConfigs[0]->iInterfaceSets[i]->iInterfaceNumber) == ifcset)
3309 __KTRACE_OPT(KUSB, Kern::Printf(" interface number %d already used", ifcset));
3321 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: no available interface number found"));
3324 // append the ifcset
3325 __KTRACE_OPT(KUSB, Kern::Printf(" creating new InterfaceSet %d first", ifcset));
3328 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: invalid interface setting number (1): %d", aIfc));
3331 if ((ifcset_ptr = new TUsbcInterfaceSet(aClientId, ifcset)) == NULL)
3333 __KTRACE_OPT(KPANIC,
3334 Kern::Printf(" Error: new TUsbcInterfaceSet(aClientId, ifcset_num) failed"));
3337 iConfigs[0]->iInterfaceSets.Append(ifcset_ptr);
3339 else /* if (ifcset_num >= 0) */
3341 // use an existent ifcset
3343 __KTRACE_OPT(KUSB, Kern::Printf(" using existing InterfaceSet %d", ifcset));
3344 ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
3345 if (aIfc != ifcset_ptr->iInterfaces.Count())
3347 // 9.2.3: "Alternate settings range from zero to one less than the number of alternate
3348 // settings for a specific interface." (Thus we can here only append a setting.)
3349 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: invalid interface setting number (2): %d", aIfc));
3352 // Check whether the existing interface belongs indeed to this client
3353 if (ifcset_ptr->iClientId != aClientId)
3355 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: iClientId (%p) != aClientId (%p)",
3356 ifcset_ptr->iClientId, aClientId));
3360 const TBool no_ep0_requests = aFeatureWord & KUsbcInterfaceInfo_NoEp0RequestsPlease;
3361 TUsbcInterface* const ifc_ptr = new TUsbcInterface(ifcset_ptr, aIfc, no_ep0_requests);
3364 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: new TUsbcInterface(ifcset, aIfc) failed"));
3367 DeleteInterfaceSet(ifcset);
3371 ifcset_ptr->iInterfaces.Append(ifc_ptr);
3376 #define RESET_SETTINGRESERVE \
3377 for (TInt i = start_ep; i < iDeviceTotalEndpoints; i++) \
3379 if (iRealEndpoints[i].iSettingReserve) \
3380 iRealEndpoints[i].iSettingReserve = EFalse; \
3383 TInt DUsbClientController::CreateEndpoints(TUsbcInterface* aIfc, TInt aEndpointsUsed,
3384 const TUsbcEndpointInfoArray& aEndpointData,
3385 TInt aRealEpNumbers[])
3387 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CreateEndpoints()"));
3388 const TInt ifc_num = aIfc->iInterfaceSet->iInterfaceNumber;
3389 const TInt start_ep = 2;
3390 for (TInt i = 0; i < aEndpointsUsed; ++i)
3392 for (TInt j = start_ep; j < iDeviceTotalEndpoints; ++j)
3394 if (iRealEndpoints[j].EndpointSuitable(&aEndpointData[i], ifc_num))
3396 // Logical endpoints are numbered 1..KMaxEndpointsPerClient (virtual 0 is real 0 and 1)
3397 TUsbcLogicalEndpoint* const ep = new TUsbcLogicalEndpoint(this, i + 1, aEndpointData[i],
3398 aIfc, &iRealEndpoints[j]);
3401 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: new TUsbcLogicalEndpoint() failed"));
3402 aIfc->iEndpoints.ResetAndDestroy();
3403 RESET_SETTINGRESERVE;
3404 return KErrNoMemory;
3406 aIfc->iEndpoints.Append(ep);
3407 // Check on logical endpoint's sizes for compliance with special restrictions.
3408 if (aIfc->iSettingCode == 0)
3410 // For details see last paragraph of 5.7.3 "Interrupt Transfer Packet Size Constraints".
3411 if ((ep->iInfo.iType == KUsbEpTypeInterrupt) && (ep->iEpSize_Hs > 64))
3413 __KTRACE_OPT(KPANIC, Kern::Printf(" Warning: INT ep HS size = %d on default ifc setting",
3415 __KTRACE_OPT(KPANIC, Kern::Printf(" (should be <= 64)"));
3417 // For details see last paragraph of 5.6.3 "Isochronous Transfer Packet Size Constraints".
3418 else if ((ep->iInfo.iType == KUsbEpTypeIsochronous) && (ep->iInfo.iSize > 0))
3420 __KTRACE_OPT(KPANIC, Kern::Printf(" Warning: ISO ep size = %d on default ifc setting",
3422 __KTRACE_OPT(KPANIC, Kern::Printf(" (should be zero or ep non-existent)"));
3425 // If the endpoint doesn't support DMA (now or never) the next operation
3426 // will be a successful no-op.
3427 const TInt r = OpenDmaChannel(j);
3430 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Opening of DMA channel failed"));
3431 aIfc->iEndpoints.ResetAndDestroy();
3432 RESET_SETTINGRESERVE;
3435 __KTRACE_OPT(KUSB, Kern::Printf(" creating ep: mapping real ep %d -> logical ep %d",
3437 iRealEndpoints[j].iIfcNumber = &aIfc->iInterfaceSet->iInterfaceNumber;
3438 iRealEndpoints[j].iSettingReserve = ETrue;
3440 Kern::Printf(" ep->iInfo: iType=0x%x iDir=0x%x iSize=%d iInterval=%d",
3441 ep->iInfo.iType, ep->iInfo.iDir, ep->iInfo.iSize,
3442 ep->iInfo.iInterval));
3444 Kern::Printf(" ep->iInfo: iInterval_Hs=%d iTransactions=%d iExtra=%d",
3445 ep->iInfo.iInterval_Hs, ep->iInfo.iTransactions,
3447 // Store real endpoint numbers:
3448 // array[x] holds the number for logical ep x.
3449 aRealEpNumbers[i + 1] = j;
3454 aRealEpNumbers[0] = 0; // ep0: 0.
3456 Kern::Printf(" Endpoint Mapping for Interface %d / Setting %d:", ifc_num, aIfc->iSettingCode);
3457 Kern::Printf("Logical | Real");
3458 Kern::Printf("Endpoint | Endpoint");
3459 for (TInt ep = 0; ep <= aEndpointsUsed; ++ep) Kern::Printf(" %2d %3d",ep, aRealEpNumbers[ep]);
3461 RESET_SETTINGRESERVE;
3466 TInt DUsbClientController::SetupIfcDescriptor(TUsbcInterface* aIfc, TUsbcClassInfo& aClass, DThread* aThread,
3467 TDesC8* aString, const TUsbcEndpointInfoArray& aEndpointData)
3469 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetupIfcDescriptor()"));
3471 // Interface descriptor
3472 TUsbcDescriptorBase* d = TUsbcInterfaceDescriptor::New(aIfc->iInterfaceSet->iInterfaceNumber,
3474 aIfc->iEndpoints.Count(),
3478 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Memory allocation for ifc desc failed."));
3479 return KErrNoMemory;
3481 iDescriptors.InsertDescriptor(d);
3483 // Interface string descriptor
3486 // we don't know the length of the string, so we have to allocate memory dynamically
3487 TUint strlen = Kern::ThreadGetDesLength(aThread, aString);
3488 if (strlen > KUsbStringDescStringMaxSize)
3490 __KTRACE_OPT(KPANIC, Kern::Printf(" Warning: $ descriptor too long - string will be truncated"));
3491 strlen = KUsbStringDescStringMaxSize;
3493 HBuf8* const stringbuf = HBuf8::New(strlen);
3496 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Memory allocation for ifc $ desc string failed."));
3497 iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
3498 aIfc->iSettingCode);
3499 return KErrNoMemory;
3501 stringbuf->SetMax();
3502 // the aString points to data that lives in user memory, so we have to copy it:
3503 TInt r = Kern::ThreadDesRead(aThread, aString, *stringbuf, 0);
3506 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Thread read error"));
3507 iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
3508 aIfc->iSettingCode);
3512 TUsbcStringDescriptor* const sd = TUsbcStringDescriptor::New(*stringbuf);
3515 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Memory allocation for ifc $ desc failed."));
3516 iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
3517 aIfc->iSettingCode);
3519 return KErrNoMemory;
3521 iDescriptors.SetIfcStringDescriptor(sd, aIfc->iInterfaceSet->iInterfaceNumber, aIfc->iSettingCode);
3522 delete stringbuf; // the (EPOC) descriptor was copied by New()
3525 // Endpoint descriptors
3526 for (TInt i = 0; i < aIfc->iEndpoints.Count(); ++i)
3528 // The reason for using another function argument for Endpoint Info
3529 // (and not possibly - similar to the Endpoint Address -
3530 // "aIfc->iEndpoints[i]->iPEndpoint->iLEndpoint->iInfo") is that this time
3531 // there are no logical endpoints associated with our real endpoints,
3532 // i.e. iLEndpoint is NULL!.
3533 if (aEndpointData[i].iExtra)
3535 // if a non-standard endpoint descriptor is requested...
3536 if (aEndpointData[i].iExtra != 2)
3538 // ...then it must be a Audio Class endpoint descriptor. Else...
3539 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: EP desc extension > 2 bytes (%d)",
3540 aEndpointData[i].iExtra));
3541 iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
3542 aIfc->iSettingCode);
3543 return KErrArgument;
3545 d = TUsbcAudioEndpointDescriptor::New(aIfc->iEndpoints[i]->iPEndpoint->iEndpointAddr,
3550 d = TUsbcEndpointDescriptor::New(aIfc->iEndpoints[i]->iPEndpoint->iEndpointAddr,
3555 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Memory allocation for ep desc #%d failed.", i));
3556 iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
3557 aIfc->iSettingCode);
3558 return KErrNoMemory;
3560 iDescriptors.InsertDescriptor(d);
3567 TInt DUsbClientController::ClientId2InterfaceNumber(const DBase* aClientId) const
3569 const TInt num_ifcsets = iConfigs[0]->iInterfaceSets.Count();
3570 for (TInt i = 0; i < num_ifcsets; ++i)
3572 if (iConfigs[0]->iInterfaceSets[i]->iClientId == aClientId)
3574 return iConfigs[0]->iInterfaceSets[i]->iInterfaceNumber;
3581 TUsbcInterfaceSet* DUsbClientController::ClientId2InterfacePointer(const DBase* aClientId) const
3583 const TInt num_ifcsets = iConfigs[0]->iInterfaceSets.Count();
3584 for (TInt i = 0; i < num_ifcsets; ++i)
3586 if (iConfigs[0]->iInterfaceSets[i]->iClientId == aClientId)
3588 return iConfigs[0]->iInterfaceSets[i];
3595 const DBase* DUsbClientController::InterfaceNumber2ClientId(TInt aIfcSet) const
3597 if (!InterfaceExists(aIfcSet))
3601 return InterfaceNumber2InterfacePointer(aIfcSet)->iClientId;
3605 TUsbcInterfaceSet* DUsbClientController::InterfaceNumber2InterfacePointer(TInt aIfcSet) const
3607 const TInt num_ifcsets = iConfigs[0]->iInterfaceSets.Count();
3608 for (TInt i = 0; i < num_ifcsets; ++i)
3610 if ((iConfigs[0]->iInterfaceSets[i]->iInterfaceNumber) == aIfcSet)
3612 return iConfigs[0]->iInterfaceSets[i];
3619 TInt DUsbClientController::ActivateHardwareController()
3621 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ActivateHardwareController()"));
3622 if (iHardwareActivated)
3624 __KTRACE_OPT(KUSB, Kern::Printf(" already active -> returning"));
3628 TInt r = StartUdc();
3631 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: StartUdc() failed"));
3632 return KErrHardwareNotAvailable;
3634 r = OtgEnableUdc(); // turn on UDC (OTG flavour)
3637 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: OtgEnableUdc() failed: %d", r));
3639 iHardwareActivated = ETrue;
3641 // Configure & enable endpoint zero
3642 const TUsbcLogicalEndpoint* const ep0_0 = iRealEndpoints[0].iLEndpoint;
3643 const TUsbcLogicalEndpoint* const ep0_1 = iRealEndpoints[1].iLEndpoint;
3646 const_cast<TUsbcLogicalEndpoint*>(ep0_0)->iInfo.iSize = ep0_0->iEpSize_Hs;
3647 const_cast<TUsbcLogicalEndpoint*>(ep0_1)->iInfo.iSize = ep0_1->iEpSize_Hs;
3651 const_cast<TUsbcLogicalEndpoint*>(ep0_0)->iInfo.iSize = ep0_0->iEpSize_Fs;
3652 const_cast<TUsbcLogicalEndpoint*>(ep0_1)->iInfo.iSize = ep0_1->iEpSize_Fs;
3654 ConfigureEndpoint(0, ep0_0->iInfo);
3655 ConfigureEndpoint(1, ep0_1->iInfo);
3656 iEp0MaxPacketSize = ep0_0->iInfo.iSize;
3658 __KTRACE_OPT(KUSB, Kern::Printf(" Controller activated."));
3659 if (UsbConnectionStatus())
3661 if (iDeviceState == EUsbcDeviceStateUndefined)
3663 NextDeviceState(EUsbcDeviceStateAttached);
3665 NextDeviceState(EUsbcDeviceStatePowered);
3671 void DUsbClientController::DeActivateHardwareController()
3673 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeActivateHardwareController()"));
3674 if (!iHardwareActivated)
3676 __KTRACE_OPT(KUSB, Kern::Printf(" not active -> returning"));
3679 // Deconfigure & disable endpoint zero
3680 DeConfigureEndpoint(KEp0_Out);
3681 DeConfigureEndpoint(KEp0_In);
3683 TInt r = OtgDisableUdc(); // turn off UDC (OTG flavour)
3686 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: OtgDisableUdc() failed: %d", r));
3689 iHardwareActivated = EFalse;
3690 __KTRACE_OPT(KUSB, Kern::Printf(" Controller deactivated."));
3691 if (UsbConnectionStatus())
3693 NextDeviceState(EUsbcDeviceStateAttached);
3699 void DUsbClientController::DeleteInterfaceSet(TInt aIfcSet)
3701 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteInterfaceSet(%d)", aIfcSet));
3702 TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(aIfcSet);
3705 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: invalid interface number: %d", aIfcSet));
3708 const TInt idx = iConfigs[0]->iInterfaceSets.Find(ifcset_ptr);
3709 if (idx == KErrNotFound)
3711 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: interface not found in array"));
3714 iConfigs[0]->iInterfaceSets.Remove(idx);
3719 void DUsbClientController::DeleteInterface(TInt aIfcSet, TInt aIfc)
3721 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteInterface(%d, %d)", aIfcSet, aIfc));
3722 TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(aIfcSet);
3725 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: invalid interface number: %d", aIfcSet));
3728 if (ifcset_ptr->iInterfaces.Count() <= aIfc)
3730 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: invalid interface setting: %d", aIfc));
3733 TUsbcInterface* const ifc_ptr = ifcset_ptr->iInterfaces[aIfc];
3734 // Always first remove, then delete (see ~TUsbcLogicalEndpoint() for the reason why)
3735 ifcset_ptr->iInterfaces.Remove(aIfc);
3737 if (aIfc == ifcset_ptr->iCurrentInterface)
3739 __KTRACE_OPT(KUSB, Kern::Printf(" > Warning: deleting current interface setting"));
3740 ifcset_ptr->iCurrentInterface = 0;
3745 void DUsbClientController::CancelTransferRequests(TInt aRealEndpoint)
3747 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CancelTransferRequests(aRealEndpoint=%d)",
3749 const DBase* const clientId = PEndpoint2ClientId(aRealEndpoint);
3750 if (EpIdx2Addr(aRealEndpoint) & KUsbEpAddress_In)
3752 CancelWriteBuffer(clientId, aRealEndpoint);
3756 CancelReadBuffer(clientId, aRealEndpoint);
3761 void DUsbClientController::DeleteRequestCallback(const DBase* aClientId, TInt aEndpointNum,
3762 TTransferDirection aTransferDir)
3764 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteRequestCallback()"));
3766 if (aEndpointNum == 0)
3768 const TInt irq = NKern::DisableAllInterrupts();
3769 TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks);
3770 TUsbcRequestCallback* p;
3771 while ((p = iter++) != NULL)
3773 if (p->Owner() == aClientId)
3775 __ASSERT_DEBUG((p->iRealEpNum == 0), Kern::Fault(KUsbPILPanicCat, __LINE__));
3776 __ASSERT_DEBUG((p->iTransferDir == EControllerRead), Kern::Fault(KUsbPILPanicCat, __LINE__));
3777 __KTRACE_OPT(KUSB, Kern::Printf(" removing RequestCallback @ 0x%x (ep0)", p));
3778 iEp0ReadRequestCallbacks.Remove(*p);
3781 NKern::RestoreInterrupts(irq);
3785 TUsbcRequestCallback* const p = iRequestCallbacks[aEndpointNum];
3788 __ASSERT_DEBUG((p->Owner() == aClientId), Kern::Fault(KUsbPILPanicCat, __LINE__));
3789 __ASSERT_DEBUG((p->iTransferDir == aTransferDir), Kern::Fault(KUsbPILPanicCat, __LINE__));
3790 __KTRACE_OPT(KUSB, Kern::Printf(" removing RequestCallback @ 0x%x", p));
3791 iRequestCallbacks[aEndpointNum] = NULL;
3796 void DUsbClientController::DeleteRequestCallbacks(const DBase* aClientId)
3798 // aClientId being NULL means: delete all requests for *all* clients.
3799 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteRequestCallbacks()"));
3801 const TInt irq = NKern::DisableAllInterrupts();
3802 TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks);
3803 TUsbcRequestCallback* p;
3804 while ((p = iter++) != NULL)
3806 if (!aClientId || p->Owner() == aClientId)
3808 __KTRACE_OPT(KUSB, Kern::Printf(" removing RequestCallback @ 0x%x (ep0)", p));
3809 iEp0ReadRequestCallbacks.Remove(*p);
3812 NKern::RestoreInterrupts(irq);
3814 for (TInt i = 1; i < KUsbcEpArraySize; i++)
3816 TUsbcRequestCallback* const p = iRequestCallbacks[i];
3817 if (p && (!aClientId || p->Owner() == aClientId))
3819 __KTRACE_OPT(KUSB, Kern::Printf(" removing RequestCallback @ 0x%x", p));
3820 iRequestCallbacks[i] = NULL;
3826 void DUsbClientController::StatusNotify(TUsbcDeviceState aState, const DBase* aClientId)
3828 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::StatusNotify()"));
3830 // This function may be called by the PSL (via chapter9.cpp) from within an
3831 // ISR -- so we have to take care what we do here (and also in all
3832 // functions that get called from here).
3834 TSglQueIter<TUsbcStatusCallback> iter(iStatusCallbacks);
3835 TUsbcStatusCallback* p;
3836 while ((p = iter++) != NULL)
3838 if (!aClientId || aClientId == p->Owner())
3840 __KTRACE_OPT(KUSB, Kern::Printf(" notifying LDD @ 0x%x about %d", p->Owner(), aState));
3841 p->SetState(aState);
3848 void DUsbClientController::EpStatusNotify(TInt aRealEndpoint)
3850 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EpStatusNotify()"));
3852 // This function may be called by the PSL (via chapter9.cpp) from within an
3853 // ISR -- so we have to take care what we do here (and also in all
3854 // functions that get called from here).
3856 const DBase* const client_id = PEndpoint2ClientId(aRealEndpoint);
3859 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Client not found for real ep %d", aRealEndpoint));
3862 // Check if there is a notification request queued for that client (if not, we can return here).
3863 TSglQueIter<TUsbcEndpointStatusCallback> iter(iEpStatusCallbacks);
3864 TUsbcEndpointStatusCallback* p;
3865 while ((p = iter++) != NULL)
3867 if (p->Owner() == client_id)
3874 __KTRACE_OPT(KUSB, Kern::Printf(" No notification request for that client, returning"));
3877 const TInt ifcset = ClientId2InterfaceNumber(client_id);
3880 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Ifcset not found for clientid %d", client_id));
3883 const TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
3886 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Ifcset pointer not found for ifcset %d", ifcset));
3889 const TUsbcInterface* const ifc_ptr = ifcset_ptr->CurrentInterface();
3892 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Current ifc pointer not found for ifcset %d", ifcset));
3896 const TInt eps = ifc_ptr->iEndpoints.Count();
3897 for (TInt i = 0; i < eps; i++)
3899 const TUsbcLogicalEndpoint* const ep_ptr = ifc_ptr->iEndpoints[i];
3900 __KTRACE_OPT(KUSB, Kern::Printf(" checking logical ep #%d for stall state...",
3901 ep_ptr->iLEndpointNum));
3902 if (ep_ptr->iPEndpoint->iHalt)
3904 __KTRACE_OPT(KUSB, Kern::Printf(" -- stalled"));
3905 // set the bit n to 1, where n is the logical endpoint number minus one
3906 state |= (1 << (ep_ptr->iLEndpointNum - 1));
3910 __KTRACE_OPT(KUSB, Kern::Printf(" -- not stalled"));
3913 __KTRACE_OPT(KUSB, Kern::Printf(" passing ep state 0x%x on to LDD @ 0x%x", state, client_id));
3919 void DUsbClientController::OtgFeaturesNotify()
3921 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::OtgFeaturesNotify()"));
3923 // This function may be called from the PSL (via PIL's chapter9.cpp) from
3924 // within an ISR -- so we have to take care what we do here (and also in
3925 // all functions that get called from here).
3927 TSglQueIter<TUsbcOtgFeatureCallback> iter(iOtgCallbacks);
3928 TUsbcOtgFeatureCallback* p;
3929 while ((p = iter++) != NULL)
3931 p->SetFeatures(iOtgFuncMap & 0x1C);
3937 void DUsbClientController::RunClientCallbacks()
3939 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RunClientCallbacks()"));
3940 TSglQueIter<TUsbcClientCallback> iter(iClientCallbacks);
3941 TUsbcClientCallback* p;
3942 while ((p = iter++) != NULL)
3944 __KTRACE_OPT(KUSB, Kern::Printf("Callback 0x%x", p));
3950 void DUsbClientController::ProcessDataTransferDone(TUsbcRequestCallback& aRcb)
3952 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessDataTransferDone()"));
3953 // This piece can only be called in thread context from ProcessEp0DataReceived() /
3954 // ProcessEp0SetupReceived() via the call to ProcessEp0ReceiveDone() in
3955 // SetupReadBuffer(), which is guarded by an interrupt lock.
3956 TInt ep = aRcb.iRealEpNum;
3959 if (aRcb.iTransferDir == EControllerRead)
3961 // Ep0 OUT is special
3962 iEp0ReadRequestCallbacks.Remove(aRcb);
3964 else // EControllerWrite
3966 // Ep0 IN needs to be adjusted: it's '1' within the PIL.
3970 if (ep > 0) // not 'else'!
3972 __ASSERT_DEBUG((iRequestCallbacks[ep] == &aRcb), Kern::Fault(KUsbPILPanicCat, __LINE__));
3973 __KTRACE_OPT(KUSB, Kern::Printf(" > removing RequestCallback[%d] @ 0x%x", ep, &aRcb));
3974 iRequestCallbacks[ep] = NULL;
3980 void DUsbClientController::NextDeviceState(TUsbcDeviceState aNextState)
3982 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::NextDeviceState()"));
3984 const char* const states[] = {"Undefined", "Attached", "Powered", "Default",
3985 "Address", "Configured", "Suspended"};
3986 if ((aNextState >= EUsbcDeviceStateUndefined) &&
3987 (aNextState <= EUsbcDeviceStateSuspended))
3989 __KTRACE_OPT(KUSB, Kern::Printf(" next device state: %s", states[aNextState]));
3993 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Unknown next device state: %d", aNextState));
3995 // Print a warning when an invalid state transition is detected
3996 // 'Undefined' is not a state that is mentioned in the USB spec, but
3997 // that's what we're in once the cable gets pulled (for instance).
3998 switch (iDeviceState)
4000 case EUsbcDeviceStateUndefined:
4001 // valid: Undefined -> Attached
4002 if (aNextState != EUsbcDeviceStateAttached)
4005 case EUsbcDeviceStateAttached:
4006 // valid: Attached -> {Undefined, Powered}
4007 if ((aNextState != EUsbcDeviceStateUndefined) &&
4008 (aNextState != EUsbcDeviceStatePowered))
4011 case EUsbcDeviceStatePowered:
4012 // valid: Powered -> {Undefined, Attached, Default, Suspended}
4013 if ((aNextState != EUsbcDeviceStateUndefined) &&
4014 (aNextState != EUsbcDeviceStateAttached) &&
4015 (aNextState != EUsbcDeviceStateDefault) &&
4016 (aNextState != EUsbcDeviceStateSuspended))
4019 case EUsbcDeviceStateDefault:
4020 // valid: Default -> {Undefined, Powered, Default, Address, Suspended}
4021 if ((aNextState != EUsbcDeviceStateUndefined) &&
4022 (aNextState != EUsbcDeviceStatePowered) &&
4023 (aNextState != EUsbcDeviceStateDefault) &&
4024 (aNextState != EUsbcDeviceStateAddress) &&
4025 (aNextState != EUsbcDeviceStateSuspended))
4028 case EUsbcDeviceStateAddress:
4029 // valid: Address -> {Undefined, Powered, Default, Configured, Suspended}
4030 if ((aNextState != EUsbcDeviceStateUndefined) &&
4031 (aNextState != EUsbcDeviceStatePowered) &&
4032 (aNextState != EUsbcDeviceStateDefault) &&
4033 (aNextState != EUsbcDeviceStateConfigured) &&
4034 (aNextState != EUsbcDeviceStateSuspended))
4037 case EUsbcDeviceStateConfigured:
4038 // valid: Configured -> {Undefined, Powered, Default, Address, Suspended}
4039 if ((aNextState != EUsbcDeviceStateUndefined) &&
4040 (aNextState != EUsbcDeviceStatePowered) &&
4041 (aNextState != EUsbcDeviceStateDefault) &&
4042 (aNextState != EUsbcDeviceStateAddress) &&
4043 (aNextState != EUsbcDeviceStateSuspended))
4046 case EUsbcDeviceStateSuspended:
4047 // valid: Suspended -> {Undefined, Powered, Default, Address, Configured}
4048 if ((aNextState != EUsbcDeviceStateUndefined) &&
4049 (aNextState != EUsbcDeviceStatePowered) &&
4050 (aNextState != EUsbcDeviceStateDefault) &&
4051 (aNextState != EUsbcDeviceStateAddress) &&
4052 (aNextState != EUsbcDeviceStateConfigured))
4056 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Unknown current device state: %d", iDeviceState));
4059 // KUSB only (instead of KPANIC) so as not to worry people too much where
4060 // a particular h/w regularly enforces invalid (but harmless) transitions
4061 __KTRACE_OPT(KUSB, Kern::Printf(" Warning: Invalid next state from %s", states[iDeviceState]));
4065 iDeviceState = aNextState;
4066 StatusNotify(iDeviceState);
4070 TInt DUsbClientController::ProcessSuspendEvent()
4072 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSuspendEvent()"));
4073 // A suspend interrupt has been received and needs attention.
4074 iDeviceStateB4Suspend = iDeviceState;
4075 // We have to move to the Suspend state immediately (in case it's a genuine Suspend)
4076 // because 7.1.7.6 says: "The device must actually be suspended, [...] after no more
4077 // than 10ms of bus inactivity [...]." Assuming we got the interrupt 3ms after the
4078 // Suspend condition arose, we have now 7ms left.
4079 NextDeviceState(EUsbcDeviceStateSuspended);
4081 // For some reason we get this interrupt also when the USB cable has been pulled.
4082 // So we want to see if that is the case in order to move to the Undefined state instead.
4083 // However, instead of immediately checking the status of the USB cable we wait for a
4084 // short moment (KUsbCableStatusDelay, see top of file), until things have become stable.
4085 // Then, in the timer callback, we can change the device state once more if necessary.
4086 iCableStatusTimer.OneShot(KUsbCableStatusDelay);
4092 // ISR (from CableStatusTimerCallback)
4094 TInt DUsbClientController::ProcessSuspendEventProceed()
4096 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSuspendEventProceed()"));
4097 if (!UsbConnectionStatus())
4099 // If we are no longer connected to the bus, we go into Undefined state (from Suspend).
4100 __KTRACE_OPT(KUSB, Kern::Printf(" > USB cable detached"));
4101 NextDeviceState(EUsbcDeviceStateUndefined);
4107 TInt DUsbClientController::ProcessResumeEvent()
4109 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessResumeEvent()"));
4110 iCableStatusTimer.Cancel();
4111 if (iDeviceState == EUsbcDeviceStateSuspended)
4113 NextDeviceState(iDeviceStateB4Suspend);
4120 TInt DUsbClientController::ProcessResetEvent(TBool aPslUpcall)
4122 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessResetEvent()"));
4126 // Call back into PSL if we're coming from there.
4127 // Also, do it always, even when PIL processing will be deferred.
4131 #ifdef USB_OTG_CLIENT
4132 if (iUsbResetDeferred) // implies (iOtgHnpHandledByHw == ETrue)
4134 __KTRACE_OPT(KUSB, Kern::Printf(" User-side (still) not ready -> returning"));
4137 else if (iOtgHnpHandledByHw && !iClientSupportReady)
4139 // Wait with the PIL Reset processing until user-side is ready
4140 __KTRACE_OPT(KUSB, Kern::Printf(" User-side not ready -> deferring"));
4141 iUsbResetDeferred = ETrue;
4144 #endif // USB_OTG_CLIENT
4146 iCableStatusTimer.Cancel();
4147 if (iDeviceState == EUsbcDeviceStateAttached)
4149 NextDeviceState(EUsbcDeviceStatePowered);
4151 // Notify the world. (This will just queue a DFC, so users won't actually be
4152 // notified before we return. But we change the device state already here so
4153 // ChangeConfiguration will see the correct one.)
4154 NextDeviceState(EUsbcDeviceStateDefault);
4155 // Tear down the current configuration (never called from thread)
4156 ChangeConfiguration(0);
4157 // Reset essential vars
4158 iRmWakeupStatus_Enabled = EFalse;
4159 ResetEp0DataOutVars();
4160 iEp0_RxExtraData = EFalse;
4161 iEp0WritePending = EFalse;
4162 iEp0ClientDataTransmitting = EFalse;
4163 // Reset OTG features, leave attributes as is
4164 iOtgFuncMap &= KUsbOtgAttr_SrpSupp | KUsbOtgAttr_HnpSupp;
4167 OtgFeaturesNotify();
4170 // Check whether there's a speed change
4171 const TBool was_hs = iHighSpeed;
4172 iHighSpeed = CurrentlyUsingHighSpeed();
4173 if (!was_hs && iHighSpeed)
4175 __KTRACE_OPT(KUSB, Kern::Printf(" Moving to High-speed"));
4178 else if (was_hs && !iHighSpeed)
4180 __KTRACE_OPT(KUSB, Kern::Printf(" Moving to Full-speed"));
4184 // Setup initial Ep0 read (SetupEndpointZeroRead never called from thread)
4185 if (SetupEndpointZeroRead() != KErrNone)
4187 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: while setting up Ep0 read"));
4195 TInt DUsbClientController::ProcessCableInsertEvent()
4197 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessCableInsertEvent()"));
4198 #ifdef USB_OTG_CLIENT
4199 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: EUsbEventCableInsert shouldn't be sent by an OTG Client PSL"));
4200 return KErrArgument;
4202 NextDeviceState(EUsbcDeviceStateAttached);
4203 if (iHardwareActivated)
4205 NextDeviceState(EUsbcDeviceStatePowered);
4208 #endif // #ifdef USB_OTG_CLIENT
4212 TInt DUsbClientController::ProcessCableRemoveEvent()
4214 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessCableRemoveEvent()"));
4215 #ifdef USB_OTG_CLIENT
4216 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: EUsbEventCableRemoved shouldn't be sent by an OTG Client PSL"));
4217 return KErrArgument;
4219 // Tear down the current configuration (if any)
4220 ChangeConfiguration(0);
4221 NextDeviceState(EUsbcDeviceStateUndefined);
4223 #endif // #ifdef USB_OTG_CLIENT
4227 void DUsbClientController::EnterFullSpeed()
4229 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnterFullSpeed()"));
4230 iDescriptors.UpdateDescriptorsFs();
4234 void DUsbClientController::EnterHighSpeed()
4236 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnterHighSpeed()"));
4237 iDescriptors.UpdateDescriptorsHs();
4242 // Called whenever either iOtgClientConnect or iClientSupportReady changes value.
4244 TInt DUsbClientController::EvaluateOtgConnectFlags()
4246 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EvaluateOtgConnectFlags()"));
4250 // Check to see if the current flag states result in a change to the
4251 // need to activate the DPLUS pull-up
4253 if (!iOtgHnpHandledByHw)
4256 enableDPlus = (iOtgClientConnect && iClientSupportReady);
4260 // certain h/w: handles HNP connect/disconnect automatically
4261 __KTRACE_OPT(KUSB, Kern::Printf(" HNP-handling h/w: only considering user-side readiness"));
4262 enableDPlus = iClientSupportReady;
4265 if (enableDPlus == iDPlusEnabled)
4270 // There has been a changed requirement that must be serviced...
4273 __KTRACE_OPT(KUSB, Kern::Printf(" calling (*iEnablePullUpOnDPlus)()"));
4274 if (iEnablePullUpOnDPlus != NULL)
4276 iDPlusEnabled = enableDPlus;
4277 // First we move to Suspend state to trigger a state change
4278 // notification in any case, even if no cable and/or host are
4279 // connected. The next Reset will get us out of it again.
4280 iDeviceStateB4Suspend = iDeviceState;
4281 NextDeviceState(EUsbcDeviceStateSuspended);
4282 r = (*iEnablePullUpOnDPlus)(iOtgContext);
4285 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: iEnablePullUpOnDPlus() = %d", r));
4290 __KTRACE_OPT(KUSB, Kern::Printf(" Warning: iEnablePullUpOnDPlus pointer not ready"));
4291 // We cannot enforce the presence of the pointer (via an ASSERT)
4292 // since it might only be available at a later point.
4293 // We shouldn't return an error at this point either, since the
4294 // problem will be a systematic one.
4299 __KTRACE_OPT(KUSB, Kern::Printf(" calling (*iDisablePullUpOnDPlus)()"));
4300 if (iDisablePullUpOnDPlus != NULL)
4302 iDPlusEnabled = enableDPlus;
4303 r = (*iDisablePullUpOnDPlus)(iOtgContext);
4306 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: iDisablePullUpOnDPlus() = %d", r));
4311 __KTRACE_OPT(KUSB, Kern::Printf(" Warning: iDisablePullUpOnDPlus pointer not ready"));
4312 // We cannot enforce the presence of the pointer (via an ASSERT)
4313 // since it might only be available at a later point.
4314 // We shouldn't return an error at this point either, since the
4315 // problem will be a systematic one.
4325 void DUsbClientController::ReconnectTimerCallback(TAny *aPtr)
4327 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ReconnectTimerCallback()"));
4330 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: !aPtr"));
4333 DUsbClientController* const ptr = static_cast<DUsbClientController*>(aPtr);
4341 void DUsbClientController::CableStatusTimerCallback(TAny *aPtr)
4343 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CableStatusTimerCallback()"));
4346 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: !aPtr"));
4349 DUsbClientController* const ptr = static_cast<DUsbClientController*>(aPtr);
4350 ptr->ProcessSuspendEventProceed();
4357 void DUsbClientController::PowerUpDfc(TAny* aPtr)
4359 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::PowerUpDfc"));
4362 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: !aPtr"));
4365 DUsbClientController* const ptr = static_cast<DUsbClientController*>(aPtr);
4366 __PM_ASSERT(ptr->iStandby);
4367 (void) ptr->PowerUp();
4368 ptr->iStandby = EFalse;
4369 ptr->iPowerHandler->PowerUpDone();
4376 void DUsbClientController::PowerDownDfc(TAny* aPtr)
4378 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::PowerDownDfc"));
4381 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: !aPtr"));
4384 DUsbClientController* const ptr = static_cast<DUsbClientController*>(aPtr);
4385 __PM_ASSERT(!ptr->iStandby);
4386 ptr->iStandby = ETrue;
4387 // We might not want to power down when the UDC is active:
4388 if (!ptr->iHardwareActivated || ptr->PowerDownWhenActive())
4390 (void) ptr->PowerDown();
4391 __KTRACE_OPT(KUSB, Kern::Printf("Calling PowerHandler->PowerDownDone()"));
4392 ptr->iPowerHandler->PowerDownDone();
4396 __KTRACE_OPT(KUSB, Kern::Printf("Not calling PowerHandler->PowerDownDone()"));
4397 __KTRACE_OPT(KUSB, Kern::Printf(" because UDC is active."));