Update contrib.
1 // Copyright (c) 2004-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 // template\template_assp\pa_usbc.cpp
15 // Platform-dependent USB client controller layer (USB PSL).
20 #include <template_assp.h> // /assp/template_assp/
21 #include <template_assp_priv.h> // /assp/template_assp/
23 #include <drivers/usbc.h>
25 #include "pa_usbc.h" // .
29 static const char KUsbPanicCat[] = "USB PSL";
33 // Define USB_SUPPORTS_PREMATURE_STATUS_IN to enable proper handling of a premature STATUS_IN stage, i.e. a
34 // situation where the host sends less data than first announced and instead of more data (OUT) will send an
35 // IN token to start the status stage. What we do in order to implement this here is to prime the TX fifo with
36 // a ZLP immediately when we find out that we're dealing with a DATA_OUT request. This way, as soon as the
37 // premature IN token is received, we complete the transaction by sending off the ZLP. If we don't prime the
38 // TX fifo then there is no way for us to recognise a premature status because the IN token itself doesn't
39 // raise an interrupt. We would simply wait forever for more data, or rather we would time out and the host
40 // would move on and send the next Setup packet.
41 // The reason why we would not want to implement the proper behaviour is this: After having primed the TX fifo
42 // with a ZLP, it is impossible for a user to reject such a (class/vendor specific) Setup request, basically
43 // because the successful status stage happens automatically. At the time the user has received and decoded
44 // the Setup request there's for her no way to stall Ep0 in order to show to the host that this Setup packet
45 // is invalid or inappropriate or whatever, because she cannot prevent the status stage from happening.
46 // (All this is strictly true only if the amount of data in the data stage is less than or equal to Ep0's max
47 // packet size. However this is almost always the case.)
48 //#define USB_SUPPORTS_PREMATURE_STATUS_IN
51 static const TUsbcEndpointCaps DeviceEndpoints[KUsbTotalEndpoints] =
53 // Hardware # iEndpoints index
54 {KEp0MaxPktSzMask, (KUsbEpTypeControl | KUsbEpDirOut)}, // 0 - 0
55 {KEp0MaxPktSzMask, (KUsbEpTypeControl | KUsbEpDirIn )}, // 0 - 1
56 {KUsbEpNotAvailable, KUsbEpNotAvailable}, // --- Not present
57 {KBlkMaxPktSzMask, (KUsbEpTypeBulk | KUsbEpDirIn )}, // 1 - 3
58 {KBlkMaxPktSzMask, (KUsbEpTypeBulk | KUsbEpDirOut)}, // 2 - 4
59 {KUsbEpNotAvailable, KUsbEpNotAvailable}, // --- Not present
60 {KUsbEpNotAvailable, KUsbEpNotAvailable}, // --- Not present
61 {KIsoMaxPktSzMask, (KUsbEpTypeIsochronous | KUsbEpDirIn )}, // 3 - 7
62 {KIsoMaxPktSzMask, (KUsbEpTypeIsochronous | KUsbEpDirOut)}, // 4 - 8
63 {KUsbEpNotAvailable, KUsbEpNotAvailable}, // --- Not present
64 {KUsbEpNotAvailable, KUsbEpNotAvailable}, // --- Not present
65 {KIntMaxPktSzMask, (KUsbEpTypeInterrupt | KUsbEpDirIn )}, // 5 - 11
69 // --- TEndpoint --------------------------------------------------------------
71 TEndpoint::TEndpoint()
75 : iRxBuf(NULL), iReceived(0), iLength(0), iZlpReqd(EFalse), iNoBuffer(EFalse), iDisabled(EFalse),
76 iPackets(0), iLastError(KErrNone), iRequest(NULL), iRxTimer(RxTimerCallback, this),
77 iRxTimerSet(EFalse), iRxMoreDataRcvd(EFalse), iPacketIndex(NULL), iPacketSize(NULL)
79 __KTRACE_OPT(KUSB, Kern::Printf("TEndpoint::TEndpoint"));
83 void TEndpoint::RxTimerCallback(TAny* aPtr)
85 // (This function is static.)
88 __KTRACE_OPT(KUSB, Kern::Printf("TEndpoint::RxTimerCallback"));
90 TEndpoint* const ep = static_cast<TEndpoint*>(aPtr);
93 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: !ep"));
95 else if (!ep->iRxTimerSet)
97 // Timer 'stop' substitute (instead of stopping it,
98 // we just let it expire after clearing iRxTimerSet)
99 __KTRACE_OPT(KUSB, Kern::Printf("!ep->iRxTimerSet - returning"));
101 else if (!ep->iRxBuf)
103 // Request already completed
104 __KTRACE_OPT(KUSB, Kern::Printf("!ep->iRxBuf - returning"));
106 else if (ep->iRxMoreDataRcvd)
108 __KTRACE_OPT(KUSB, Kern::Printf(" > rx timer cb: not yet completing..."));
109 ep->iRxMoreDataRcvd = EFalse;
110 ep->iRxTimer.Again(KRxTimerTimeout);
114 __KTRACE_OPT(KUSB, Kern::Printf(" > rx timer cb: completing now..."));
115 *ep->iPacketSize = ep->iReceived;
116 ep->iController->RxComplete(ep);
121 // --- TTemplateAsspUsbcc public ---------------------------------------------------
123 TTemplateAsspUsbcc::TTemplateAsspUsbcc()
127 : iCableConnected(ETrue), iBusIsPowered(EFalse),
128 iInitialized(EFalse), iUsbClientConnectorCallback(UsbClientConnectorCallback),
129 iEp0Configured(EFalse)
131 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::TTemplateAsspUsbcc"));
133 iAssp = static_cast<TemplateAssp*>(Arch::TheAsic());
135 iSoftwareConnectable = iAssp->UsbSoftwareConnectable();
137 iCableDetectable = iAssp->UsbClientConnectorDetectable();
139 if (iCableDetectable)
141 // Register our callback for detecting USB cable insertion/removal.
142 // We ignore the error code: if the registration fails, we just won't get any events.
143 // (Which of course is bad enough...)
144 (void) iAssp->RegisterUsbClientConnectorCallback(iUsbClientConnectorCallback, this);
145 // Call the callback straight away so we get the proper PIL state from the beginning.
146 (void) UsbClientConnectorCallback(this);
149 for (TInt i = 0; i < KUsbTotalEndpoints; i++)
151 iEndpoints[i].iController = this;
156 TInt TTemplateAsspUsbcc::Construct()
161 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Construct"));
163 TUsbcDeviceDescriptor* DeviceDesc = TUsbcDeviceDescriptor::New(
164 0x00, // aDeviceClass
165 0x00, // aDeviceSubClass
166 0x00, // aDeviceProtocol
167 KEp0MaxPktSz, // aMaxPacketSize0
168 KUsbVendorId, // aVendorId
169 KUsbProductId, // aProductId
170 KUsbDevRelease, // aDeviceRelease
171 1); // aNumConfigurations
174 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Memory allocation for dev desc failed."));
178 TUsbcConfigDescriptor* ConfigDesc = TUsbcConfigDescriptor::New(
179 1, // aConfigurationValue
180 ETrue, // aSelfPowered (see 12.4.2 "Bus-Powered Devices")
181 ETrue, // aRemoteWakeup
182 0); // aMaxPower (mA)
185 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Memory allocation for config desc failed."));
189 TUsbcLangIdDescriptor* StringDescLang = TUsbcLangIdDescriptor::New(KUsbLangId);
192 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Memory allocation for lang id $ desc failed."));
196 // ('sizeof(x) - 2' because 'wchar_t KStringXyz' created a wide string that ends in '\0\0'.)
198 TUsbcStringDescriptor* StringDescManu =
199 TUsbcStringDescriptor::New(TPtr8(
200 const_cast<TUint8*>(reinterpret_cast<const TUint8*>(KStringManufacturer)),
201 sizeof(KStringManufacturer) - 2, sizeof(KStringManufacturer) - 2));
204 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Memory allocation for manufacturer $ desc failed."));
208 TUsbcStringDescriptor* StringDescProd =
209 TUsbcStringDescriptor::New(TPtr8(
210 const_cast<TUint8*>(reinterpret_cast<const TUint8*>(KStringProduct)),
211 sizeof(KStringProduct) - 2, sizeof(KStringProduct) - 2));
214 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Memory allocation for product $ desc failed."));
218 TUsbcStringDescriptor* StringDescSer =
219 TUsbcStringDescriptor::New(TPtr8(
220 const_cast<TUint8*>(reinterpret_cast<const TUint8*>(KStringSerialNo)),
221 sizeof(KStringSerialNo) - 2, sizeof(KStringSerialNo) - 2));
224 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Memory allocation for serial no $ desc failed."));
228 TUsbcStringDescriptor* StringDescConf =
229 TUsbcStringDescriptor::New(TPtr8(
230 const_cast<TUint8*>(reinterpret_cast<const TUint8*>(KStringConfig)),
231 sizeof(KStringConfig) - 2, sizeof(KStringConfig) - 2));
234 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Memory allocation for config $ desc failed."));
238 const TBool r = InitialiseBaseClass(DeviceDesc,
247 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: UsbClientController::InitialiseBaseClass failed."));
255 TTemplateAsspUsbcc::~TTemplateAsspUsbcc()
260 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::~TTemplateAsspUsbcc"));
262 // Unregister our callback for detecting USB cable insertion/removal
263 if (iCableDetectable)
265 iAssp->UnregisterUsbClientConnectorCallback();
269 // (The explicit scope operator is used against Lint warning #1506.)
270 TTemplateAsspUsbcc::StopUdc();
275 TBool TTemplateAsspUsbcc::DeviceStateChangeCaps() const
277 // Returns capability of hardware to accurately track the device state (Chapter 9 state).
280 // TO DO: Return EFalse or ETrue here, depending on whether the UDC supports exact device state tracking
286 TInt TTemplateAsspUsbcc::SignalRemoteWakeup()
288 // Forces the UDC into a non-idle state to perform a remote wakeup operation.
291 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SignalRemoteWakeup"));
293 // TO DO: Do here whatever is necessary for the UDC to signal remote wakeup.
299 void TTemplateAsspUsbcc::DumpRegisters()
301 // Dumps the contents of a number of UDC registers to the screen (using Kern::Printf()).
302 // Rarely used, but might prove helpful when needed.
305 Kern::Printf("TCotullaUsbcc::DumpRegisters:");
307 // TO DO: Print the contents of some (or all) UDC registers here.
311 TDfcQue* TTemplateAsspUsbcc::DfcQ(TInt /* aUnit */)
313 // Returns a pointer to the kernel DFC queue to be used buy the USB LDD.
316 return Kern::DfcQue0();
320 // --- TTemplateAsspUsbcc private virtual ------------------------------------------
322 TInt TTemplateAsspUsbcc::SetDeviceAddress(TInt aAddress)
324 // Sets the PIL-provided device address manually (if possible - otherwise do nothing).
327 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SetDeviceAddress: %d", aAddress));
329 // TO DO (optional): Set device address here.
333 // Address can be zero.
334 MoveToAddressState();
341 TInt TTemplateAsspUsbcc::ConfigureEndpoint(TInt aRealEndpoint, const TUsbcEndpointInfo& aEndpointInfo)
343 // Prepares (enables) an endpoint (incl. Ep0) for data transmission or reception.
346 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::ConfigureEndpoint(%d)", aRealEndpoint));
348 const TInt n = ArrayIdx2TemplateEp(aRealEndpoint);
352 TEndpoint* const ep = &iEndpoints[aRealEndpoint];
353 if (ep->iDisabled == EFalse)
355 EnableEndpointInterrupt(n);
357 ep->iNoBuffer = EFalse;
359 iEp0Configured = ETrue;
365 TInt TTemplateAsspUsbcc::DeConfigureEndpoint(TInt aRealEndpoint)
367 // Disables an endpoint (incl. Ep0).
370 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::DeConfigureEndpoint(%d)", aRealEndpoint));
372 const TInt n = ArrayIdx2TemplateEp(aRealEndpoint);
376 DisableEndpointInterrupt(n);
378 iEp0Configured = EFalse;
384 TInt TTemplateAsspUsbcc::AllocateEndpointResource(TInt aRealEndpoint, TUsbcEndpointResource aResource)
386 // Puts the requested endpoint resource to use, if possible.
389 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::AllocateEndpointResource(%d): %d",
390 aRealEndpoint, aResource));
392 // TO DO: Allocate endpoint resource here.
398 TInt TTemplateAsspUsbcc::DeAllocateEndpointResource(TInt aRealEndpoint, TUsbcEndpointResource aResource)
400 // Stops the use of the indicated endpoint resource, if beneficial.
403 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::DeAllocateEndpointResource(%d): %d",
404 aRealEndpoint, aResource));
406 // TO DO: Deallocate endpoint resource here.
412 TBool TTemplateAsspUsbcc::QueryEndpointResource(TInt aRealEndpoint, TUsbcEndpointResource aResource) const
414 // Returns the status of the indicated resource and endpoint.
417 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::QueryEndpointResource(%d): %d",
418 aRealEndpoint, aResource));
420 // TO DO: Query endpoint resource here. The return value should reflect the actual state.
425 TInt TTemplateAsspUsbcc::OpenDmaChannel(TInt aRealEndpoint)
427 // Opens a DMA channel for this endpoint. This function is always called during the creation of an endpoint
428 // in the PIL. If DMA channels are a scarce resource, it's possible to do nothing here and wait for an
429 // AllocateEndpointResource call instead.
432 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::OpenDmaChannel(%d)", aRealEndpoint));
434 // TO DO (optional): Open DMA channel here.
436 // An error should only be returned in case of an actual DMA problem.
441 void TTemplateAsspUsbcc::CloseDmaChannel(TInt aRealEndpoint)
443 // Closes a DMA channel for this endpoint. This function is always called during the destruction of an
444 // endpoint in the PIL.
447 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::CloseDmaChannel(%d)", aRealEndpoint));
449 // TO DO (optional): Close DMA channel here (only if it was opened via OpenDmaChannel).
453 TInt TTemplateAsspUsbcc::SetupEndpointRead(TInt aRealEndpoint, TUsbcRequestCallback& aCallback)
455 // Sets up a read request for an endpoint on behalf of the LDD.
458 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SetupEndpointRead(%d)", aRealEndpoint));
460 if (!IS_OUT_ENDPOINT(aRealEndpoint))
462 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: !IS_OUT_ENDPOINT(%d)", aRealEndpoint));
465 TEndpoint* const ep = &iEndpoints[aRealEndpoint];
466 if (ep->iRxBuf != NULL)
468 __KTRACE_OPT(KUSB, Kern::Printf(" > WARNING: iEndpoints[%d].iRxBuf != NULL", aRealEndpoint));
471 ep->iRxBuf = aCallback.iBufferStart;
473 ep->iLength = aCallback.iLength;
474 // For Bulk reads we start out with the assumption of 1 packet (see BulkReceive for why):
475 ep->iPackets = IS_BULK_OUT_ENDPOINT(aRealEndpoint) ? 1 : 0;
476 ep->iRequest = &aCallback;
477 ep->iPacketIndex = aCallback.iPacketIndex;
478 if (IS_BULK_OUT_ENDPOINT(aRealEndpoint))
479 *ep->iPacketIndex = 0; // a one-off optimization
480 ep->iPacketSize = aCallback.iPacketSize;
482 const TInt n = ArrayIdx2TemplateEp(aRealEndpoint);
485 ep->iDisabled = EFalse;
486 EnableEndpointInterrupt(n);
488 else if (ep->iNoBuffer)
490 __KTRACE_OPT(KUSB, Kern::Printf(" > There had been no Rx buffer available: reading Rx FIFO now"));
491 ep->iNoBuffer = EFalse;
492 if (IS_BULK_OUT_ENDPOINT(aRealEndpoint))
496 else if (IS_ISO_OUT_ENDPOINT(aRealEndpoint))
502 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint not found"));
510 TInt TTemplateAsspUsbcc::SetupEndpointWrite(TInt aRealEndpoint, TUsbcRequestCallback& aCallback)
512 // Sets up a write request for an endpoint on behalf of the LDD.
515 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SetupEndpointWrite(%d)", aRealEndpoint));
517 if (!IS_IN_ENDPOINT(aRealEndpoint))
519 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: !IS_IN_ENDPOINT(%d)", aRealEndpoint));
522 TEndpoint* const ep = &iEndpoints[aRealEndpoint];
523 if (ep->iTxBuf != NULL)
525 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: iEndpoints[%d].iTxBuf != NULL", aRealEndpoint));
528 ep->iTxBuf = aCallback.iBufferStart;
529 ep->iTransmitted = 0;
530 ep->iLength = aCallback.iLength;
532 ep->iZlpReqd = aCallback.iZlpReqd;
533 ep->iRequest = &aCallback;
535 const TInt n = ArrayIdx2TemplateEp(aRealEndpoint);
536 if (IS_BULK_IN_ENDPOINT(aRealEndpoint))
540 ep->iDisabled = EFalse;
541 EnableEndpointInterrupt(n);
545 else if (IS_ISO_IN_ENDPOINT(aRealEndpoint))
549 else if (IS_INT_IN_ENDPOINT(aRealEndpoint))
555 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint not found"));
562 TInt TTemplateAsspUsbcc::CancelEndpointRead(TInt aRealEndpoint)
564 // Cancels a read request for an endpoint on behalf of the LDD.
565 // No completion to the PIL occurs.
568 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::CancelEndpointRead(%d)", aRealEndpoint));
570 if (!IS_OUT_ENDPOINT(aRealEndpoint))
572 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: !IS_OUT_ENDPOINT(%d)", aRealEndpoint));
575 TEndpoint* const ep = &iEndpoints[aRealEndpoint];
576 if (ep->iRxBuf == NULL)
578 __KTRACE_OPT(KUSB, Kern::Printf(" > WARNING: iEndpoints[%d].iRxBuf == NULL", aRealEndpoint));
583 ep->iNoBuffer = EFalse;
589 TInt TTemplateAsspUsbcc::CancelEndpointWrite(TInt aRealEndpoint)
591 // Cancels a write request for an endpoint on behalf of the LDD.
592 // No completion to the PIL occurs.
595 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::CancelEndpointWrite(%d)", aRealEndpoint));
597 if (!IS_IN_ENDPOINT(aRealEndpoint))
599 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: !IS_IN_ENDPOINT(%d)", aRealEndpoint));
602 TEndpoint* const ep = &iEndpoints[aRealEndpoint];
603 if (ep->iTxBuf == NULL)
605 __KTRACE_OPT(KUSB, Kern::Printf(" > WARNING: iEndpoints[%d].iTxBuf == NULL", aRealEndpoint));
609 // TO DO (optional): Flush the Ep's Tx FIFO here, if possible.
612 ep->iTransmitted = 0;
613 ep->iNoBuffer = EFalse;
619 TInt TTemplateAsspUsbcc::SetupEndpointZeroRead()
621 // Sets up an Ep0 read request (own function due to Ep0's special status).
624 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SetupEndpointZeroRead"));
626 TEndpoint* const ep = &iEndpoints[KEp0_Out];
627 if (ep->iRxBuf != NULL)
629 __KTRACE_OPT(KUSB, Kern::Printf(" > WARNING: iEndpoints[%d].iRxBuf != NULL", KEp0_Out));
632 ep->iRxBuf = iEp0_RxBuf;
639 TInt TTemplateAsspUsbcc::SetupEndpointZeroWrite(const TUint8* aBuffer, TInt aLength, TBool aZlpReqd)
641 // Sets up an Ep0 write request (own function due to Ep0's special status).
644 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SetupEndpointZeroWrite"));
646 TEndpoint* const ep = &iEndpoints[KEp0_In];
647 if (ep->iTxBuf != NULL)
649 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: iEndpoints[%d].iTxBuf != NULL", KEp0_In));
652 ep->iTxBuf = aBuffer;
653 ep->iTransmitted = 0;
654 ep->iLength = aLength;
655 ep->iZlpReqd = aZlpReqd;
663 TInt TTemplateAsspUsbcc::SendEp0ZeroByteStatusPacket()
665 // Sets up an Ep0 write request for zero bytes.
666 // This is a separate function because no data transfer is involved here.
669 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SendEp0ZeroByteStatusPacket"));
671 // This is possibly a bit tricky. When this function is called it just means that the higher layer wants a
672 // ZLP to be sent. Whether we actually send one manually here depends on a number of factors, as the
673 // current Ep0 state (i.e. the stage of the Ep0 Control transfer), and, in case the hardware handles some
674 // ZLPs itself, whether it might already handle this one.
676 // Here is an example of what the checking of the conditions might look like:
678 #ifndef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST
679 if ((!iEp0ReceivedNonStdRequest && iEp0State == EP0_IN_DATA_PHASE) ||
681 if ((!iEp0ReceivedNonStdRequest && iEp0State != EP0_IDLE) ||
683 #ifdef USB_SUPPORTS_PREMATURE_STATUS_IN
684 (iEp0ReceivedNonStdRequest && iEp0State != EP0_OUT_DATA_PHASE))
686 (iEp0ReceivedNonStdRequest))
689 // TO DO: Arrange for the sending of a ZLP here.
696 TInt TTemplateAsspUsbcc::StallEndpoint(TInt aRealEndpoint)
698 // Stalls an endpoint.
701 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::StallEndpoint(%d)", aRealEndpoint));
703 if (IS_ISO_ENDPOINT(aRealEndpoint))
705 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Iso endpoint cannot be stalled"));
709 // TO DO: Stall the endpoint here.
715 TInt TTemplateAsspUsbcc::ClearStallEndpoint(TInt aRealEndpoint)
717 // Clears the stall condition of an endpoint.
720 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::ClearStallEndpoint(%d)", aRealEndpoint));
722 if (IS_ISO_ENDPOINT(aRealEndpoint))
724 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Iso endpoint cannot be unstalled"));
728 // TO DO: De-stall the endpoint here.
734 TInt TTemplateAsspUsbcc::EndpointStallStatus(TInt aRealEndpoint) const
736 // Reports the stall status of an endpoint.
739 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::EndpointStallStatus(%d)", aRealEndpoint));
741 if (IS_ISO_ENDPOINT(aRealEndpoint))
743 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Iso endpoint has no stall status"));
747 // TO DO: Query endpoint stall status here. The return value should reflect the actual state.
752 TInt TTemplateAsspUsbcc::EndpointErrorStatus(TInt aRealEndpoint) const
754 // Reports the error status of an endpoint.
757 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::EndpointErrorStatus(%d)", aRealEndpoint));
759 if (!IS_VALID_ENDPOINT(aRealEndpoint))
761 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: !IS_VALID_ENDPOINT(%d)", aRealEndpoint));
765 // TO DO: Query endpoint error status here. The return value should reflect the actual state.
766 // With some UDCs there is no way of inquiring the endpoint error status; say 'ETrue' in that case.
771 TInt TTemplateAsspUsbcc::ResetDataToggle(TInt aRealEndpoint)
773 // Resets to zero the data toggle bit of an endpoint.
776 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::ResetDataToggle(%d)", aRealEndpoint));
778 // TO DO: Reset the endpoint's data toggle bit here.
779 // With some UDCs there is no way to individually reset the endpoint's toggle bits; just return KErrNone
786 TInt TTemplateAsspUsbcc::SynchFrameNumber() const
788 // For use with isochronous endpoints only. Causes the SOF frame number to be returned.
791 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SynchFrameNumber"));
793 // TO DO: Query and return the SOF frame number here.
798 void TTemplateAsspUsbcc::SetSynchFrameNumber(TInt aFrameNumber)
800 // For use with isochronous endpoints only. Causes the SOF frame number to be stored.
803 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SetSynchFrameNumber(%d)", aFrameNumber));
805 // We should actually store this number somewhere. But the PIL always sends '0x00'
806 // in response to a SYNCH_FRAME request...
807 // TO DO: Store the frame number. Alternatively (until SYNCH_FRAME request specification changes): Do
812 TInt TTemplateAsspUsbcc::StartUdc()
814 // Called to initialize the device controller hardware before any operation can be performed.
817 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::StartUdc"));
821 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: UDC already initialised"));
825 // Disable UDC (might also reset the entire design):
828 // Enable UDC's clock:
829 // TO DO: Enable UDC's clock here.
831 // Even if only one USB feature has been enabled, we later need to undo it:
832 iInitialized = ETrue;
834 // Bind & enable the UDC interrupt
835 if (SetupUdcInterrupt() != KErrNone)
840 // Write meaningful values to some registers:
841 InitialiseUdcRegisters();
843 // Finally, turn on the UDC:
850 TInt TTemplateAsspUsbcc::StopUdc()
852 // Basically, makes undone what happened in StartUdc.
855 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::StopUdc"));
859 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: UDC not initialized"));
866 // Mask (disable) Reset interrupt:
867 // TO DO: Mask (disable) the USB Reset interrupt here.
869 // Disable & unbind the UDC interrupt:
870 ReleaseUdcInterrupt();
872 // Finally turn off UDC's clock:
873 // TO DO: Disable UDC's clock here.
875 // Only when all USB features have been disabled we'll call it a day:
876 iInitialized = EFalse;
882 TInt TTemplateAsspUsbcc::UdcConnect()
884 // Connects the UDC to the bus under software control. How this is achieved depends on the UDC; the
885 // functionality might also be part of the Variant component (instead of the ASSP).
888 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::UdcConnect"));
890 // Here: A call into the Variant-provided function.
891 return iAssp->UsbConnect();
895 TInt TTemplateAsspUsbcc::UdcDisconnect()
897 // Disconnects the UDC from the bus under software control. How this is achieved depends on the UDC; the
898 // functionality might also be part of the Variant component (instead of the ASSP).
901 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::UdcDisconnect"));
903 // Here: A call into the Variant-provided function.
904 return iAssp->UsbDisconnect();
908 TBool TTemplateAsspUsbcc::UsbConnectionStatus() const
910 // Returns a value showing the USB cable connection status of the device.
913 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::UsbConnectionStatus"));
915 return iCableConnected;
919 TBool TTemplateAsspUsbcc::UsbPowerStatus() const
921 // Returns a truth value showing whether VBUS is currently powered or not.
924 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::UsbPowerStatus"));
926 return iBusIsPowered;
930 TBool TTemplateAsspUsbcc::DeviceSelfPowered() const
932 // Returns a truth value showing whether the device is currently self-powered or not.
935 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::DeviceSelfPowered"));
937 // TO DO: Query and return self powered status here. The return value should reflect the actual state.
938 // (This can be always 'ETrue' if the UDC does not support bus-powered devices.)
943 const TUsbcEndpointCaps* TTemplateAsspUsbcc::DeviceEndpointCaps() const
945 // Returns a pointer to an array of elements, each of which describes the capabilities of one endpoint.
948 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::DeviceEndpointCaps"));
949 __KTRACE_OPT(KUSB, Kern::Printf(" > Ep: Sizes Mask, Types Mask"));
950 __KTRACE_OPT(KUSB, Kern::Printf(" > --------------------------"));
951 for (TInt i = 0; i < KUsbTotalEndpoints; ++i)
953 __KTRACE_OPT(KUSB, Kern::Printf(" > %02d: 0x%08x, 0x%08x",
954 i, DeviceEndpoints[i].iSizes, DeviceEndpoints[i].iTypesAndDir));
956 return DeviceEndpoints;
960 TInt TTemplateAsspUsbcc::DeviceTotalEndpoints() const
962 // Returns the element number of the endpoints array a pointer to which is returned by DeviceEndpointCaps.
965 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::DeviceTotalEndpoints"));
967 return KUsbTotalEndpoints;
971 TBool TTemplateAsspUsbcc::SoftConnectCaps() const
973 // Returns a truth value showing whether or not there is the capability to disconnect and re-connect the D+
974 // line under software control.
977 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SoftConnectCaps"));
979 return iSoftwareConnectable;
983 void TTemplateAsspUsbcc::Suspend()
985 // Called by the PIL after a Suspend event has been reported (by us).
988 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Suspend"));
990 // TO DO (optional): Implement here anything the device might require after bus SUSPEND signalling.
994 void TTemplateAsspUsbcc::Resume()
996 // Called by the PIL after a Resume event has been reported (by us).
999 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Resume"));
1001 // TO DO (optional): Implement here anything the device might require after bus RESUME signalling.
1005 void TTemplateAsspUsbcc::Reset()
1007 // Called by the PIL after a Reset event has been reported (by us).
1010 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Reset"));
1012 // This does not really belong here, but has to do with the way the PIL sets
1013 // up Ep0 reads and writes.
1014 TEndpoint* ep = &iEndpoints[0];
1019 Ep0NextState(EP0_IDLE);
1021 // TO DO (optional): Implement here anything the device might require after bus RESET signalling.
1023 // Write meaningful values to some registers
1024 InitialiseUdcRegisters();
1027 EnableEndpointInterrupt(0);
1031 // --- TTemplateAsspUsbcc private --------------------------------------------------
1033 void TTemplateAsspUsbcc::InitialiseUdcRegisters()
1035 // Called after every USB Reset etc.
1038 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::InitialiseUdcRegisters"));
1040 // Unmask Suspend interrupt
1041 // TO DO: Unmask Suspend interrupt here.
1043 // Unmask Resume interrupt
1044 // TO DO: Unmask Resume interrupt here.
1046 // Unmask Start-of-Frame (SOF) interrupt
1047 // TO DO (optional): Unmask SOF interrupt here.
1049 // Disable interrupt requests for all endpoints
1050 // TO DO: Disable interrupt requests for all endpoints here.
1054 void TTemplateAsspUsbcc::UdcEnable()
1056 // Enables the UDC for USB transmission or reception.
1059 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::UdcEnable"));
1061 // TO DO: Do whatever is necessary to enable the UDC here. This might include enabling (unmasking)
1062 // the USB Reset interrupt, setting a UDC enable bit, etc.
1066 void TTemplateAsspUsbcc::UdcDisable()
1068 // Disables the UDC.
1071 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::UdcDisable"));
1073 // TO DO: Do whatever is necessary to disable the UDC here. This might include disabling (masking)
1074 // the USB Reset interrupt, clearing a UDC enable bit, etc.
1078 void TTemplateAsspUsbcc::EnableEndpointInterrupt(TInt aEndpoint)
1080 // Enables interrupt requests for an endpoint.
1083 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::EnableEndpointInterrupt(%d)", aEndpoint));
1085 // Enable (unmask) interrupt requests for this endpoint:
1086 // TO DO: Enable interrupt requests for aEndpoint here.
1090 void TTemplateAsspUsbcc::DisableEndpointInterrupt(TInt aEndpoint)
1092 // Disables interrupt requests for an endpoint.
1095 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::DisableEndpointInterrupt(%d)", aEndpoint));
1097 // Disable (mask) interrupt requests for this endpoint:
1098 // TO DO: Disable interrupt requests for aEndpoint here.
1102 void TTemplateAsspUsbcc::ClearEndpointInterrupt(TInt aEndpoint)
1104 // Clears a pending interrupt request for an endpoint.
1107 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::ClearEndpointInterrupt(%d)", aEndpoint));
1109 // Clear (reset) pending interrupt request for this endpoint:
1110 // TO DO: Clear interrupt request for aEndpoint here.
1114 void TTemplateAsspUsbcc::Ep0IntService()
1116 // ISR for endpoint zero interrupt.
1119 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0IntService"));
1121 // TO DO: Enquire about Ep0 status & the interrupt cause here. Depending on the event and the Ep0 state,
1122 // one or more of the following functions might then be called:
1126 Ep0PrematureStatusOut();
1130 ClearStallEndpoint(0);
1132 ClearEndpointInterrupt(0);
1137 void TTemplateAsspUsbcc::Ep0ReadSetupPkt()
1139 // Called from the Ep0 ISR when a new Setup packet has been received.
1142 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0ReadSetupPkt"));
1144 TEndpoint* const ep = &iEndpoints[KEp0_Out];
1145 TUint8* buf = ep->iRxBuf;
1148 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: No Ep0 Rx buffer available (1)"));
1149 StallEndpoint(KEp0_Out);
1153 // TO DO: Read Setup packet data from Rx FIFO into 'buf' here.
1154 // (In this function we don't need to use "ep->iReceived" since Setup packets
1155 // are always 8 bytes long.)
1157 // Upcall into PIL to determine next Ep0 state:
1158 TUsbcEp0State state = EnquireEp0NextState(ep->iRxBuf);
1160 if (state == EEp0StateStatusIn)
1162 Ep0NextState(EP0_IDLE); // Ep0 No Data
1164 else if (state == EEp0StateDataIn)
1166 Ep0NextState(EP0_IN_DATA_PHASE); // Ep0 Control Read
1170 Ep0NextState(EP0_OUT_DATA_PHASE); // Ep0 Control Write
1174 const TInt r = Ep0RequestComplete(KEp0_Out, 8, KErrNone);
1176 // Don't finish (proceed) if request completion returned 'KErrNotFound'!
1177 if (!(r == KErrNone || r == KErrGeneral))
1179 DisableEndpointInterrupt(0);
1182 // TO DO (optional): Clear Ep0 Setup condition flags here.
1184 #ifdef USB_SUPPORTS_PREMATURE_STATUS_IN
1185 if (iEp0State == EP0_OUT_DATA_PHASE)
1187 // Allow for a premature STATUS IN
1188 // TO DO: Arrange for the sending of a ZLP here.
1194 void TTemplateAsspUsbcc::Ep0ReadSetupPktProceed()
1196 // Called by the PIL to signal that it has finished processing a received Setup packet and that the PSL can
1197 // now prepare itself for the next Ep0 reception (for instance by re-enabling the Ep0 interrupt).
1200 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0ReadSetupPktProceed"));
1202 EnableEndpointInterrupt(0);
1206 void TTemplateAsspUsbcc::Ep0Receive()
1208 // Called from the Ep0 ISR when a data packet has been received.
1211 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0Receive"));
1213 TEndpoint* const ep = &iEndpoints[KEp0_Out];
1214 TUint8* buf = ep->iRxBuf;
1217 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: No Ep0 Rx buffer available (2)"));
1218 StallEndpoint(KEp0_Out);
1223 // TO DO: Read packet data from Rx FIFO into 'buf' and update 'n' (# of received bytes) here.
1227 const TInt r = Ep0RequestComplete(KEp0_Out, n, KErrNone);
1229 // Don't finish (proceed) if request was 'KErrNotFound'!
1230 if (!(r == KErrNone || r == KErrGeneral))
1232 DisableEndpointInterrupt(0);
1235 // TO DO (optional): Clear Ep0 Rx condition flags here.
1237 #ifdef USB_SUPPORTS_PREMATURE_STATUS_IN
1238 // Allow for a premature STATUS IN
1239 // TO DO: Arrange for the sending of a ZLP here.
1244 void TTemplateAsspUsbcc::Ep0ReceiveProceed()
1246 // Called by the PIL to signal that it has finished processing a received Ep0 data packet and that the PSL can
1247 // now prepare itself for the next Ep0 reception (for instance by re-enabling the Ep0 interrupt).
1250 Ep0ReadSetupPktProceed();
1254 void TTemplateAsspUsbcc::Ep0Transmit()
1256 // Called from either the Ep0 ISR or the PIL when a data packet has been or is to be transmitted.
1259 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0Transmit"));
1261 if (iEp0State != EP0_IN_DATA_PHASE)
1263 __KTRACE_OPT(KUSB, Kern::Printf(" > WARNING: Invalid Ep0 state when trying to handle EP0 IN"));
1264 // TO DO (optional): Do something about this warning.
1267 TEndpoint* const ep = &iEndpoints[KEp0_In];
1268 const TUint8* buf = ep->iTxBuf;
1271 __KTRACE_OPT(KUSB, Kern::Printf(" > No Tx buffer available: returning"));
1274 const TInt t = ep->iTransmitted; // already transmitted
1276 TInt n = 0; // now transmitted
1278 // TO DO: Write packet data (if any) into Tx FIFO from 'buf' and update 'n' (# of tx'ed bytes) here.
1280 ep->iTransmitted += n;
1282 // coverity[dead_error_condition]
1283 // The next line should be reachable when this template file is edited for use
1284 if (n == KEp0MaxPktSz)
1286 if (ep->iTransmitted == ep->iLength && !(ep->iZlpReqd))
1287 Ep0NextState(EP0_END_XFER);
1289 else if (n && n != KEp0MaxPktSz)
1291 // Send off the data
1292 __ASSERT_DEBUG((ep->iTransmitted == ep->iLength),
1293 Kern::Printf(" > ERROR: Short packet in mid-transfer"));
1294 Ep0NextState(EP0_END_XFER);
1295 // TO DO: Send off the data here.
1299 __ASSERT_DEBUG((ep->iTransmitted == ep->iLength),
1300 Kern::Printf(" > ERROR: Nothing transmitted but still not finished"));
1303 // Send a zero length packet
1304 ep->iZlpReqd = EFalse;
1305 Ep0NextState(EP0_END_XFER);
1306 // TO DO: Arrange for the sending of a ZLP here.
1310 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: nothing transmitted & no ZLP req'd"));
1316 void TTemplateAsspUsbcc::Ep0EndXfer()
1318 // Called at the end of a Ep0 Control transfer.
1321 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0EndXfer"));
1323 // TO DO (optional): Clear Ep0 Rx condition flags here.
1325 Ep0NextState(EP0_IDLE);
1326 TEndpoint* const ep = &iEndpoints[KEp0_In];
1328 (void) Ep0RequestComplete(KEp0_In, ep->iTransmitted, KErrNone);
1332 void TTemplateAsspUsbcc::Ep0Cancel()
1334 // Called when an ongoing Ep0 Control transfer has to be aborted prematurely (for instance when receiving a
1335 // new Setup packet before the processing of the old one has completed).
1338 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0Cancel"));
1340 Ep0NextState(EP0_IDLE);
1341 TEndpoint* const ep = &iEndpoints[KEp0_In];
1345 const TInt err = (ep->iTransmitted == ep->iLength) ? KErrNone : KErrCancel;
1346 (void) Ep0RequestComplete(KEp0_In, ep->iTransmitted, err);
1351 void TTemplateAsspUsbcc::Ep0PrematureStatusOut()
1353 // Called when an ongoing Ep0 Control transfer encounters a premature Status OUT condition.
1356 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0PrematureStatusOut"));
1358 // TO DO (optional): Clear Ep0 Rx condition flags here.
1360 Ep0NextState(EP0_IDLE);
1362 // TO DO (optional): Flush the Ep0 Tx FIFO here, if possible.
1364 TEndpoint* const ep = &iEndpoints[KEp0_In];
1368 (void) Ep0RequestComplete(KEp0_In, ep->iTransmitted, KErrPrematureEnd);
1373 void TTemplateAsspUsbcc::Ep0StatusIn()
1375 // Called when an ongoing Ep0 Control transfer moves to a Status IN stage.
1378 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0StatusIn"));
1380 Ep0NextState(EP0_IDLE);
1384 void TTemplateAsspUsbcc::BulkTransmit(TInt aEndpoint)
1386 // Endpoint 1 (BULK IN).
1387 // Called from either the Ep ISR or the PIL when a data packet has been or is to be transmitted.
1390 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::BulkTransmit(%d)", aEndpoint));
1392 // TO DO: Enquire about Ep status here.
1394 const TInt idx = 3; // only in our special case of course!
1395 TEndpoint* const ep = &iEndpoints[idx];
1396 const TUint8* buf = ep->iTxBuf;
1399 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: No Tx buffer has been set up"));
1400 DisableEndpointInterrupt(aEndpoint);
1401 ep->iDisabled = ETrue;
1402 ClearEndpointInterrupt(aEndpoint);
1405 const TInt t = ep->iTransmitted; // already transmitted
1406 const TInt len = ep->iLength; // to be sent in total
1407 // (len || ep->iPackets): Don't complete for a zero bytes request straight away.
1408 if (t >= len && (len || ep->iPackets))
1412 __KTRACE_OPT(KUSB, Kern::Printf(" > 'Transmit Short Packet' explicitly"));
1413 // TO DO: Arrange for the sending of a ZLP here.
1414 ep->iZlpReqd = EFalse;
1418 __KTRACE_OPT(KUSB, Kern::Printf(" > All data sent: %d --> completing", len));
1420 ep->iRequest->iTxBytes = ep->iTransmitted;
1421 ep->iRequest->iError = KErrNone;
1422 EndpointRequestComplete(ep->iRequest);
1423 ep->iRequest = NULL;
1429 TInt left = len - t; // left in total
1430 TInt n = (left >= KBlkMaxPktSz) ? KBlkMaxPktSz : left; // now to be transmitted
1431 __KTRACE_OPT(KUSB, Kern::Printf(" > About to send %d bytes (%d bytes left in total)", n, left));
1433 // TO DO: Write data into Tx FIFO from 'buf' here.
1435 ep->iTransmitted += n;
1436 ep->iPackets++; // only used for (len == 0) case
1437 left -= n; // (still) left in total
1438 if (n < KBlkMaxPktSz)
1440 __KTRACE_OPT(KUSB, Kern::Printf(" > 'Transmit Short Packet' implicitly"));
1441 // TO DO: Arrange for the sending of a ZLP here.
1442 ep->iZlpReqd = EFalse;
1444 // If double-buffering is available, it might be possible to stick a second packet
1445 // into the FIFO here.
1447 // TO DO (optional): Send another packet if possible (& available) here.
1450 ClearEndpointInterrupt(aEndpoint);
1455 void TTemplateAsspUsbcc::BulkReceive(TInt aEndpoint)
1457 // Endpoint 2 (BULK OUT) (This one is called in an ISR.)
1460 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::BulkReceive(%d)", aEndpoint));
1462 // TO DO: Enquire about Ep status here.
1463 const TUint32 status = *(TUint32*)0xdefaced; // bogus
1465 const TInt idx = 4; // only in our special case of course!
1466 TEndpoint* const ep = &iEndpoints[idx];
1467 TUint8* buf = ep->iRxBuf;
1470 __KTRACE_OPT(KUSB, Kern::Printf(" > No Rx buffer available: setting iNoBuffer"));
1471 ep->iNoBuffer = ETrue;
1472 DisableEndpointInterrupt(aEndpoint);
1473 ep->iDisabled = ETrue;
1474 ClearEndpointInterrupt(aEndpoint);
1478 const TInt r = ep->iReceived; // already received
1479 // TO DO: Check whether a ZLP was received here:
1480 if (status & 1) // some condition
1482 __KTRACE_OPT(KUSB, Kern::Printf(" > received zero-length packet"));
1484 else if (status & 2) // some other condition
1486 // TO DO: Get number of bytes received here.
1487 bytes = *(TUint32*)0xdadadada; // bogus
1488 __KTRACE_OPT(KUSB, Kern::Printf(" > Bulk received: %d bytes", bytes));
1489 if (r + bytes > ep->iLength)
1491 __KTRACE_OPT(KUSB, Kern::Printf(" > not enough space in rx buffer: setting iNoBuffer"));
1492 ep->iNoBuffer = ETrue;
1494 *ep->iPacketSize = ep->iReceived;
1497 // TO DO (optional): Clear Ep Rx condition flags here.
1499 ClearEndpointInterrupt(aEndpoint);
1502 buf += r; // set buffer pointer
1504 // TO DO: Read 'bytes' bytes from Rx FIFO into 'buf' here.
1506 ep->iReceived += bytes;
1510 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Inconsistent Ep%d state", aEndpoint));
1512 // TO DO (optional): Clear Ep Rx condition flags here.
1514 ClearEndpointInterrupt(aEndpoint);
1520 // ZLPs must be recorded separately
1521 const TInt i = ep->iReceived ? 1 : 0;
1522 ep->iPacketIndex[i] = r;
1523 ep->iPacketSize[i] = 0;
1524 // If there were data packets before: total packets reported 1 -> 2
1528 if ((bytes < KBlkMaxPktSz) ||
1529 (ep->iReceived == ep->iLength))
1532 *ep->iPacketSize = ep->iReceived;
1534 // since we have no buffer any longer we disable interrupts:
1535 DisableEndpointInterrupt(aEndpoint);
1536 ep->iDisabled = ETrue;
1540 if (!ep->iRxTimerSet)
1542 __KTRACE_OPT(KUSB, Kern::Printf(" > setting rx timer"));
1543 ep->iRxTimerSet = ETrue;
1544 ep->iRxTimer.OneShot(KRxTimerTimeout);
1548 ep->iRxMoreDataRcvd = ETrue;
1552 // TO DO (optional): Clear Ep Rx condition flags here.
1554 ClearEndpointInterrupt(aEndpoint);
1558 void TTemplateAsspUsbcc::BulkReadRxFifo(TInt aEndpoint)
1560 // Endpoint 2 (BULK OUT) (This one is called w/o interrupt to be served.)
1563 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::BulkReadRxFifo(%d)", aEndpoint));
1565 // TO DO: Enquire about Ep status here.
1566 const TUint32 status = *(TUint32*)0xdefaced; // bogus
1568 const TInt idx = 4; // only in our special case of course!
1569 TEndpoint* const ep = &iEndpoints[idx];
1570 TUint8* buf = ep->iRxBuf;
1573 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: No Rx buffer has been set up"));
1577 const TInt r = ep->iReceived; // already received
1578 // TO DO: Check whether a ZLP was received here:
1579 if (status & 1) // some condition
1581 __KTRACE_OPT(KUSB, Kern::Printf(" > received zero-length packet"));
1583 else if (status & 2) // some other condition
1585 // TO DO: Get number of bytes received here.
1586 bytes = *(TUint32*)0xdadadada; // bogus
1587 __KTRACE_OPT(KUSB, Kern::Printf(" > Bulk received: %d bytes", bytes));
1588 if (r + bytes > ep->iLength)
1590 __KTRACE_OPT(KUSB, Kern::Printf(" > not enough space in rx buffer: setting iNoBuffer"));
1591 ep->iNoBuffer = ETrue;
1592 *ep->iPacketSize = ep->iReceived;
1596 buf += r; // set buffer pointer
1598 // TO DO: Read 'bytes' bytes from Rx FIFO into 'buf' here.
1600 ep->iReceived += bytes;
1604 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Inconsistent Ep%d state", aEndpoint));
1610 // ZLPs must be recorded separately
1611 const TInt i = ep->iReceived ? 1 : 0;
1612 ep->iPacketIndex[i] = r;
1613 ep->iPacketSize[i] = 0;
1614 // If there were data packets before: total packets reported 1 -> 2
1618 if ((bytes < KBlkMaxPktSz) ||
1619 (ep->iReceived == ep->iLength))
1621 *ep->iPacketSize = ep->iReceived;
1626 if (!ep->iRxTimerSet)
1628 __KTRACE_OPT(KUSB, Kern::Printf(" > setting rx timer"));
1629 ep->iRxTimerSet = ETrue;
1630 ep->iRxTimer.OneShot(KRxTimerTimeout);
1634 ep->iRxMoreDataRcvd = ETrue;
1638 // TO DO (optional): Clear Ep Rx condition flags here.
1643 void TTemplateAsspUsbcc::IsoTransmit(TInt aEndpoint)
1645 // Endpoint 3 (ISOCHRONOUS IN).
1648 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::IsoTransmit(%d)", aEndpoint));
1650 // TO DO: Write data to endpoint FIFO. Might be similar to BulkTransmit.
1655 void TTemplateAsspUsbcc::IsoReceive(TInt aEndpoint)
1657 // Endpoint 4 (ISOCHRONOUS OUT) (This one is called in an ISR.)
1660 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::IsoReceive(%d)", aEndpoint));
1662 // TO DO: Read data from endpoint FIFO. Might be similar to BulkReceive.
1666 void TTemplateAsspUsbcc::IsoReadRxFifo(TInt aEndpoint)
1668 // Endpoint 4 (ISOCHRONOUS OUT) (This one is called w/o interrupt to be served.)
1671 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::IsoReadRxFifo(%d)", aEndpoint));
1673 // TO DO: Read data from endpoint FIFO. Might be similar to BulkReadRxFifo.
1677 void TTemplateAsspUsbcc::IntTransmit(TInt aEndpoint)
1679 // Endpoint 5 (INTERRUPT IN).
1682 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::IntTransmit(%d)", aEndpoint));
1684 // TO DO: Write data to endpoint FIFO. Might be similar to BulkTransmit.
1688 void TTemplateAsspUsbcc::RxComplete(TEndpoint* aEndpoint)
1690 // Called at the end of an Rx (OUT) transfer to complete to the PIL.
1693 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::RxComplete"));
1695 TUsbcRequestCallback* const req = aEndpoint->iRequest;
1697 __ASSERT_DEBUG((req != NULL), Kern::Fault(KUsbPanicCat, __LINE__));
1699 aEndpoint->iRxBuf = NULL;
1700 aEndpoint->iRxTimerSet = EFalse;
1701 aEndpoint->iRxMoreDataRcvd = EFalse;
1702 req->iRxPackets = aEndpoint->iPackets;
1703 req->iError = aEndpoint->iLastError;
1704 EndpointRequestComplete(req);
1705 aEndpoint->iRequest = NULL;
1709 void TTemplateAsspUsbcc::StopRxTimer(TEndpoint* aEndpoint)
1711 // Stops (cancels) the Rx timer for an endpoint.
1714 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::StopRxTimer"));
1716 if (aEndpoint->iRxTimerSet)
1718 __KTRACE_OPT(KUSB, Kern::Printf(" > stopping rx timer"));
1719 aEndpoint->iRxTimer.Cancel();
1720 aEndpoint->iRxTimerSet = EFalse;
1725 void TTemplateAsspUsbcc::EndpointIntService(TInt aEndpoint)
1727 // ISR for endpoint interrupts.
1728 // Note: the aEndpoint here is a "hardware endpoint", not a aRealEndpoint.
1731 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::EndpointIntService(%d)", aEndpoint));
1739 BulkTransmit(aEndpoint);
1742 BulkReceive(aEndpoint);
1745 IsoTransmit(aEndpoint);
1748 IsoReceive(aEndpoint);
1751 IntTransmit(aEndpoint);
1754 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint not found"));
1760 TInt TTemplateAsspUsbcc::ResetIntService()
1762 // ISR for a USB Reset event interrupt.
1763 // This function returns a value which can be used on the calling end to decide how to proceed.
1766 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::ResetIntService"));
1768 // Clear an interrupt:
1769 // TO DO: Clear reset interrupt flag here.
1771 // TO DO (optional): Enquire about special conditions and possibly return here.
1773 DeviceEventNotification(EUsbEventReset);
1779 void TTemplateAsspUsbcc::SuspendIntService()
1781 // ISR for a USB Suspend event interrupt.
1784 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SuspendIntService"));
1786 // Clear an interrupt:
1787 // TO DO: Clear suspend interrupt flag here.
1789 DeviceEventNotification(EUsbEventSuspend);
1793 void TTemplateAsspUsbcc::ResumeIntService()
1795 // ISR for a USB Resume event interrupt.
1798 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::ResumeIntService"));
1800 // Clear an interrupt:
1801 // TO DO: Clear resume interrupt flag here.
1803 DeviceEventNotification(EUsbEventResume);
1807 void TTemplateAsspUsbcc::SofIntService()
1809 // ISR for a USB Start-of-Frame event interrupt.
1812 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SofIntService"));
1814 // Clear an interrupt:
1815 // TO DO: Clear SOF interrupt flag here.
1817 // TO DO (optional): Do something about the SOF condition.
1821 void TTemplateAsspUsbcc::UdcInterruptService()
1823 // Main UDC ISR - determines the cause of the interrupt, clears the condition, dispatches further for service.
1826 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::InterruptService"));
1828 // TO DO: Find the cause of the interrupt (possibly querying a number of status registers) here.
1830 // Determine the type of UDC interrupt & then serve it:
1831 // (The following operations are of course EXAMPLES only.)
1832 volatile const TUint32* const status_reg = (TUint32*) 0xdefaced;
1833 const TUint32 status = *status_reg;
1834 enum {reset_interrupt, suspend_interrupt, resume_interrupt, sof_interrupt, ep_interrupt};
1837 if (status & reset_interrupt)
1842 // Suspend interrupt
1843 if (status & suspend_interrupt)
1845 SuspendIntService();
1849 if (status & resume_interrupt)
1854 // Start-of-Frame interrupt
1855 if (status & sof_interrupt)
1860 // Endpoint interrupt
1861 if (status & ep_interrupt)
1863 const TInt ep = status & 0xffff0000;
1865 EndpointIntService(ep);
1871 void TTemplateAsspUsbcc::Ep0NextState(TEp0State aNextState)
1873 // Moves the Ep0 state to aNextState.
1876 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0NextState"));
1878 iEp0State = aNextState;
1882 void TTemplateAsspUsbcc::UdcIsr(TAny* aPtr)
1884 // This is the static ASSP first-level UDC interrupt service routine. It dispatches the call to the
1885 // actual controller's ISR.
1888 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::UdcIsr"));
1890 static_cast<TTemplateAsspUsbcc*>(aPtr)->UdcInterruptService();
1894 TInt TTemplateAsspUsbcc::UsbClientConnectorCallback(TAny* aPtr)
1896 // This function is called in ISR context by the Variant's UsbClientConnectorInterruptService.
1897 // (This function is static.)
1900 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::UsbClientConnectorCallback"));
1902 TTemplateAsspUsbcc* const ptr = static_cast<TTemplateAsspUsbcc*>(aPtr);
1903 ptr->iCableConnected = ptr->iAssp->UsbClientConnectorInserted();
1905 _LIT(KIns, "inserted");
1906 _LIT(KRem, "removed");
1907 __KTRACE_OPT(KUSB, Kern::Printf(" > USB cable now %lS", ptr->iCableConnected ? &KIns : &KRem));
1909 if (ptr->iCableConnected)
1911 ptr->DeviceEventNotification(EUsbEventCableInserted);
1915 ptr->DeviceEventNotification(EUsbEventCableRemoved);
1922 TInt TTemplateAsspUsbcc::SetupUdcInterrupt()
1924 // Registers and enables the UDC interrupt (ASSP first level interrupt).
1927 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SetupUdcInterrupt"));
1929 // Register UDC interrupt:
1930 const TInt error = Interrupt::Bind(EAsspIntIdUsb, UdcIsr, this);
1931 if (error != KErrNone)
1933 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Binding UDC interrupt failed"));
1937 // Enable UDC interrupt:
1938 Interrupt::Enable(EAsspIntIdUsb);
1944 void TTemplateAsspUsbcc::ReleaseUdcInterrupt()
1946 // Disables and unbinds the UDC interrupt.
1949 __KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::ReleaseUdcInterrupt"));
1951 // Disable UDC interrupt:
1952 Interrupt::Disable(EAsspIntIdUsb);
1954 // Unregister UDC interrupt:
1955 Interrupt::Unbind(EAsspIntIdUsb);
1960 // --- DLL Exported Function --------------------------------------------------
1963 DECLARE_STANDARD_EXTENSION()
1965 // Creates and initializes a new USB client controller object on the kernel heap.
1968 __KTRACE_OPT(KUSB, Kern::Printf(" > Initializing USB client support (Udcc)..."));
1970 TTemplateAsspUsbcc* const usbcc = new TTemplateAsspUsbcc();
1973 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Memory allocation for TTemplateAsspUsbcc failed"));
1974 return KErrNoMemory;
1978 if ((r = usbcc->Construct()) != KErrNone)
1980 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Construction of TTemplateAsspUsbcc failed (%d)", r));
1985 if (usbcc->RegisterUdc(0) == NULL)
1987 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: PIL registration of PSL failed"));
1992 __KTRACE_OPT(KUSB, Kern::Printf(" > Initializing USB client support: Done"));
1998 // --- EOF --------------------------------------------------------------------