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\usbcsc\d_usbcsc.cpp
15 // LDD for USB Device driver stack, using shared chunks:
16 // The channel object.
25 #include <drivers/usbcsc.h>
28 /*****************************************************************************\
31 * Inherits from DLogicalDevice, the USB Shared Chunk LDD factory class *
33 \*****************************************************************************/
35 _LIT(KUsbScLddName, "Usbcsc");
37 static const TInt KUsbRequestCallbackPriority = 2;
39 /** Real entry point from the Kernel: return a new driver.
41 DECLARE_STANDARD_LDD()
43 return new DUsbcScLogDevice;
46 /** Create a channel on the device.
50 TInt DUsbcScLogDevice::Create(DLogicalChannelBase*& aChannel)
52 aChannel = new DLddUsbcScChannel;
53 return aChannel ? KErrNone : KErrNoMemory;
57 DUsbcScLogDevice::DUsbcScLogDevice()
59 iParseMask = KDeviceAllowUnit;
60 iUnitsMask = 0xffffffff; // Leave units decision to the Controller
61 iVersion = TVersion(KUsbcScMajorVersion, KUsbcScMinorVersion, KUsbcScBuildVersion);
65 TInt DUsbcScLogDevice::Install()
67 // Only proceed if we have the Controller underneath us
68 if (!DUsbClientController::UsbcControllerPointer())
70 __KTRACE_OPT(KPANIC, Kern::Printf("LDD Install: USB Controller Not Present"));
73 return SetName(&KUsbScLddName);
78 // Return the USB controller capabilities.
80 void DUsbcScLogDevice::GetCaps(TDes8& aDes) const
82 TPckgBuf<TCapsDevUsbc> b;
83 b().version = iVersion;
84 Kern::InfoCopy(aDes, b);
87 // End DUsbcScLogDevice
89 /*****************************************************************************\
92 * Where Chunk information is stored for the channel, and preseved for the *
93 * life of the chunk. *
95 \*****************************************************************************/
97 void DfcChunkCleanup(TAny*);
99 TUsbcScChunkInfo::TUsbcScChunkInfo(DLogicalDevice* aLdd)
101 iCleanup((TDfcFn)&DfcChunkCleanup,this,Kern::SvMsgQue(),0),
105 iPageNtz = (TInt8)__e32_find_ls1_32(Kern::RoundToPageSize(1));
108 TInt TUsbcScChunkInfo::CreateChunk(TInt aTotalSize)
110 // First, reserve an TUint of memory for each of pages needed to hold aTotalSize of memory.
111 // This will form the chunk map, so that we can look up the memory geometry.
112 iAllocatedSize = (aTotalSize>>iPageNtz)*sizeof(TUint);
113 iPhysicalMap = (TUint*) Kern::AllocZ(iAllocatedSize);
115 if (iPhysicalMap==NULL)
119 TChunkCreateInfo chunkInfo;
120 chunkInfo.iType = TChunkCreateInfo::ESharedKernelMultiple;
121 chunkInfo.iMaxSize = aTotalSize;
122 chunkInfo.iMapAttr = EMapAttrCachedMax;
123 chunkInfo.iOwnsMemory = EFalse;
124 chunkInfo.iDestroyedDfc = &iCleanup;
127 r = Kern::ChunkCreate(chunkInfo, iChunk, chunkMem, iChunkMapAttr);
128 iChunkMem = (TInt8*) chunkMem;
137 // This method requests closing the chunk.
138 // Note that nothing may happen immediately, as something else may have the chunk open.
139 void TUsbcScChunkInfo::Close()
141 Kern::ChunkClose(iChunk);
145 TInt TUsbcScChunkInfo::ChunkAlloc(TInt aOffset, TInt aSize)
147 TUint pageMask = (~0)<<iPageNtz;
148 TUint rleMask = ~pageMask;
149 TUint pageSize = rleMask+1;
153 __KTRACE_OPT(KUSB, Kern::Printf("::chunkalloc AllocPhysicalRam aSize %d", aSize));
155 r = Epoc::AllocPhysicalRam(aSize, physAddr);
156 __KTRACE_OPT(KUSB, if (r!=KErrNone) Kern::Printf("::chunkalloc AllocPhysicalRam r=%d (Error!)", r));
159 __KTRACE_OPT(KUSB, Kern::Printf("::chunkalloc ChunkCommitPhysical iChunk 0x%x size(%d), aOffset 0x%x, aSize 0x%x phsAddr 0x%x",
160 iChunk, sizeof(DChunk), aOffset, aSize,physAddr ));
162 r = Kern::ChunkCommitPhysical(iChunk, aOffset, aSize, physAddr);
163 __KTRACE_OPT(KUSB, if (r!=KErrNone) Kern::Printf("::chunkalloc ChunkCommitPhysical r=%d (Error!)", r));
166 Epoc::FreePhysicalRam(physAddr, aSize);
168 { // record physical address and length in physical map
171 for (rle=(aSize>>iPageNtz); rle>0; rle--, i++,physAddr+=pageSize)
173 __KTRACE_OPT(KUSB, Kern::Printf("::phys offset 0x%x = 0x%x",
174 (aOffset>>iPageNtz)+i, (physAddr & pageMask) | ((rle>(TInt)rleMask)?(TInt)rleMask:rle)));
175 iPhysicalMap[(aOffset>>iPageNtz)+i] = (physAddr & pageMask) | ((rle>(TInt)rleMask)?(TInt)rleMask:rle);
179 else if (r==KErrNoMemory)
180 r = -KErrNoMemory; // Semi-expected error.
185 This method retrieves the physical address of a given offset into the Chunk, and returns
186 the length of contiguous physical memory from this point.
188 @param aOffset the offset from the start of the chunk, to be queried.
189 @param aPhysical a pointer to a TPhysAddr, to be filled with the physical
190 address of the memory at the given offset.
192 @returns the length of contiguous physical memory from the given offset.
195 TInt TUsbcScChunkInfo::GetPhysical(TInt aOffset, TPhysAddr* aPhysical)
197 // Use masks, to retrieve the two components from the physical map, we created of the memory.
198 TUint pageMask = (~0)<<iPageNtz;
199 TUint val = iPhysicalMap[aOffset>>iPageNtz];
200 *aPhysical=(val & pageMask)+(aOffset & ~pageMask);
201 return ((val & ~pageMask)<<iPageNtz) - (aOffset & ~pageMask);
205 // DFC calls this fuction, which invokes the cleanup method.
207 void DfcChunkCleanup(TAny* aChunkInfo)
209 ((TUsbcScChunkInfo*) aChunkInfo)->ChunkCleanup();
213 void TUsbcScChunkInfo::ChunkCleanup()
215 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChunkInfo::ChunkCleanup()"));
220 // The part of the field used for the physical page address.
221 TUint pageMask = (~0)<<iPageNtz;
223 // The part of the field used for the run length encoding, of the contiguous pages.
224 TUint rleMask = ~pageMask;
225 TInt records=(iAllocatedSize>>2);
227 while (offset < records)
229 physAddr = iPhysicalMap[offset] & pageMask;
230 length = iPhysicalMap[offset] & rleMask;
233 Epoc::FreePhysicalRam(physAddr, length);
235 offset += (length>0)?length:1;
237 Kern::Free(iPhysicalMap);
239 DLogicalDevice* ldd = iLdd;
244 TInt TUsbcScChunkInfo::New(TUsbcScChunkInfo*& aChunk, TInt aSize, DLogicalDevice* aLdd)
246 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChunkInfo::New totalSize %d", aSize));
248 aChunk = new TUsbcScChunkInfo(aLdd);
254 TInt r = aChunk->CreateChunk(aSize);
262 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChunkInfo::New Created at 0x%x", aChunk->iChunkMem ));
266 // End TUsbcScChunkInfo
268 /*****************************************************************************\
271 * Represents a buffer, within a chunk. Each buffers can be used by *
272 * differt endpoint on differnt alt settings *
274 \*****************************************************************************/
277 TInt TUsbcScBuffer::Construct(TInt aDirection, DLddUsbcScChannel* aLdd, TInt aBufferOffset, TInt aBufferEndOffset, TInt aMinReadSize, TInt aMaxPacketSize, TInt aMaxReadSize)
281 iSequence = aBufferOffset; // Initialized at this, so that each buffer starts with a diffrent sequence number
283 iMinReadSize = aMinReadSize;
284 TInt size = (aBufferEndOffset - aBufferOffset);
285 TInt pageSize = Kern::RoundToPageSize(1);
286 if (aMaxReadSize > 0)
287 iMaxReadSize = aMaxReadSize;
289 iMaxReadSize = pageSize + ((size/3) & ~(pageSize -1));
291 iDirection = aDirection;
293 iChunkInfo = aLdd->iChunkInfo;
294 iChunkAddr = (TLinAddr) (aLdd->iChunkInfo->iChunkMem); //aChunkAddr;
296 TInt headerSize = sizeof(TUsbcScTransferHeader)-4; // TransferHeader includes 4 bytes of data.
299 TUint maxAlignment; // Note: This is a mask for max Alignment,
302 { // EP0 packets are not DMAed, and so dont need ialignment.
307 maxAlignment = 1023; // We don't know what the alignment requirement will be until enumeration, so assume worse case.
309 iFirstPacket = aBufferOffset + sizeof(SUsbcScBufferHeader) + headerSize;
310 iFirstPacket = (iFirstPacket + maxAlignment) & ~maxAlignment;
312 iBufferStart = (SUsbcScBufferHeader *) (iChunkAddr+aBufferOffset);
313 iBufferEnd = aBufferEndOffset;
315 if ((iDirection&1)==KUsbcScOut)
316 iHead = iFirstPacket-headerSize;//aBufferOffset + sizeof(SUsbcScBufferHeader);
323 r = iStatusList.Construct((aDirection==KUsbcScIn)?KUsbcScInRequests:KUsbcScOutRequests, iLdd->iClient);
326 iMaxPacketSize = aMaxPacketSize; // Indicates configured if ep0, otherwise not.
332 void TUsbcScBuffer::CreateChunkBufferHeader()
334 if ((iDirection&1)==KUsbcScOut)
336 iBufferStart->iHead= iHead;
337 iBufferStart->iTail= iHead; // Initially no data!
338 iBufferStart->iBilTail=iHead;
339 __KTRACE_OPT(KUSB, Kern::Printf("Realize: iHead 0x%x bufferHeader 0x%x", iHead,iBufferStart ));
341 // Dont need to round here, as we will round it up on endpoint change. (configuration)
346 TUsbcScBuffer::StartEndpoint
348 This method sets the nessesary paramenters to the buffer, for use for a particular endpoint.
351 void TUsbcScBuffer::StartEndpoint(TUsbcRequestCallback* aRequestInfo, TUint aFlags)
353 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartEndpoint (0x%x) : ep %d(%d)",this,aRequestInfo->iEndpointNum, aRequestInfo->iRealEpNum));
355 iCallback=aRequestInfo;
356 iMaxPacketSize = iLdd->iController->EndpointPacketSize(iLdd, aRequestInfo->iRealEpNum);
357 iAlignMask = ~(((iMaxPacketSize+1) & 0xFFFFFFF8)-1);
359 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartEndpoint : max Packets %d, mask 0x%x flags 0x%x", iMaxPacketSize, iAlignMask, iMode));
360 if ((iDirection&1)==KUsbcScOut)
362 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UsbcScOut\n"));
363 // Add dummy packet (doesnt have to be aligned, which avoids what if it changes issue)
364 // And Start next read.
365 iNeedsPacket=KEpIsStarting;
371 void TUsbcScBuffer::Destroy()
373 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::Destroy()"));
375 if (iLdd->iController && ((iDirection&1)==KUsbcScOut))
376 { // Me must cancel reads to LDD to, an there will be no list for the callbacks to look into.
377 iLdd->iController->CancelReadBuffer(iLdd, iCallback->iRealEpNum);
379 iStatusList.Destroy();
384 TInt TUsbcScBuffer::StartDataRead()
388 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataRead() - Not Configured"));
391 if (iStatusList.iState!=ENotRunning)
393 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataRead() - Already Stated! (%d)",iStatusList.iState));
402 TUsbcScStatusElement* nextJob = iStatusList.Next();
405 __KTRACE_OPT(KUSB, Kern::Printf("No more jobs"));
406 if (iMode && KUsbScCoupledRead)
408 iStatusList.iState=EReadingAhead;
411 iStatusList.iState=EInProgress;
413 TInt tail = iBufferStart->iTail;
414 TInt headerSize = sizeof(TUsbcScTransferHeader)-4; // TransferHeader includes 4 bytes of data.
415 maxLength = iChunkInfo->GetPhysical(iHead + headerSize, &physAddr); //returns all the bytes available after iHead + headerSize)
417 __ASSERT_DEBUG(maxLength>0,Kern::Fault("TUsbcScBuffer::StartDataRead(", __LINE__));
420 if (tail>iHead) // # # # H _ _ _ T # # # #
422 __KTRACE_OPT(KUSB,Kern::Printf("TUsbcScBuffer::StartDataRead() - tail 0x%x>head 0x%x, maxlength 0x%x", tail, iHead, maxLength));
424 freeSpace = (tail & iAlignMask) - (iHead +headerSize + (~iAlignMask+1) ); // Cant read right up to last buffer, or head/tail will cross.
426 if (freeSpace<iMinReadSize)
428 iStatusList.iState=ENotRunning;
429 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataRead() - Stall!!"));
430 return KErrOverflow; // Read STALL !! !! !!
433 if (freeSpace<maxLength)
434 maxLength = freeSpace;
436 if (maxLength> iMaxReadSize)
437 maxLength = iMaxReadSize;
438 // else tail<iHead (or empty) _ _ _ T # # # H _ _ _ _
439 // We would not have set iHead here if too small. So must be ok.
441 __ASSERT_DEBUG(maxLength>=iMinReadSize,Kern::Fault("TUsbcScBuffer::StartDataRead(", __LINE__));
443 TUint8* data = ((TUsbcScTransferHeader *) (iHead + iChunkAddr))->iData.b;
444 // set up callback stucture
446 iCallback->SetRxBufferInfo(data, physAddr, iIndexArray, iSizeArray,maxLength);
449 r = iLdd->iController->SetupReadBuffer(*iCallback);
452 __KTRACE_OPT(KUSB,Kern::Printf("SetupReadBuffer Error: %d, RT %d",r, iStatusList.iState));
453 iStatusList.Complete(r);
455 // After this, TUsbcScEndpoint::RequestCallback is called in a DFC.
456 // This in turn calls either TUsbcScBuffer::CompleteRead.
461 void TUsbcScBuffer::CompleteRead(TBool aStartNextRead)
463 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::CompleteRead buff=%x",this));
465 // The first packet always contains the total #of bytes
466 const TInt byteCount = iCallback->iPacketSize[0];
467 const TInt packetCount = iCallback->iRxPackets;
468 iCallback->iRxPackets=0;
471 if (iCallback->iPacketSize[packetCount - 1] < (TUint) iMaxPacketSize)
472 flags = KUsbcScShortPacket;
474 UpdateBufferList(byteCount, flags, aStartNextRead);
478 // This method "submits" the current transfer, and starts off the next read.
480 void TUsbcScBuffer::UpdateBufferList(TInt aByteCount,TUint aFlags, TBool aStartNextRead)
483 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst aByteCount %d, flags 0x%x iHead 0x%x", aByteCount, aFlags, iHead));
485 TInt headerSize = sizeof(TUsbcScTransferHeader)-4; // TransferHeader includes 4 bytes of data.
487 __KTRACE_OPT(KUSB, Kern::Printf("iHead 0x%x headerSize 0x%x",iHead, headerSize));
491 TInt next = iHead + headerSize + aByteCount; // next unused byte in buffer.
494 // This may take a few loops before we settle on a value.
498 next = (next + headerSize + ~iAlignMask) & iAlignMask;
499 maxLength = iChunkInfo->GetPhysical(next, &dummy);
501 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst next %x buffer end %x min-read: %x maxRun %x", next, iBufferEnd, iMinReadSize, maxLength));
502 // At the end of the buffer - wrap it if needbe.
503 if ((TUint)(next + iMinReadSize) > iBufferEnd)
508 // Not enough space, move onto next block.
509 if (maxLength<iMinReadSize)
512 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst Skip exhausted block. next %x max %d", next, maxLength));
518 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst next (pre deduct): %x, Fill in header at head: 0x%x, BuffStart: 0x%x.", next, iHead, iBufferStart));
520 next -= headerSize; // Move next back from the data start position, to the header start.
522 TUsbcScTransferHeader* header = (TUsbcScTransferHeader*) (iHead + iChunkAddr);
526 header->iHashId=59*(iLdd->iAlternateSetting+1)+iCallback->iRealEpNum; // Alt setting realated....
527 header->iSequence=iSequence;
530 header->iBytes=aByteCount;
532 header->iAltSettingSeq=iLdd->iAsSeq;
533 header->iAltSetting=iLdd->iAlternateSetting;
534 header->iFlags=aFlags;
535 __KTRACE_OPT(KUSB, Kern::Printf("We set next to 0x%x", next));
537 iStatusList.iState=ENotRunning;
538 if (next==iBufferStart->iTail) //or (othwise is as good as full)
545 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst StartRead?? "));
549 if ((aStartNextRead) && (StartDataRead() == KErrOverflow))
550 { // Oh crumbs, set state as slalled.
551 if (oldHead != iBufferStart->iBilTail)
552 // If user has not read everything in the buffer
553 // then set up a stall, so that ldd get to be woken early
558 else // otherwise if everything is read
559 // no choice but to return what we have
561 iBufferStart->iHead = iHead;
566 iBufferStart->iHead = next;
567 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst Compleating\n"));
570 iStatusList.Complete();
574 void TUsbcScBuffer::PopStall()
576 if (iStalled==iBufferStart->iTail)
577 return; // Still stalled.
579 if (iStalled!=-1) // If not Alt packet only stall
585 // If Alt setting of the popped packet is different to now
586 // Add alt setting change packet.
589 if (StartDataRead() == KErrOverflow)
591 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::PopStall Warning: Transfer was freed, but still no space!\n"));
594 iBufferStart->iHead = iHead;
599 void TUsbcScBuffer::StartDataWrite()
602 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite()"));
603 TUsbcScStatusElement* nextJob = iStatusList.Next();
613 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite() - Not Configured"));
619 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite() - No more jobs d=%d", iDirection));
620 if (iDirection==KUsbcScBiIn) // assume this is EP0, if this is true.
622 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite() Queue Read on EP0."));
623 // Start other read again.
624 iLdd->iBuffers[iLdd->iEP0OutBuff].StartDataRead();
629 if (iStatusList.iState==ENotRunning)
631 iStatusList.iState=EInProgress;
633 start = nextJob->iStart;
634 startAddr = (TUint8*) (start + ((TUint) (iChunkInfo->iChunkMem)));
636 length = nextJob->iLength;
637 zlpReqd = (nextJob->iFlags & KUsbcScWriteFlagsZlp) !=0;
638 // get max read length
639 maxLength = iChunkInfo->GetPhysical( start, &physAddr);
641 if (maxLength < length)
644 nextJob->iStart += maxLength;
645 nextJob->iLength -= maxLength;
646 // start this request.
647 iStatusList.iState=EFramgementInProgress;
652 if (iDirection==KUsbcScBiIn) // this is for EP0
654 iLdd->iController->CancelReadBuffer(iLdd, iCallback->iRealEpNum);
655 iLdd->iBuffers[iLdd->iEP0OutBuff].iStatusList.iState=ENotRunning;
658 iCallback->SetTxBufferInfo(startAddr, physAddr, length);
659 iCallback->iZlpReqd = zlpReqd;
660 r = iLdd->iController->SetupWriteBuffer(*iCallback);
663 __KTRACE_OPT(KUSB, Kern::Printf("SetupWriteBUffer Error: %d",r));
664 iStatusList.Complete(r);
670 void TUsbcScBuffer::CompleteWrite()
672 TInt error = iCallback->iError;
673 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::CompleteWrite buff=%x, err=%d",this, error));
674 iSent+= iCallback->iTxBytes;
677 if (error || iStatusList.iState!=EFramgementInProgress)
679 // complete request with error (if one).
680 // Some data could have been transmitted, even with an error.
681 iStatusList.Complete(error);
684 // Start next request, or next part of this one.
689 // Cancels the current request's callback.
690 // This is not to say it will cancel the actual operation,
691 // However it will cancel any further sections of the user perceived operation
692 // that are not yet started.
693 void TUsbcScBuffer::Cancel(TInt aErrorCode)
695 iStatusList.CancelQueued();
696 if (iLdd->iController && ((iDirection&1)==KUsbcScIn))
698 iLdd->iController->CancelWriteBuffer(iLdd, iCallback->iRealEpNum);
701 iStatusList.Complete(aErrorCode);
704 void TUsbcScBuffer::Ep0CancelLddRead()
706 // Stopping a read isn't as easy as one might think.
707 // We cancel the callback, but then check if any data was received (but not returned to us).
708 // If so, we must de-queue the request, and call the completion code.
710 iLdd->iController->CancelReadBuffer(iLdd, iCallback->iRealEpNum);
711 if (iCallback->iRxPackets) // received data?
713 // remove DFC (if infact sent)
714 iCallback->iDfc.Cancel();
716 // process the callback now, but dont start another
717 CompleteRead(EFalse);
721 void TUsbcScBuffer::SendEp0StatusPacket(TInt aState)
723 __KTRACE_OPT(KUSB, Kern::Printf(" TUsbcScBuffer::SendEp0StatusPacket(%d)", aState));
725 // We need to add a packet to the buffer, so we must stop the pending read, and start
726 // another after we have added out packet.
729 TUint* state = ((TUsbcScTransferHeader *) (iHead + iChunkAddr))->iData.i;
731 UpdateBufferList(4,KUsbcScStateChange);
736 /*****************************************************************************\
737 * TUsbcScStatusList *
739 * This is a list of read or write requests, containing user status *
740 * requests, that should later be completed. *
742 \*****************************************************************************/
745 Constructor for TUsbcScStatusList.
747 @param aSize is the number of requests to allow at any one time. This value
748 must be a power of two, for correct operation.
750 @returns KErrNoMemory if memory allocation failure, otherwise KErrNone.
753 TInt TUsbcScStatusList::Construct(TInt aSize, DThread* aClient)
759 iElements=(TUsbcScStatusElement *) Kern::AllocZ(sizeof(TUsbcScStatusElement)*aSize);
760 return (iElements==NULL)?KErrNoMemory:KErrNone;
764 // StatusList must be inactive before destroying.
765 void TUsbcScStatusList::Destroy()
767 if (iState!=ENotRunning)
768 Kern::Fault("TUsbcScStatusList::Destroy", __LINE__);
771 Kern::Free(iElements);
777 void TUsbcScStatusList::Pop()
782 iHead = ((iHead+1) & (iSize-1));
786 TUsbcScStatusElement* TUsbcScStatusList::Next()
788 return (iLength==0)?NULL:&(iElements[iHead]);
791 TInt TUsbcScStatusList ::Add(TRequestStatus* aStatus, TInt aLength, TUint aStart, TUint aFlags)
793 __KTRACE_OPT(KUSB,Kern::Printf("Adding request. iLength %d iSize %d", iLength, iSize));
796 TUsbcScStatusElement& e = iElements[((iHead+iLength) & (iSize-1))];
802 __KTRACE_OPT(KUSB,Kern::Printf("Adding request. new iLength %d", iLength));
812 // This method cancels any requests that have yet to be started.
814 void TUsbcScStatusList::CancelQueued(TInt aError)
816 if ((iLength==0) || ((iState!=ENotRunning) && (iLength==1))) // Nothing to do.
818 TInt elements2Complete = iLength - (iState?1:0);
821 if (iState) // If (iState != ENotRunning), complete all elements excepting the one at head
823 head = ((head+1) & (iSize-1)); // To iterate through the queue
826 // complete them all.
827 for (; elements2Complete>0; elements2Complete--)
829 Kern::RequestComplete(iClient, iElements[head].iStatus, aError);
830 head = ((head+1) & (iSize-1));
836 /* This method Completes the head status request, and pops it from its list.
837 This version of Complete is to be used in cases where the next request is not
838 chained - usually because of an error.
840 @Param aError - the code to complete with.
842 returns KErrNotFound if there was no request to complete
846 TInt TUsbcScStatusList::Complete(TInt aError)
848 if (iState==ENotRunning)
850 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScStatusList::Complete() - iState == ENotRunning!"));
858 Kern::RequestComplete(iClient, iElements[iHead].iStatus, aError);
861 iHead = ((iHead+1) & (iSize-1));
867 /* This method Completes the head status request, and pops it from its list. (If found.)
868 This version of Complete is to be used in cases where the request is successful, and
869 next request after this has (if present) been chained.
872 void TUsbcScStatusList::Complete()
876 __KTRACE_OPT(KUSB, Kern::Printf("Completing request. iLength %d", iLength));
878 Kern::RequestComplete(iClient, iElements[iHead].iStatus, KErrNone);
881 iHead = ((iHead+1) & (iSize-1));
884 // End TUsbcScStatusList
886 /*****************************************************************************\
889 * Used by DLddUsbcScChannel::RealizeInterface to set up the chunk *
891 \*****************************************************************************/
895 // This method works out the number potential maximum number of endpoints
896 // and the number of alt settings. With this information it allocs
897 // the necessary space for the given stucture to store information about
899 // This is intended to be called by RealizeInterface. This stucture is
900 // intended to be only temporary, and the space will be freed with Free()
901 // before RealizeInteface has finished.
903 void TRealizeInfo::Init(TUsbcScAlternateSettingList* aAlternateSettingList)
905 iAlternateSettingList = aAlternateSettingList;
910 __KTRACE_OPT(KUSB, Kern::Printf("Realize: work out max endpoint"));
911 // Work out max endpoints and number of alternate settings.
913 if (iAlternateSettingList)
915 TUsbcScAlternateSetting* alt = iAlternateSettingList->iHead;
919 if (alt->iNumberOfEndpoints>iMaxEndpoints)
920 iMaxEndpoints = alt->iNumberOfEndpoints;
921 // could work out in/out specifics, but unnecessary.
926 // Alloc some temporary working space for temp endpoint metadata
927 __KTRACE_OPT(KUSB, Kern::Printf("Realize: Alloc temp. Maxendpoints %d", iMaxEndpoints));
929 for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
931 iBufs[inout].iEp = (TUsbcScEndpoint **) Kern::AllocZ(iAltSettings*iMaxEndpoints*sizeof(TUsbcScEndpoint *));
932 iBufs[inout].iSizes = (TInt *) Kern::AllocZ(iMaxEndpoints*sizeof(TInt));
936 // CopyAndSortEndpoints
938 // This method copies pointers to the endpoint records into TRealizeInfo
939 // such that they are sorted in order of size per alt setting.
940 // In and Out endpoints are separated, and kept separate.
941 // The provided data structure is assumed to have been initialised with
942 // Realize_InitRealizeInfo.
944 // Return KErrArgument if the direction field is neither In or Out.
947 TInt TRealizeInfo::CopyAndSortEndpoints()
949 __KTRACE_OPT(KUSB, Kern::Printf("Realize: copy And sort"));
957 TUsbcScAlternateSetting* alt;
958 TEndpointSortBufs* bufsd;
960 if (iAlternateSettingList)
962 for (alt = iAlternateSettingList->iHead;alt!=NULL;alt = alt->iNext )
964 __KTRACE_OPT(KUSB, Kern::Printf("Realize: AlternateSetting %x", alt));
966 iBufs[KUsbcScIn].iEps =0;
967 iBufs[KUsbcScOut].iEps =0;
969 // For alt setting, iterate eps
970 for (altEp=1; altEp <= alt->iNumberOfEndpoints; altEp++)
972 __KTRACE_OPT(KUSB, Kern::Printf("Realize: Endpoint to add: %d",altEp));
974 TUsbcScEndpoint* nextEp = alt->iEndpoint[altEp];
976 __KTRACE_OPT(KUSB, Kern::Printf("Realize: ep Buffer Size: %d",nextEp->EndpointInfo()->iBufferSize));
978 inout = (nextEp->EndpointInfo()->iDir==KUsbEpDirIn)?KUsbcScIn:
979 (nextEp->EndpointInfo()->iDir==KUsbEpDirOut)?KUsbcScOut:KUsbcScUnknown;
980 if (inout==KUsbcScUnknown)
982 __KTRACE_OPT(KUSB, Kern::Printf("Realize: KUsbcScUnknown %x",nextEp->EndpointInfo()->iDir));
986 bufsd = &(iBufs[inout]);
987 __KTRACE_OPT(KUSB, Kern::Printf("Realize: ep direction: %x # endpoints %d", inout, bufsd->iEps));
990 // find and position ep, and insert.
992 if (bufsd->iEps==0) // First entry.
994 __KTRACE_OPT(KUSB, Kern::Printf("Realize: Add first endpoint"));
995 endpointOffs = altSetting*iMaxEndpoints;
996 bufsd->iEp[endpointOffs] = nextEp;
1001 // Move down the list, until we find the right place.
1002 for (endpoint=bufsd->iEps-1; endpoint>-1; endpoint--)
1004 endpointOffs = altSetting*iMaxEndpoints + endpoint;
1005 if (bufsd->iEp[endpointOffs]->EndpointInfo()->iBufferSize < nextEp->EndpointInfo()->iBufferSize)
1007 __KTRACE_OPT(KUSB, Kern::Printf("Realize: Shift Endpoint %d", endpoint));
1009 bufsd->iEp[endpointOffs+1] = bufsd->iEp[endpointOffs];
1013 __KTRACE_OPT(KUSB, Kern::Printf("Realize: Insert After Endpoint %d", endpoint));
1015 bufsd->iEp[endpointOffs+1] = nextEp;
1019 } // end for endpoint
1020 if (!placed) // if we didn't place it, it must be the biggest so far, so goes at the top.
1021 bufsd->iEp[0] = nextEp;
1027 }// if iAltsettingList
1033 // This works out the sizes of all the buffers, and stores the result in aBufInfo
1034 // based on the buffer information provided in the same structure.
1035 // Realize_CopyAndSortEndpoints is used to fill the structure with the informaition
1038 void TRealizeInfo::CalcBuffSizes()
1040 __KTRACE_OPT(KUSB, Kern::Printf("Realize: Calculate Buffers"));
1045 TUsbcScEndpoint* nextEp;
1047 TEndpointSortBufs* bufsd;
1049 for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
1051 __KTRACE_OPT(KUSB, Kern::Printf("Realize: Direction: %d", inout));
1054 bufsd = &(iBufs[inout]);
1055 // for each row, ie, buffer, find largest buffer need.
1056 for (endpoint=0; endpoint<iMaxEndpoints; endpoint++)
1058 __KTRACE_OPT(KUSB, Kern::Printf("Realize: endpoint %d", endpoint));
1060 for (altSetting=0; altSetting< iAltSettings; altSetting++)
1062 __KTRACE_OPT(KUSB, Kern::Printf("Realize: altSetting %d", altSetting));
1063 nextEp= bufsd->iEp[altSetting* iMaxEndpoints + endpoint];
1066 bufferSize = nextEp->EndpointInfo()->iBufferSize;
1067 __KTRACE_OPT(KUSB, Kern::Printf("Realize: comparing size %d", bufferSize));
1068 if (bufferSize> bufMaxSize)
1069 bufMaxSize = bufferSize;
1072 __KTRACE_OPT(KUSB, Kern::Printf("Realize: bufMaxSize %d", bufMaxSize));
1073 bufsd->iSizes[endpoint] = bufMaxSize;
1076 iTotalSize += bufsd->iSizes[endpoint];
1085 // Cleans up after Init()
1087 void TRealizeInfo::Free()
1090 for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
1092 Kern::Free(iBufs[inout].iEp);
1093 Kern::Free(iBufs[inout].iSizes);
1100 // LayoutChunkHeader
1102 // Sets up some geometry for the chunk;
1104 void TRealizeInfo::LayoutChunkHeader(TUsbcScChunkInfo* aChunkInfo)
1106 // First set up the indexes to the header structures.
1107 TUsbcScChunkHdrOffs* chkHdr = (TUsbcScChunkHdrOffs*) aChunkInfo->iChunkMem;
1109 chkHdr->iBuffers = sizeof(TUsbcScChunkHdrOffs); // First struct just after this one.
1110 iChunkStuct = (TUsbcScChunkBuffersHeader*) ( (TInt) aChunkInfo->iChunkMem + chkHdr->iBuffers);
1112 // Store number of buffers in chunk
1113 iChunkStuct->iRecordSize = sizeof(TUsbcScBufferRecord);
1114 iChunkStuct->iNumOfBufs=iTotalBuffers;
1116 iAltSettingsTbl = (TUsbcScChunkAltSettingHeader*) &(iChunkStuct->iBufferOffset[(iTotalBuffers+2)*sizeof(TUsbcScBufferRecord)]); // 2 extra for EP0 in and out.
1118 chkHdr->iAltSettings = (TUint) iAltSettingsTbl - (TUint) aChunkInfo->iChunkMem;
1120 iAltSettingsTbl->iEpRecordSize = sizeof(TUint);
1121 iAltSettingsTbl->iNumOfAltSettings = iAltSettings;
1124 TInt tableOffset = (TUint) iAltSettingsTbl->iAltTableOffset - (TUint) aChunkInfo->iChunkMem + iAltSettings*sizeof(TInt);
1125 __KTRACE_OPT(KUSB, Kern::Printf("Realize: table offset: 0x%x, altTble %x iChnkMem %x altSettings %x",tableOffset, iAltSettingsTbl, aChunkInfo->iChunkMem, iAltSettings ));
1127 __KTRACE_OPT(KUSB, Kern::Printf("Realize: populate chunk - create alt settings table"));
1129 // Create alt settings table. Set each element of altsettings table, to each induivatual alt setting table.
1130 // then fill in the number of endpoints for that alt setting, in the table.
1134 TUsbcScAlternateSetting* alt;
1135 if (iAlternateSettingList)
1137 alt = iAlternateSettingList->iHead;
1138 for (altSetting=0; altSetting<iAltSettings; altSetting++)
1140 __KTRACE_OPT(KUSB, Kern::Printf("Realize: altSetting %d, tableOffset %d", altSetting, tableOffset));
1142 iAltSettingsTbl->iAltTableOffset[altSetting] = tableOffset;
1143 noEpForAlt = (TInt*) &aChunkInfo->iChunkMem[tableOffset];
1145 *noEpForAlt = alt->iNumberOfEndpoints; // Set NumberofEndpoints field in Altsetting table
1146 tableOffset+= sizeof(TInt)+ alt->iNumberOfEndpoints*sizeof(TUsbcScHdrEndpointRecord);
1151 } // end LayoutChunkHeader
1155 /*****************************************************************************\
1156 * DLddUsbcScChannel *
1158 * Inherits from DLogicalDevice, the USB Shared Chunk LDD factory class *
1160 \*****************************************************************************/
1165 DLddUsbcScChannel::DLddUsbcScChannel()
1166 : iValidInterface(EFalse),
1167 iAlternateSettingList(NULL),
1169 iCompleteAllCallbackInfo(this, DLddUsbcScChannel::EmergencyCompleteDfc, KUsbRequestCallbackPriority),
1170 iStatusChangePtr(NULL),
1171 iStatusCallbackInfo(this, DLddUsbcScChannel::StatusChangeCallback, KUsbRequestCallbackPriority),
1172 iEndpointStatusChangePtr(NULL),
1173 iEndpointStatusCallbackInfo(this, DLddUsbcScChannel::EndpointStatusChangeCallback,
1174 KUsbRequestCallbackPriority),
1175 iOtgFeatureChangePtr(NULL),
1176 iOtgFeatureCallbackInfo(this, DLddUsbcScChannel::OtgFeatureChangeCallback, KUsbRequestCallbackPriority),
1177 iNumberOfEndpoints(0),
1178 iDeviceState(EUsbcDeviceStateUndefined),
1179 iOwnsDeviceControl(EFalse),
1180 iAlternateSetting(0),
1183 iUserKnowsAltSetting(ETrue),
1184 iDeviceStatusNeeded(EFalse),
1185 iChannelClosing(EFalse),
1186 iRealizeCalled(EFalse),
1192 __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DLddUsbcScChannel()"));
1193 iClient = &Kern::CurrentThread();
1195 for (TInt i = 1; i < KUsbcMaxRequests; i++)
1197 iRequestStatus[i] = NULL;
1206 DLddUsbcScChannel::~DLddUsbcScChannel()
1208 __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::~DLddUsbcScChannel()"));
1211 iStatusCallbackInfo.Cancel();
1212 iEndpointStatusCallbackInfo.Cancel();
1213 iOtgFeatureCallbackInfo.Cancel();
1214 iCompleteAllCallbackInfo.Cancel();
1215 DestroyAllInterfaces();
1216 if (iOwnsDeviceControl)
1218 iController->ReleaseDeviceControl(this);
1219 iOwnsDeviceControl = EFalse;
1221 iController->DeRegisterClient(this);
1224 if (iStatusFifo!=NULL)
1229 __KTRACE_OPT(KUSB, Kern::Printf("Closing buffers"));
1233 for (i=0; i<(iNumBuffers+2); i++)
1235 iBuffers[i].Destroy();
1237 Kern::Free(iBuffers);
1243 iChunkInfo->Close();
1244 // ChunkInfo will delete itself with DFC, but the pointer here is no longer needed.
1247 __KTRACE_OPT(KUSB, Kern::Printf("about to SafeClose"));
1248 Kern::SafeClose((DObject*&)iClient, NULL);
1253 // DoCreate - Create channel
1256 TInt DLddUsbcScChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer)
1258 __KTRACE_OPT(KUSB, Kern::Printf("LDD DoCreateL 1 Ver = %02d %02d %02d",
1259 aVer.iMajor, aVer.iMinor, aVer.iBuild));
1260 if (!Kern::CurrentThreadHasCapability(ECapabilityCommDD,
1261 __PLATSEC_DIAGNOSTIC_STRING("Checked by USBCSC.LDD (USB Driver)")))
1263 return KErrPermissionDenied;
1266 iController = DUsbClientController::UsbcControllerPointer();
1273 iStatusFifo = new TUsbcDeviceStatusQueue;
1274 if (iStatusFifo == NULL)
1276 return KErrNoMemory;
1279 if (!Kern::QueryVersionSupported(TVersion(KUsbcScMajorVersion, KUsbcScMinorVersion, KUsbcScBuildVersion), aVer))
1281 return KErrNotSupported;
1284 // set up the correct DFC queue
1285 SetDfcQ(iController->DfcQ(0)); // sets the channel's dfc queue
1286 iCompleteAllCallbackInfo.SetDfcQ(iDfcQ);
1287 iStatusCallbackInfo.SetDfcQ(iDfcQ); // use the channel's dfcq for this dfc
1288 iEndpointStatusCallbackInfo.SetDfcQ(iDfcQ); // use the channel's dfcq for this dfc
1289 iOtgFeatureCallbackInfo.SetDfcQ(iDfcQ);
1290 iMsgQ.Receive(); //start up the message q
1291 TInt r = iController->RegisterClientCallback(iCompleteAllCallbackInfo);
1294 r = iController->RegisterForStatusChange(iStatusCallbackInfo);
1297 r = iController->RegisterForEndpointStatusChange(iEndpointStatusCallbackInfo);
1300 r = iController->RegisterForOtgFeatureChange(iOtgFeatureCallbackInfo);
1312 // Events from userside arrive here, and delegated to either DoRequest, DoControl or DoCancel.
1315 void DLddUsbcScChannel::HandleMsg(TMessageBase* aMsg)
1317 TThreadMessage& m = *(TThreadMessage*)aMsg;
1319 __KTRACE_OPT(KUSB, Kern::Printf("HandleMsg 0x%x", id));
1321 if (id == (TInt) ECloseMsg)
1323 iChannelClosing = ETrue;
1324 m.Complete(KErrNone, EFalse);
1332 TRequestStatus* pS = (TRequestStatus*) m.Ptr0();
1333 r = DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
1334 m.Complete(r, ETrue);
1336 else if (id & RDevUsbcScClient::ERequestCancel)
1339 r = DoCancel(id, (TUint) m.Ptr0(), (TUint) m.Ptr1());
1340 m.Complete(r, ETrue);
1345 r = DoControl(id, m.Ptr0(), m.Ptr1());
1346 m.Complete(r, ETrue);
1352 #define BREAK_IF_NULL_ARG(a,r) if (a==NULL) { r = KErrArgument; __KTRACE_OPT(KUSB,Kern::Printf("NULL Argument")); break; }
1355 // DoRequest - Asynchronous requests
1357 // Overrides pure virtual, called by HandleMsg. (Above)
1359 TInt DLddUsbcScChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
1361 TInt reqNo = aReqNo & RDevUsbcScClient::KFieldIdMask;
1362 TInt r = KErrNone; // return via request notify
1363 TBool needsCompletion =EFalse;
1365 __KTRACE_OPT(KUSB, Kern::Printf("DoRequest 0x%08x", aReqNo));
1367 if ((reqNo>RDevUsbcScClient::ERequestReadDataNotify) &&
1368 (reqNo<RDevUsbcScClient::ERequestMaxRequests))
1370 if (iRequestStatus[reqNo])
1372 PanicClientThread(ERequestAlreadyPending);
1375 iRequestStatus[reqNo] = aStatus;
1380 case RDevUsbcScClient::ERequestWriteData:
1382 TInt buffer = (aReqNo>>RDevUsbcScClient::KFieldBuffPos)&RDevUsbcScClient::KFieldBuffMask;
1383 __KTRACE_OPT(KUSB, Kern::Printf("ERequestWriteData"));
1384 BREAK_IF_NULL_ARG(a2,r);
1386 r = DoWriteData( aStatus, buffer, (TInt) a1 /*Start*/, (TInt) a2 /* Length */,
1387 aReqNo>>RDevUsbcScClient::KFieldFlagsPos ); // Flags
1390 case RDevUsbcScClient::ERequestReadDataNotify:
1392 __KTRACE_OPT(KUSB, Kern::Printf("ERequestReadDataNotify"));
1393 return DoReadDataNotify(aStatus, (TInt) a1, (TInt) a2); // a1 = aBufferNumber, a2 - aLength;
1396 case RDevUsbcScClient::ERequestAlternateDeviceStatusNotify:
1398 __KTRACE_OPT(KUSB, Kern::Printf("ERequestAlternateDeviceStatusNotify"));
1399 BREAK_IF_NULL_ARG(a1,r);
1400 iDeviceStatusNeeded = ETrue;
1401 iStatusChangePtr = a1;
1402 needsCompletion = AlternateDeviceStateTestComplete();
1405 case RDevUsbcScClient::ERequestReEnumerate:
1407 __KTRACE_OPT(KUSB, Kern::Printf("ERequestReEnumerate"));
1408 // If successful, this will complete via the status notification.
1409 r = iController->ReEnumerate();
1412 case RDevUsbcScClient::ERequestEndpointStatusNotify:
1414 __KTRACE_OPT(KUSB, Kern::Printf("ERequestEndpointStatusNotify"));
1415 BREAK_IF_NULL_ARG(a1,r);
1417 iEndpointStatusChangePtr = a1;
1420 case RDevUsbcScClient::ERequestOtgFeaturesNotify:
1422 __KTRACE_OPT(KUSB, Kern::Printf("ERequestOtgFeaturesNotify"));
1423 BREAK_IF_NULL_ARG(a1,r);
1425 iOtgFeatureChangePtr = a1;
1429 r = KErrNotSupported;
1432 if ((needsCompletion) || (r != KErrNone))
1434 iRequestStatus[reqNo] = aStatus;
1435 Kern::RequestComplete(iClient, iRequestStatus[reqNo], r);
1445 // This method sets up the request to facilitate the userside being notifed when new data has been read.
1447 TInt DLddUsbcScChannel::DoReadDataNotify(TRequestStatus* aStatus, TInt aBufferNum, TInt aLength)
1449 __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify(x, %d, 0x%x)", aBufferNum, aLength));
1452 if ((aBufferNum<0) || (aBufferNum>=iNumBuffers)) // Indirectly checks that we are set up.
1454 if (aBufferNum!=KUsbcScEndpointZero)
1456 __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify : Bad Buffer Number!"));
1457 return KErrArgument;
1461 aBufferNum = iEP0OutBuff;
1467 if (iBuffers[aBufferNum].iDirection!=KUsbcScOut)
1469 __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify : Bad Buffer Direction!"));
1470 return KErrNotSupported;
1473 return KErrUsbInterfaceNotReady;
1475 SUsbcScBufferHeader* scBuffer = (SUsbcScBufferHeader*) iBuffers[aBufferNum].iBufferStart;
1477 __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify head %x tail %x", iBuffers[aBufferNum].iHead , scBuffer->iTail ));
1479 if (iBuffers[aBufferNum].iHead != scBuffer->iBilTail)
1482 if (iBuffers[aBufferNum].iStalled)
1484 iBuffers[aBufferNum].PopStall();
1485 return KErrCompletion;
1488 r = iBuffers[aBufferNum].iStatusList.Add(aStatus, aLength, 0,0);
1490 if (iBuffers[aBufferNum].iStatusList.iState==ENotRunning)
1492 iBuffers[aBufferNum].StartDataRead();
1496 __KTRACE_OPT(KUSB, Kern::Printf("Job in Progress!"));
1500 // end DoReadDataNotify.
1507 // This method sets up the request to write data to USB from userside.
1509 TInt DLddUsbcScChannel::DoWriteData(TRequestStatus* aStatus,TInt aBufferNum, TUint aStart, TUint aLength, TUint aFlags)
1511 __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData(%d, 0x%x, 0x%x, 0x%x)", aBufferNum, aStart, aLength, aFlags));
1512 if (!iUserKnowsAltSetting)
1514 // Check Buffer Number
1515 if ((aBufferNum<0) || (aBufferNum>=iNumBuffers))
1517 if ((TUint)aBufferNum!=RDevUsbcScClient::KFieldBuffMask) // KUsbcScEndpointZero & KFieldBuffMas = KFieldBuffMas;
1519 __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData : Bad Buffer Number!"));
1520 return KErrArgument;
1524 aBufferNum = iEP0InBuff;
1530 if (iBuffers[aBufferNum].iDirection!=KUsbcScIn)
1532 __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData Bad endpoint Direction"));
1533 return KErrArgument;
1537 TUsbcScBuffer& buf=iBuffers[aBufferNum];
1539 if ((aStart< (((TLinAddr) buf.iBufferStart)-buf.iChunkAddr)) || ((aStart+aLength)>iBuffers[aBufferNum].iBufferEnd))
1541 __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData Bad Range aStart or aLength 0x%x > 0x%x + 0x%x < 0x%x", (((TLinAddr) buf.iBufferStart)-buf.iChunkAddr),aStart, aLength, iBuffers[aBufferNum].iBufferEnd ));
1542 return KErrArgument;
1545 if ( (aBufferNum != iEP0InBuff) && !Configured())
1546 return KErrUsbInterfaceNotReady;
1548 if (aStart & ~buf.iAlignMask)
1550 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::DoDataWrite: address 0x%x unaligned.",aStart));
1551 return KErrArgument;
1554 TInt r = iBuffers[aBufferNum].iStatusList.Add(aStatus, aLength, aStart, aFlags); //update
1556 if (iBuffers[aBufferNum].iStatusList.iState==ENotRunning)
1558 iBuffers[aBufferNum].StartDataWrite();
1562 __KTRACE_OPT(KUSB, Kern::Printf("Job in Progress!"));
1572 // Cancel an outstanding request // Cancel need reworking.
1574 TInt DLddUsbcScChannel::DoCancel(TInt aReqNo, TUint aBuff, TUint aSpair)
1577 TInt direction=KUsbcScOut;
1579 __KTRACE_OPT(KUSB, Kern::Printf("DoCancel: 0x%x aBuff 0x%x", aReqNo, aBuff));
1582 case RDevUsbcScClient::ERequestCancel:
1586 for (buffer=1, mask=1; buffer<iNumBuffers; buffer++,mask<<=1)
1588 iBuffers[buffer].Cancel(KErrCancel);
1592 // coverity[missing_break]
1593 case RDevUsbcScClient::ERequestWriteDataCancel:
1594 direction = KUsbcScIn;
1595 case RDevUsbcScClient::ERequestReadDataNotifyCancel:
1596 __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Direction %d endpoints: 0x%x",direction, aReqNo));
1598 if (((TInt)aBuff)==KUsbcScEndpointZero) // EP0 is bi-directional, so pick correct buffer for call type
1600 __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Cancel Endpoint 0/%d",direction));
1601 iEp0Endpoint->AbortTransfer();
1602 if (direction==KUsbcScIn)
1607 else if ((TInt)aBuff >= iNumBuffers) // check buff no range.
1609 __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Error: Bad buffer number"));
1610 return KErrArgument;
1613 if ((iBuffers[aBuff].iDirection&1)!=direction) // Does direction match call type?
1615 __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Error: Bad buffer direction"));
1616 return KErrArgument;
1618 iBuffers[aBuff].iStatusList.CancelQueued();
1619 iBuffers[aBuff].Cancel(KErrCancel);
1623 case RDevUsbcScClient::ERequestAlternateDeviceStatusNotifyCancel:
1624 __KTRACE_OPT(KUSB, Kern::Printf("DoCancel: ERequestAlternateDeviceStatusNotify 0x%x", aReqNo));
1625 iDeviceStatusNeeded = EFalse;
1626 iStatusFifo->FlushQueue();
1627 if (iStatusChangePtr)
1629 TInt deviceState = iController->GetDeviceStatus();
1630 r = Kern::ThreadRawWrite(iClient, iStatusChangePtr, &deviceState, sizeof(deviceState), iClient);
1632 PanicClientThread(r);
1633 iStatusChangePtr = NULL;
1637 case RDevUsbcScClient::ERequestReEnumerateCancel:
1638 __KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestReEnumerate: 0x%x", aReqNo));
1641 case RDevUsbcScClient::ERequestEndpointStatusNotifyCancel:
1642 __KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestEndpointStatusNotify: 0x%x", aReqNo));
1643 CancelNotifyEndpointStatus();
1646 case RDevUsbcScClient::ERequestOtgFeaturesNotifyCancel:
1647 __KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestOtgFeaturesNotify: 0x%x", aReqNo));
1648 CancelNotifyOtgFeatures();
1652 __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Unknown! 0x%x", aReqNo));
1653 return KErrArgument;
1656 Kern::RequestComplete(iClient,iRequestStatus[aReqNo & ~RDevUsbcScClient::ERequestCancel], KErrCancel);
1661 void DLddUsbcScChannel::CancelNotifyEndpointStatus()
1663 if (iEndpointStatusChangePtr)
1666 for (TInt i = 1; i <= iNumberOfEndpoints; i++)
1668 TInt v = iController->GetEndpointStatus(this, iEndpoint[i]->RealEpNumber());
1670 (v == EEndpointStateStalled) ? b = 1 : b = 0;
1673 TInt r=Kern::ThreadRawWrite(iClient, iEndpointStatusChangePtr, (TUint8*) &epBitmap, sizeof(epBitmap), iClient);
1675 PanicClientThread(r);
1676 iEndpointStatusChangePtr = NULL;
1680 void DLddUsbcScChannel::CancelNotifyOtgFeatures()
1682 if (iOtgFeatureChangePtr)
1685 iController->GetCurrentOtgFeatures(features);
1686 TInt r=Kern::ThreadRawWrite(iClient, iOtgFeatureChangePtr, (TUint8*)&features, sizeof(features), iClient);
1688 PanicClientThread(r);
1689 iOtgFeatureChangePtr = NULL;
1696 // DoControl - Synchronous requests
1698 // Called from HandleMsg.
1700 TInt DLddUsbcScChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
1702 __KTRACE_OPT(KUSB, Kern::Printf("DoControl: %d", aFunction));
1706 TUsbcScEndpoint* pEndpoint;
1707 TPtrC8 pZeroDesc(NULL, 0);
1708 TEndpointDescriptorInfo epInfo;
1709 TUsbcScIfcInfo ifcInfo;
1710 TCSDescriptorInfo desInfo;
1711 TUsbcEndpointResource epRes;
1715 case RDevUsbcScClient::EControlEndpointZeroRequestError:
1716 __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointZeroRequestError"));
1718 if (iOwnsDeviceControl || (iValidInterface && iDeviceState == EUsbcDeviceStateConfigured))
1720 iController->Ep0Stall(this);
1724 if (iDeviceState != EUsbcDeviceStateConfigured)
1725 r = KErrUsbDeviceNotConfigured;
1727 r = KErrUsbInterfaceNotReady;
1731 case RDevUsbcScClient::EControlGetAlternateSetting:
1732 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetAlternateSetting"));
1733 if (iValidInterface && iDeviceState == EUsbcDeviceStateConfigured)
1735 r = iController->GetInterfaceNumber(this, param);
1738 r = Kern::ThreadRawWrite(iClient, a1, ¶m, sizeof(param), iClient);
1740 PanicClientThread(r);
1745 if (iDeviceState != EUsbcDeviceStateConfigured)
1746 r = KErrUsbDeviceNotConfigured;
1748 r = KErrUsbInterfaceNotReady;
1752 case RDevUsbcScClient::EControlDeviceStatus:
1753 __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceStatus"));
1754 param = iController->GetDeviceStatus();
1755 r = Kern::ThreadRawWrite(iClient, a1, ¶m, sizeof(param), iClient);
1757 PanicClientThread(r);
1760 case RDevUsbcScClient::EControlEndpointStatus:
1761 __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointStatus"));
1762 if (iValidInterface && ValidEndpoint((TInt) a1))
1764 pEndpoint = iEndpoint[(TInt)a1];
1765 if (pEndpoint == NULL)
1766 r = KErrNotSupported;
1769 param = iController->GetEndpointStatus(this, iEndpoint[(TInt)a1]->RealEpNumber());
1770 r = Kern::ThreadRawWrite(iClient, a2, ¶m, sizeof(param), iClient);
1772 PanicClientThread(r);
1777 if (iDeviceState != EUsbcDeviceStateConfigured)
1778 r = KErrUsbDeviceNotConfigured;
1780 r = KErrUsbInterfaceNotReady;
1784 case RDevUsbcScClient::EControlEndpointCaps:
1785 __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointCaps"));
1786 r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
1788 PanicClientThread(r);
1789 iController->EndpointCaps(this, *((TDes8*) a1));
1792 case RDevUsbcScClient::EControlDeviceCaps:
1793 __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceCaps"));
1794 r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
1796 PanicClientThread(r);
1797 iController->DeviceCaps(this, *((TDes8*) a1));
1800 case RDevUsbcScClient::EControlSendEp0StatusPacket:
1801 __KTRACE_OPT(KUSB, Kern::Printf("EControlSendEp0StatusPacket"));
1802 iController->SendEp0StatusPacket(this);
1805 case RDevUsbcScClient::EControlHaltEndpoint:
1806 __KTRACE_OPT(KUSB, Kern::Printf("EControlHaltEndpoint"));
1807 if (iValidInterface && ValidEndpoint((TInt) a1))
1809 r = iController->HaltEndpoint(this, iEndpoint[(TInt)a1]->RealEpNumber());
1813 if (iDeviceState != EUsbcDeviceStateConfigured)
1814 r = KErrUsbDeviceNotConfigured;
1816 r = KErrUsbInterfaceNotReady;
1820 case RDevUsbcScClient::EControlClearHaltEndpoint:
1821 __KTRACE_OPT(KUSB, Kern::Printf("EControlClearHaltEndpoint"));
1822 if (iValidInterface && ValidEndpoint((TInt) a1))
1824 r = iController->ClearHaltEndpoint(this, iEndpoint[(TInt)a1]->RealEpNumber());
1828 if (iDeviceState != EUsbcDeviceStateConfigured)
1829 r = KErrUsbDeviceNotConfigured;
1831 r = KErrUsbInterfaceNotReady;
1835 case RDevUsbcScClient::EControlDumpRegisters:
1836 __KTRACE_OPT(KUSB, Kern::Printf("EControlDumpRegisters"));
1837 iController->DumpRegisters();
1840 case RDevUsbcScClient::EControlReleaseDeviceControl:
1841 __KTRACE_OPT(KUSB, Kern::Printf("EControlReleaseDeviceControl"));
1842 iController->ReleaseDeviceControl(this);
1843 iOwnsDeviceControl = EFalse;
1846 case RDevUsbcScClient::EControlEndpointZeroMaxPacketSizes:
1847 __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointZeroMaxPacketSizes"));
1848 r = iController->EndpointZeroMaxPacketSizes();
1851 case RDevUsbcScClient::EControlSetEndpointZeroMaxPacketSize:
1852 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetEndpointZeroMaxPacketSize"));
1853 r = iController->SetEndpointZeroMaxPacketSize(reinterpret_cast<TInt>(a1));
1856 case RDevUsbcScClient::EControlGetEndpointZeroMaxPacketSize:
1857 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointZeroMaxPacketSize"));
1858 r = iController->Ep0PacketSize();
1861 case RDevUsbcScClient::EControlGetDeviceDescriptor:
1862 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceDescriptor"));
1863 r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
1865 PanicClientThread(r);
1866 r = iController->GetDeviceDescriptor(iClient, *((TDes8*) a1));
1869 case RDevUsbcScClient::EControlSetDeviceDescriptor:
1870 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceDescriptor"));
1871 BREAK_IF_NULL_ARG(a1,r);
1872 r = iController->SetDeviceDescriptor(iClient, *((TDes8*) a1));
1875 case RDevUsbcScClient::EControlGetDeviceDescriptorSize:
1876 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceDescriptorSize"));
1877 BREAK_IF_NULL_ARG(a1,r);
1878 r = iController->GetDeviceDescriptorSize(iClient, *((TDes8*) a1));
1881 case RDevUsbcScClient::EControlGetConfigurationDescriptor:
1882 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationDescriptor"));
1883 r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0 , 0, iClient);
1885 PanicClientThread(r);
1886 r = iController->GetConfigurationDescriptor(iClient, *((TDes8*) a1));
1889 case RDevUsbcScClient::EControlGetConfigurationDescriptorSize:
1890 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationDescriptorSize"));
1893 r = iController->GetConfigurationDescriptorSize(iClient, *((TDes8*) a1));
1899 case RDevUsbcScClient::EControlSetConfigurationDescriptor:
1900 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetConfigurationDescriptor"));
1901 r = iController->SetConfigurationDescriptor(iClient, *((TDes8*) a1));
1904 case RDevUsbcScClient::EControlGetInterfaceDescriptor:
1905 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetInterfaceDescriptor"));
1906 r = iController->GetInterfaceDescriptor(iClient, this, (TInt) a1, *((TDes8*) a2));
1909 case RDevUsbcScClient::EControlGetInterfaceDescriptorSize:
1910 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetInterfaceDescriptorSize"));
1911 r = iController->GetInterfaceDescriptorSize(iClient, this, (TInt) a1, *(TDes8*) a2);
1914 case RDevUsbcScClient::EControlSetInterfaceDescriptor:
1915 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetInterfaceDescriptor"));
1916 r = iController->SetInterfaceDescriptor(iClient, this, (TInt) a1, *((TDes8*) a2));
1919 case RDevUsbcScClient::EControlGetEndpointDescriptor:
1920 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointDescriptor"));
1921 r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
1923 PanicClientThread(r);
1924 ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
1925 r = (ep<0)?ep:iController->GetEndpointDescriptor(iClient, this, epInfo.iSetting,
1926 ep, *(TDes8*) epInfo.iArg);
1929 case RDevUsbcScClient::EControlGetEndpointDescriptorSize:
1930 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointDescriptorSize"));
1931 r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
1933 PanicClientThread(r);
1934 ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
1935 r = iController->GetEndpointDescriptorSize(iClient, this, epInfo.iSetting,
1936 ep, *(TDes8*) epInfo.iArg);
1939 case RDevUsbcScClient::EControlSetEndpointDescriptor:
1940 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetEndpointDescriptor"));
1941 r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
1943 PanicClientThread(r);
1944 ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
1945 r = iController->SetEndpointDescriptor(iClient, this, epInfo.iSetting,
1946 ep, *(TDes8*)epInfo.iArg);
1949 case RDevUsbcScClient::EControlGetDeviceQualifierDescriptor:
1950 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceQualifierDescriptor"));
1951 r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
1953 PanicClientThread(r);
1954 r = iController->GetDeviceQualifierDescriptor(iClient, *((TDes8*) a1));
1957 case RDevUsbcScClient::EControlSetDeviceQualifierDescriptor:
1958 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceQualifierDescriptor"));
1959 BREAK_IF_NULL_ARG(a1,r);
1960 r = iController->SetDeviceQualifierDescriptor(iClient, *((TDes8*) a1));
1963 case RDevUsbcScClient::EControlGetOtherSpeedConfigurationDescriptor:
1964 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetOtherSpeedConfigurationDescriptor"));
1965 r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0 , 0, iClient);
1967 PanicClientThread(r);
1968 r = iController->GetOtherSpeedConfigurationDescriptor(iClient, *((TDes8*) a1));
1971 case RDevUsbcScClient::EControlSetOtherSpeedConfigurationDescriptor:
1972 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetOtherSpeedConfigurationDescriptor"));
1973 r = iController->SetOtherSpeedConfigurationDescriptor(iClient, *((TDes8*) a1));
1977 case RDevUsbcScClient::EControlGetCSInterfaceDescriptor:
1978 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSInterfaceDescriptor"));
1979 r = iController->GetCSInterfaceDescriptorBlock(iClient, this, (TInt) a1, *((TDes8*) a2));
1982 case RDevUsbcScClient::EControlGetCSInterfaceDescriptorSize:
1983 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSInterfaceDescriptorSize"));
1984 r = iController->GetCSInterfaceDescriptorBlockSize(iClient, this, (TInt) a1, *(TDes8*) a2);
1987 case RDevUsbcScClient::EControlGetCSEndpointDescriptor:
1988 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSEndpointDescriptor"));
1989 r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
1991 PanicClientThread(r);
1992 ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
1993 r = iController->GetCSEndpointDescriptorBlock(iClient, this, epInfo.iSetting,
1994 ep, *(TDes8*) epInfo.iArg);
1997 case RDevUsbcScClient::EControlGetCSEndpointDescriptorSize:
1998 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSEndpointDescriptorSize"));
1999 r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
2001 PanicClientThread(r);
2002 ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
2003 r = iController->GetCSEndpointDescriptorBlockSize(iClient, this, epInfo.iSetting,
2004 ep, *(TDes8*) epInfo.iArg);
2007 case RDevUsbcScClient::EControlSignalRemoteWakeup:
2008 __KTRACE_OPT(KUSB, Kern::Printf("EControlSignalRemoteWakeup"));
2009 r = iController->SignalRemoteWakeup();
2012 case RDevUsbcScClient::EControlDeviceDisconnectFromHost:
2013 __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceDisconnectFromHost"));
2014 r = iController->UsbDisconnect();
2017 case RDevUsbcScClient::EControlDeviceConnectToHost:
2018 __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceConnectToHost"));
2019 r = iController->UsbConnect();
2022 case RDevUsbcScClient::EControlDevicePowerUpUdc:
2023 __KTRACE_OPT(KUSB, Kern::Printf("EControlDevicePowerUpUdc"));
2024 r = iController->PowerUpUdc();
2027 case RDevUsbcScClient::EControlSetDeviceControl:
2028 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceControl"));
2029 r = iController->SetDeviceControl(this);
2032 iOwnsDeviceControl = ETrue;
2033 if (iEp0Endpoint == NULL)
2035 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceControl"));
2039 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: SetupEp0() failed"));
2040 iController->ReleaseDeviceControl(this);
2041 iOwnsDeviceControl=EFalse;
2050 case RDevUsbcScClient::EControlCurrentlyUsingHighSpeed:
2051 __KTRACE_OPT(KUSB, Kern::Printf("EControlCurrentlyUsingHighSpeed"));
2052 r = iController->CurrentlyUsingHighSpeed();
2055 case RDevUsbcScClient::EControlSetInterface:
2056 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetInterface"));
2057 r = Kern::ThreadRawRead(iClient, a2, &ifcInfo, sizeof(ifcInfo));
2059 PanicClientThread(r);
2060 r = SetInterface((TInt) a1, &ifcInfo);
2063 case RDevUsbcScClient::EControlReleaseInterface:
2064 __KTRACE_OPT(KUSB, Kern::Printf("EControlReleaseInterface"));
2065 if (!iRealizeCalled)
2067 r = iController->ReleaseInterface(this, (TInt) a1);
2070 DestroyInterface((TUint) a1);
2074 __KTRACE_OPT(KPANIC, Kern::Printf(" Error in PIL: LDD interface won't be released."));
2078 r = KErrUsbAlreadyRealized;
2081 case RDevUsbcScClient::EControlSetCSInterfaceDescriptor:
2082 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetCSInterfaceDescriptor"));
2083 r = Kern::ThreadRawRead(iClient, a1, &desInfo, sizeof(desInfo));
2085 PanicClientThread(r);
2086 r = iController->SetCSInterfaceDescriptorBlock(iClient, this, desInfo.iSetting,
2087 *reinterpret_cast<const TDes8*>(desInfo.iArg),
2091 case RDevUsbcScClient::EControlSetCSEndpointDescriptor:
2092 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetCSEndpointDescriptor"));
2093 r = Kern::ThreadRawRead(iClient, a1, &desInfo, sizeof(desInfo));
2095 PanicClientThread(r);
2096 ep = EpFromAlternateSetting(desInfo.iSetting, desInfo.iEndpoint);
2097 r = iController->SetCSEndpointDescriptorBlock(iClient, this, desInfo.iSetting, ep,
2098 *reinterpret_cast<const TDes8*>(desInfo.iArg),
2102 case RDevUsbcScClient::EControlGetStringDescriptorLangId:
2103 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetStringDescriptorLangId"));
2104 r = iController->GetStringDescriptorLangId(iClient, *((TDes8*) a1));
2107 case RDevUsbcScClient::EControlSetStringDescriptorLangId:
2108 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetStringDescriptorLangId"));
2109 r = iController->SetStringDescriptorLangId(reinterpret_cast<TUint>(a1));
2112 case RDevUsbcScClient::EControlGetManufacturerStringDescriptor:
2113 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetManufacturerStringDescriptor"));
2114 r = iController->GetManufacturerStringDescriptor(iClient, *((TPtr8*) a1));
2117 case RDevUsbcScClient::EControlSetManufacturerStringDescriptor:
2118 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetManufacturerStringDescriptor"));
2119 r = iController->SetManufacturerStringDescriptor(iClient, *((TPtr8*) a1));
2122 case RDevUsbcScClient::EControlRemoveManufacturerStringDescriptor:
2123 __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveManufacturerStringDescriptor"));
2124 r = iController->RemoveManufacturerStringDescriptor();
2127 case RDevUsbcScClient::EControlGetProductStringDescriptor:
2128 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetProductStringDescriptor"));
2129 r = iController->GetProductStringDescriptor(iClient, *((TPtr8*) a1));
2132 case RDevUsbcScClient::EControlSetProductStringDescriptor:
2133 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetProductStringDescriptor"));
2134 r = iController->SetProductStringDescriptor(iClient, *((TPtr8*) a1));
2137 case RDevUsbcScClient::EControlRemoveProductStringDescriptor:
2138 __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveProductStringDescriptor"));
2139 r = iController->RemoveProductStringDescriptor();
2142 case RDevUsbcScClient::EControlGetSerialNumberStringDescriptor:
2143 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetSerialNumberStringDescriptor"));
2144 r = iController->GetSerialNumberStringDescriptor(iClient, *((TPtr8*) a1));
2147 case RDevUsbcScClient::EControlSetSerialNumberStringDescriptor:
2148 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetSerialNumberStringDescriptor"));
2149 r = iController->SetSerialNumberStringDescriptor(iClient, *((TPtr8*) a1));
2152 case RDevUsbcScClient::EControlRemoveSerialNumberStringDescriptor:
2153 __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveSerialNumberStringDescriptor"));
2154 r = iController->RemoveSerialNumberStringDescriptor();
2157 case RDevUsbcScClient::EControlGetConfigurationStringDescriptor:
2158 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationStringDescriptor"));
2159 r = iController->GetConfigurationStringDescriptor(iClient, *((TPtr8*) a1));
2162 case RDevUsbcScClient::EControlSetConfigurationStringDescriptor:
2163 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetConfigurationStringDescriptor"));
2164 r = iController->SetConfigurationStringDescriptor(iClient, *((TPtr8*) a1));
2167 case RDevUsbcScClient::EControlRemoveConfigurationStringDescriptor:
2168 __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveConfigurationStringDescriptor"));
2169 r = iController->RemoveConfigurationStringDescriptor();
2172 case RDevUsbcScClient::EControlGetStringDescriptor:
2173 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetStringDescriptor"));
2174 r = iController->GetStringDescriptor(iClient, (TUint8) (TInt) a1, *((TPtr8*) a2));
2177 case RDevUsbcScClient::EControlSetStringDescriptor:
2178 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetStringDescriptor"));
2179 r = iController->SetStringDescriptor(iClient, (TUint8) (TInt) a1, *((TPtr8*) a2));
2182 case RDevUsbcScClient::EControlRemoveStringDescriptor:
2183 __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveStringDescriptor"));
2184 r = iController->RemoveStringDescriptor((TUint8) (TInt) a1);
2187 case RDevUsbcScClient::EControlAllocateEndpointResource:
2189 __KTRACE_OPT(KUSB, Kern::Printf("EControlAllocateEndpointResource"));
2190 epRes = (TUsbcEndpointResource)((TInt) a2);
2192 r = GetRealEpForEpResource((TInt)a1, realEp);
2194 r = iController->AllocateEndpointResource(this, realEp, epRes);
2197 case RDevUsbcScClient::EControlDeAllocateEndpointResource:
2199 __KTRACE_OPT(KUSB, Kern::Printf("EControlDeAllocateEndpointResource"));
2200 epRes = (TUsbcEndpointResource)((TInt) a2);
2202 r = GetRealEpForEpResource((TInt)a1, realEp);
2204 r = iController->DeAllocateEndpointResource(this, realEp, epRes);
2207 case RDevUsbcScClient::EControlQueryEndpointResourceUse:
2209 __KTRACE_OPT(KUSB, Kern::Printf("EControlQueryEndpointResourceUse"));
2210 epRes = (TUsbcEndpointResource)((TInt) a2);
2212 r = GetRealEpForEpResource((TInt)a1, realEp);
2214 r = iController->QueryEndpointResource(this, realEp, epRes);
2217 case RDevUsbcScClient::EControlSetOtgDescriptor:
2218 __KTRACE_OPT(KUSB, Kern::Printf("EControlSetOtgDescriptor"));
2219 r = iController->SetOtgDescriptor(iClient, *((const TDesC8*)a1));
2222 case RDevUsbcScClient::EControlGetOtgDescriptor:
2223 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetOtgDescriptor"));
2224 r = iController->GetOtgDescriptor(iClient, *((TDes8*)a1));
2227 case RDevUsbcScClient::EControlGetOtgFeatures:
2228 __KTRACE_OPT(KUSB, Kern::Printf("EControlGetOtgFeatures"));
2229 r = iController->GetOtgFeatures(iClient, *((TDes8*)a1));
2232 case RDevUsbcScClient::EControlRealizeInterface:
2233 __KTRACE_OPT(KUSB, Kern::Printf("EControlRealizeInterface"));
2234 r = RealizeInterface();
2236 case RDevUsbcScClient::EControlStartNextInAlternateSetting:
2237 __KTRACE_OPT(KUSB, Kern::Printf("EControlStartNextInAlternateSetting"));
2238 r = StartNextInAlternateSetting();
2242 __KTRACE_OPT(KUSB, Kern::Printf("Function code not supported"));
2243 r = KErrNotSupported;
2253 // Overriding DObject virtual
2255 TInt DLddUsbcScChannel::RequestUserHandle(DThread* aThread, TOwnerType /*aType*/)
2257 __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::RequestUserHandle"));
2258 // The USB client LDD is not designed for a channel to be shared between
2259 // threads. It saves a pointer to the current thread when it is opened, and
2260 // uses this to complete any asynchronous requests.
2261 // It is therefore not acceptable for the handle to be duplicated and used
2262 // by another thread:
2263 if (aThread == iClient)
2269 return KErrAccessDenied;
2273 inline TInt DLddUsbcScChannel::GetRealEpForEpResource(TInt aEndpoint, TInt& aRealEp)
2275 if (iEndpoint) // if we've enumerated at least once, proceed as normal.
2277 if (aEndpoint <= iNumberOfEndpoints && aEndpoint >= 0)
2279 aRealEp=iEndpoint[aEndpoint]->RealEpNumber();
2283 else // Assume alternate setting 0.
2285 if (iAlternateSettingList) // Check it has been set up.
2287 TUsbcScAlternateSetting* alt = iAlternateSettingList->iHead;
2288 if (alt && (aEndpoint <= alt->iNumberOfEndpoints && aEndpoint >= 0))
2290 aRealEp= alt->iEndpoint[aEndpoint]->RealEpNumber();
2295 return KErrUsbDeviceNotConfigured;
2299 TUsbcEndpointInfoArray::TUsbcEndpointInfoArray(const TUsbcScEndpointInfo* aData, TInt aDataSize)
2301 iType = EUsbcScEndpointInfo;
2302 iData = (TUint8*) aData;
2304 iDataSize = aDataSize;
2306 iDataSize = sizeof(TUsbcScEndpointInfo);
2313 // Called from DoControl. Sets the configuration of a given Interface. // Needs changing
2314 // All interfaces must be configured before one can be used.
2317 TInt DLddUsbcScChannel::SetInterface(TInt aInterfaceNumber, TUsbcScIfcInfo* aInfoBuf)
2319 // Copy interface description.
2322 return KErrUsbAlreadyRealized;
2324 if (!iAlternateSettingList)
2326 iAlternateSettingList = new TUsbcScAlternateSettingList;
2327 if (iAlternateSettingList==NULL)
2329 return KErrNoMemory;
2333 // Read descriptor in
2334 TUsbcScInterfaceInfoBuf ifc_info_buf;
2335 TUsbcScInterfaceInfoBuf* const ifc_info_buf_ptr = aInfoBuf->iInterfaceData;
2336 const TInt srcLen = Kern::ThreadGetDesLength(iClient, ifc_info_buf_ptr);
2338 __KTRACE_OPT(KUSB, Kern::Printf("SetInterface srcLen = %d len = %d", srcLen, ifc_info_buf.Length() ));
2340 if (srcLen < ifc_info_buf.Length())
2342 __KTRACE_OPT(KUSB, Kern::Printf("SetInterface can't copy"));
2343 PanicClientThread(EDesOverflow);
2346 TInt r = Kern::ThreadDesRead(iClient, ifc_info_buf_ptr, ifc_info_buf, 0, KChunkShiftBy0);
2349 __KTRACE_OPT(KUSB, Kern::Printf("SetInterface Copy failed reason=%d", r));
2350 PanicClientThread(r);
2353 // The list of endpoints is within the interface info.
2354 TUsbcScEndpointInfo* pEndpointData = ifc_info_buf().iEndpointData;
2356 const TInt num_endpoints = ifc_info_buf().iTotalEndpointsUsed;
2357 __KTRACE_OPT(KUSB, Kern::Printf("SetInterface num_endpoints=%d", num_endpoints));
2358 if (num_endpoints>KMaxEndpointsPerClient)
2359 return KErrOverflow;
2362 // Initialize real ep numbers list.
2364 TInt real_ep_numbers[KMaxEndpointsPerClient+1]; // range 1->KMaxEndpointsPerClient (0 not used)
2365 for (i=0; i<=KMaxEndpointsPerClient; i++)
2366 real_ep_numbers[i] = -1;
2369 // See if PIL will accept this interface
2370 __KTRACE_OPT(KUSB, Kern::Printf("SetInterface Calling controller"));
2371 TUsbcEndpointInfoArray endpointData = TUsbcEndpointInfoArray(ifc_info_buf().iEndpointData);
2373 r = iController->SetInterface(this,
2376 ifc_info_buf().iClass,
2378 (TInt) ifc_info_buf().iTotalEndpointsUsed,
2380 &real_ep_numbers[0],
2381 ifc_info_buf().iFeatureWord);
2383 __KTRACE_OPT(KUSB, Kern::Printf("SetInterface controller returned %d", r));
2386 __KTRACE_OPT(KPANIC, Kern::Printf("SetInterface failed reason=%d", r));
2390 // create alternate setting record
2391 TUsbcScAlternateSetting* alternateSettingListRec = new TUsbcScAlternateSetting;
2392 if (!alternateSettingListRec)
2395 goto ReleaseInterface;
2399 for (TInt i = 1; i <= num_endpoints; i++, pEndpointData++)
2401 __KTRACE_OPT(KUSB, Kern::Printf("SetInterface for ep=%d", i));
2403 if ((pEndpointData->iType==KUsbEpTypeControl)
2404 || (pEndpointData->iDir != KUsbEpDirIn && pEndpointData->iDir != KUsbEpDirOut)
2405 || (pEndpointData->iSize > 1024) || (pEndpointData->iSize<=0))
2407 r = KErrUsbBadEndpoint;
2412 TUint* bufferSize = &(pEndpointData->iBufferSize);
2414 *bufferSize= KUsbcScDefaultBufferSize;
2416 TInt pageSize = Kern::RoundToPageSize(1);
2417 // Round buffersize up to nearest pagesize.
2418 *bufferSize = (*bufferSize+pageSize-1) & ~(pageSize-1);
2420 TUsbcScEndpoint* ep = new TUsbcScEndpoint(this, iController, pEndpointData, i);
2421 alternateSettingListRec->iEndpoint[i] = ep;
2427 if (ep->Construct() != KErrNone)
2434 __KTRACE_OPT(KUSB, Kern::Printf("SetInterface for ep=%d rec=0x%08x ep==0x%08x",
2435 i, alternateSettingListRec, ep));
2438 if (iAlternateSettingList->iHead)
2440 iAlternateSettingList->iTail->iNext = alternateSettingListRec;
2441 alternateSettingListRec->iPrevious = iAlternateSettingList->iTail;
2442 iAlternateSettingList->iTail = alternateSettingListRec;
2446 iAlternateSettingList->iHead = alternateSettingListRec;
2447 iAlternateSettingList->iTail = alternateSettingListRec;
2450 alternateSettingListRec->iNext = NULL;
2451 alternateSettingListRec->iSetting = aInterfaceNumber;
2452 alternateSettingListRec->iNumberOfEndpoints = num_endpoints;
2454 // Record the 'real' endpoint number used by the PDD in both the Ep and
2455 // the Req callback:
2456 for (TInt i = 1; i <= num_endpoints; i++)
2458 alternateSettingListRec->iEndpoint[i]->SetRealEpNumber(real_ep_numbers[i]);
2464 delete alternateSettingListRec;
2469 TInt r1 = iController->ReleaseInterface(this, aInterfaceNumber);
2470 __KTRACE_OPT(KUSB, Kern::Printf("Release Interface controller returned %d", r1));
2472 (void) iController->ReleaseInterface(this, aInterfaceNumber);
2481 void RealizeInterface_Dump(TUint* aMem)
2484 __KTRACE_OPT(KUSB, mem = aMem);
2488 Kern::Printf("Final chunk header State:");
2489 for (j=0; j<30; j+=8)
2490 Kern::Printf("%2x: %8x %8x %8x %8x %8x %8x %8x %8x", j, mem[j], mem[j+1], mem[j+2], mem[j+3], mem[j+4], mem[j+5], mem[j+6], mem[j+7] );
2497 Chunk Created, filled with structure, and passed back to userside.
2499 TInt DLddUsbcScChannel::RealizeInterface(void)
2502 return KErrUsbAlreadyRealized;
2504 TRealizeInfo bufInfo;
2506 TInt errorOrChunk = KErrNone;
2507 TBool openedCS = EFalse;
2510 // Start by creating a temporary scratchpad for endpoint calculations.
2511 bufInfo.Init(iAlternateSettingList);
2513 // Fill in our scratchpad with all the required endpoints, sorting them
2514 // in order of size required.
2515 errorOrChunk = bufInfo.CopyAndSortEndpoints();
2516 if (errorOrChunk!=KErrNone)
2521 // We now have endpoints sorted in order of size for each altsetting.
2522 // The very largest for each endpoint will share the first buffer, and all of
2523 // the second largest ends points will share the second buffer, and so on.
2524 // Find the highest buffer size for each row, to determine the buffer size,
2525 // and keep a total of total space needed.
2526 bufInfo.CalcBuffSizes();
2528 // We now have the max sizes wanted for each endpoint buffer.
2529 // we also have to total size for all endpoints.
2530 // and finally we have the total number of buffers.
2532 // Add on size for header, then add on size for guard pages.
2533 bufInfo.iTotalSize+= KHeaderSize + bufInfo.iTotalBuffers * KGuardSize;
2535 // Create shared Chunk . . . . . . . . . .
2536 if (iChunkInfo==NULL)
2538 NKern::ThreadEnterCS();
2540 errorOrChunk = TUsbcScChunkInfo::New(iChunkInfo, bufInfo.iTotalSize, (DLogicalDevice*) iDevice);
2541 if (errorOrChunk!=KErrNone)
2548 // As of writing, the was no way for iChunk to be anything other then NULL.
2549 // You cannot 'unrealise' and iChunk cannot be set any other way.
2550 Kern::Fault("DLddUsbcScChannel::RealizeInterface", __LINE__);
2553 // Populate the shared chunk . . . . . . .
2556 // First create chunk header.
2557 errorOrChunk = iChunkInfo->ChunkAlloc(offset, KHeaderSize);
2558 if (errorOrChunk!=KErrNone)
2560 if (errorOrChunk==-KErrNoMemory)
2561 errorOrChunk=KErrNoMemory;
2566 offset+=KHeaderSize + KGuardSize; // Also any more for EP0?
2568 // Next, lay out the geometry of the chunk header.
2570 bufInfo.LayoutChunkHeader(iChunkInfo);
2576 // Create K-side buffer table
2578 iBuffers = (TUsbcScBuffer *) Kern::AllocZ(sizeof(TUsbcScBuffer) * (bufInfo.iTotalBuffers+2)); // +2 is for ep0.
2581 __KTRACE_OPT(KUSB, Kern::Printf("Realize: Error: Alloc iBufers failed!"));
2582 errorOrChunk = KErrNoMemory;
2587 errorOrChunk = SetupEp0();
2590 __KTRACE_OPT(KUSB, Kern::Printf("Realize: SetupEp0 . ERROR %d",errorOrChunk));
2594 ep0Size = iEp0Endpoint->EndpointInfo()->iSize;
2595 __KTRACE_OPT(KUSB, Kern::Printf("Realize: Setup EP0. max packet size %d", ep0Size));
2597 // Create EP0 buffers
2598 iEP0OutBuff=bufInfo.iTotalBuffers;
2599 errorOrChunk = iBuffers[iEP0OutBuff].Construct(KUsbcScBiOut, this, KUsbScEP0OutBufPos, KUsbScEP0OutBufEnd, ep0Size, ep0Size, ep0Size);
2602 __KTRACE_OPT(KUSB, Kern::Printf("Realize: Setup EP0 Out. ERROR %d",errorOrChunk));
2606 iBuffers[iEP0OutBuff].CreateChunkBufferHeader();
2607 iBuffers[iEP0OutBuff].iCallback = iEp0Endpoint->iRequestCallbackInfo;
2608 ((TUsbcScBufferRecord*) &(
2609 bufInfo.iChunkStuct->iBufferOffset[KUsbcScEp0OutBuff*sizeof(TUsbcScBufferRecord)]
2610 )) ->Set(KUsbScEP0OutBufPos, KUsbScEP0OutBufEnd);
2613 iEP0InBuff=bufInfo.iTotalBuffers+1;
2614 errorOrChunk = iBuffers[iEP0InBuff].Construct( KUsbcScBiIn , this, KUsbScEP0InBufPos , KUsbScEP0InBufEnd , ep0Size, ep0Size, ep0Size);
2617 __KTRACE_OPT(KUSB, Kern::Printf("Realize: Setup EP0 In. ERROR %d",errorOrChunk));
2621 iBuffers[iEP0InBuff].iCallback = iEp0Endpoint->iRequestCallbackInfo;
2623 ((TUsbcScBufferRecord*) &(
2624 bufInfo.iChunkStuct->iBufferOffset[KUsbcScEp0InBuff*sizeof(TUsbcScBufferRecord)]
2625 ))->Set(KUsbScEP0InBufPos, KUsbScEP0InBufEnd);
2628 } // end ep0Size scope
2630 // Create resources and tables. . . . . .
2631 __KTRACE_OPT(KUSB, Kern::Printf("Realize: Create resources tables"));
2633 { // scope of bufNum
2634 // For each EP buffer
2637 TInt endpointNumber;
2638 TUsbcScEndpoint* endpointRecord;
2641 TEndpointSortBufs* bufsd;
2642 TUsbcScHdrEndpointRecord* epRecord;
2643 for (endpoint=0; endpoint<bufInfo.iMaxEndpoints; endpoint++) // endpoint = buf row.
2645 for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
2647 buffMinSize = KUsbSc_BigBuff_MinimumRamRun;
2649 TInt needed = bufInfo.iBufs[inout].iSizes[endpoint];
2652 TInt bufStart = offset;
2654 __KTRACE_OPT(KUSB, Kern::Printf("Realize: buf row:%d inout %d, iBufferOffset[%d+2]=%x",endpoint, inout, buffNum, bufStart));
2656 bufsd = &(bufInfo.iBufs[inout]);
2657 // and then point all endpoints that use it, towards it.
2659 TUint maxReadSize = ~0;
2660 for (altSetting=0; altSetting < bufInfo.iAltSettings; altSetting++)
2662 endpointRecord =bufsd->iEp[altSetting*bufInfo.iMaxEndpoints + endpoint];
2665 endpointNumber = endpointRecord->EpNumber();
2666 endpointRecord->SetBuffer(&iBuffers[buffNum]);
2668 epRecord = (TUsbcScHdrEndpointRecord*) &iChunkInfo->iChunkMem[
2669 (bufInfo.iAltSettingsTbl->iAltTableOffset[altSetting]) // i.e. Just after altSettingsTbl
2670 +sizeof(TInt) // after number of endpoints field
2671 +(endpointNumber-1)*sizeof(TUsbcScHdrEndpointRecord)
2673 epRecord->iBufferNo = (TUint8) buffNum;
2675 TInt epType=(endpointRecord->EndpointInfo()->iType);
2676 epType= (epType& KUsbEpTypeControl)?KUsbScHdrEpTypeControl:
2677 (epType& KUsbEpTypeIsochronous)?KUsbScHdrEpTypeIsochronous:
2678 (epType& KUsbEpTypeBulk)?KUsbScHdrEpTypeBulk:
2679 (epType& KUsbEpTypeInterrupt)?KUsbScHdrEpTypeInterrupt:KUsbScHdrEpTypeUnknown;
2681 epRecord->iType = (inout+1) | (epType<<2);
2683 if (endpointRecord->EndpointInfo()->iReadSize)
2684 maxReadSize = (maxReadSize <= endpointRecord->EndpointInfo()->iReadSize) ? maxReadSize : endpointRecord->EndpointInfo()->iReadSize;
2686 __KTRACE_OPT(KUSB, Kern::Printf("Realize: endpointNum %d in altSetting %d, alt table @ %d",
2687 endpointNumber, altSetting,bufInfo.iAltSettingsTbl->iAltTableOffset[altSetting]));
2691 __KTRACE_OPT(KUSB, Kern::Printf("Realize: endpointNum NA in altSetting %d", altSetting));
2697 // Alloc memory for buffer.
2698 TInt grabSize = needed;
2699 // Generally, a buffer fragmented into smaller memory regions will reduce the efficiency
2700 // of reading or writing data, and so avoiding the allocation of very small sections
2702 // However, if only a small amount is being allocated to start with, it is likely
2703 // smaller amounts of data are to be sent (reducing this advantage), and 1 memory page
2704 // is a much bigger proportion of the buffer, and so more worth allocating individually.
2707 if (needed<KUsbScBigBuffIs)
2709 minimumGrab=Kern::RoundToPageSize(1);
2710 buffMinSize = KUsbSc_SmallBuff_MinimumRamRun; // 1k
2714 minimumGrab = buffMinSize+Kern::RoundToPageSize(1);
2717 // Grab required memory, in bits as big as possible, down to the minimum size.
2718 while (needed >= minimumGrab)
2721 r = iChunkInfo->ChunkAlloc(offset, grabSize);
2729 if (r==-KErrNoMemory)
2733 if ((grabSize<minimumGrab) || (r!=-KErrNoMemory))
2739 } // end while needed
2741 // Initialize buffer
2742 iBuffers[buffNum].Construct(inout, this, bufStart, offset, buffMinSize, 0, maxReadSize);
2743 iBuffers[buffNum].CreateChunkBufferHeader();
2744 ((TUsbcScBufferRecord*) &(
2745 bufInfo.iChunkStuct->iBufferOffset[(buffNum+2)*sizeof(TUsbcScBufferRecord)]
2746 ))->Set(bufStart, offset);
2749 // inc pointers for next buffer
2755 } // end for each buffer
2756 } // scope of bufNum
2759 RealizeInterface_Dump((TUint*) iChunkInfo->iChunkMem); // Debug only tracing
2763 __KTRACE_OPT(KUSB, Kern::Printf("Realize: cleanup. Err=%d", errorOrChunk));
2764 // Here we clean up after either success, or after bailing out early.
2770 if (errorOrChunk==KErrNone)
2772 // Everything is looking good - create RChunk for Userside.
2773 errorOrChunk = Kern::MakeHandleAndOpen(iClient, iChunkInfo->iChunk);
2774 iRealizeCalled = (errorOrChunk>=0);
2775 } // endif errorOrChunk
2777 if (errorOrChunk<0) // If error, destroy the chunk.
2779 iChunkInfo->Close();
2780 // ChunkInfo will delete itself with DFC, but the pointer here is no longer needed.
2787 for (i=0; i<(iNumBuffers+2); i++)
2789 iBuffers[i].iStatusList.Destroy();
2791 Kern::Free(iBuffers);
2798 iNumBuffers = bufInfo.iTotalBuffers;
2799 iValidInterface = ETrue; // Let the games commence!
2802 } // endif iChunkInfo
2804 NKern::ThreadLeaveCS();
2806 __KTRACE_OPT(KUSB, Kern::Printf("Realize: returning %x (%d)", errorOrChunk, errorOrChunk));
2807 return errorOrChunk;
2808 } // End RealizeInterface
2812 // DestroyAllInterfaces
2815 void DLddUsbcScChannel::DestroyAllInterfaces()
2817 __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyAllInterfaces"));
2818 // Removes all interfaces
2819 if (iAlternateSettingList)
2821 if (iAlternateSettingList->iHead != NULL)
2823 TUsbcScAlternateSetting* alternateSettingListRec = iAlternateSettingList->iTail;
2824 while (alternateSettingListRec)
2826 iAlternateSettingList->iTail = alternateSettingListRec->iPrevious;
2827 // If this contains NULL now that is only possible if the record to be deleted was at the head
2828 __KTRACE_OPT(KUSB, Kern::Printf("Release interface %d \n", alternateSettingListRec->iSetting));
2829 iController->ReleaseInterface(this, alternateSettingListRec->iSetting);
2830 delete alternateSettingListRec;
2831 if (iAlternateSettingList->iTail == NULL) //No more interfaces left
2835 iAlternateSettingList->iTail->iNext = NULL;
2836 alternateSettingListRec = iAlternateSettingList->iTail;
2840 delete iAlternateSettingList;
2843 iNumberOfEndpoints = 0;
2844 iAlternateSettingList = NULL;
2845 iValidInterface = EFalse;
2847 __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyAllInterfaces done"));
2858 void DLddUsbcScChannel::DestroyInterface(TUint aInterfaceNumber)
2860 __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyInterface \n"));
2862 if (iAlternateSetting == aInterfaceNumber)
2864 ResetInterface(KErrUsbInterfaceNotReady);
2865 iValidInterface = EFalse;
2866 iNumberOfEndpoints = 0;
2868 if (iAlternateSettingList)
2870 TUsbcScAlternateSetting* alternateSettingListRec = iAlternateSettingList->iTail;
2871 TUsbcScAlternateSetting* alternateSettingListRecFound = NULL;
2872 while (alternateSettingListRec)
2874 if (alternateSettingListRec->iSetting == aInterfaceNumber)
2876 alternateSettingListRecFound = alternateSettingListRec;
2877 if (alternateSettingListRec->iPrevious == NULL) //Interface is at HEAD OF List, Should only be if Interface is also at Tail of list
2879 iAlternateSettingList->iHead = alternateSettingListRec->iNext; // Should be NULL
2880 if (alternateSettingListRec->iNext)
2881 iAlternateSettingList->iHead->iPrevious = NULL;
2883 else if (alternateSettingListRec->iNext == NULL) //Interface is at TAIL OF List
2885 iAlternateSettingList->iTail = alternateSettingListRecFound->iPrevious;
2886 iAlternateSettingList->iTail->iNext = NULL;
2888 else //Somewhere in the middle (would not expect this in normal operation, but here for completeness)
2890 __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyInterface Middle interface!\n"));
2891 alternateSettingListRec->iPrevious->iNext = alternateSettingListRec->iNext;
2892 alternateSettingListRec->iNext->iPrevious = alternateSettingListRec->iPrevious;
2895 delete alternateSettingListRecFound;
2898 alternateSettingListRec = alternateSettingListRec->iPrevious;
2907 TInt DLddUsbcScChannel::SetupEp0()
2909 __ASSERT_ALWAYS(iEp0Endpoint==NULL, Kern::Fault("DLddUsbcScChannel::SetupEp0", __LINE__));
2911 TUsbcScEndpointInfo ep0Info = TUsbcScEndpointInfo(KUsbEpTypeControl, KUsbEpDirBidirect);
2912 ep0Info.iSize = iController->Ep0PacketSize();
2914 TUsbcScEndpoint* ep0 = new TUsbcScEndpoint(this, iController, &ep0Info, 0);
2917 return KErrNoMemory;
2920 TInt r = ep0->Construct();
2924 return KErrNoMemory;
2927 ep0->SetRealEpNumber(0);
2928 ep0->SetBuffer(NULL); // Cannot find it this way.
2938 void DLddUsbcScChannel::DestroyEp0()
2940 __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DestroyEp0"));
2941 delete iEp0Endpoint;
2942 iEp0Endpoint = NULL;
2946 void DLddUsbcScChannel::RequestCallbackEp0(TAny* aDLddUsbcScChannel)
2948 DLddUsbcScChannel* channel = (DLddUsbcScChannel*) aDLddUsbcScChannel;
2950 __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::RequestCallbackEp0"));
2952 if (channel->ChannelClosing())
2954 __KTRACE_OPT(KUSB, Kern::Printf("Channel Closing: Completion not accepted!"));
2958 switch (channel->iEp0Endpoint->iRequestCallbackInfo->iTransferDir)
2960 case EControllerWrite:
2961 channel->iBuffers[channel->iEP0InBuff].CompleteWrite();
2963 case EControllerRead:
2964 channel->iBuffers[channel->iEP0OutBuff].CompleteRead();
2967 Kern::Printf("DLddUsbcScChannel::RequestCallbackEp0 - Unexpected completion direction %d",channel->iEp0Endpoint->iRequestCallbackInfo->iTransferDir);
2968 Kern::Fault("DLddUsbcScChannel::RequestCallbackEp0", __LINE__);
2978 // EndpointStatusChangeCallback
2981 void DLddUsbcScChannel::EndpointStatusChangeCallback(TAny* aDLddUsbcScChannel)
2983 __KTRACE_OPT(KUSB, Kern::Printf("EndpointStatusChangeCallback"));
2984 DLddUsbcScChannel* dUsbc = (DLddUsbcScChannel*) aDLddUsbcScChannel;
2985 if (dUsbc->iChannelClosing)
2987 TUint endpointState = dUsbc->iEndpointStatusCallbackInfo.State();
2988 const TInt reqNo = (TInt) RDevUsbcScClient::ERequestEndpointStatusNotify;
2989 if (dUsbc->iRequestStatus[reqNo])
2991 __KTRACE_OPT(KUSB, Kern::Printf("EndpointStatusChangeCallback Notify status"));
2992 DThread* client = dUsbc->iClient;
2993 // set client descriptor length to zero
2994 TInt r = Kern::ThreadRawWrite(client, dUsbc->iEndpointStatusChangePtr, &endpointState,
2995 sizeof(TUint), client);
2997 dUsbc->PanicClientThread(r);
2998 Kern::RequestComplete(dUsbc->iClient, dUsbc->iRequestStatus[reqNo], r);
2999 dUsbc->iEndpointStatusChangePtr = NULL;
3005 // StatusChangeCallback
3008 void DLddUsbcScChannel::StatusChangeCallback(TAny* aDLddUsbcScChannel)
3010 DLddUsbcScChannel* dUsbc = (DLddUsbcScChannel*) aDLddUsbcScChannel;
3011 if (dUsbc->iChannelClosing)
3014 TUsbcDeviceState deviceState;
3017 (i < KUsbcDeviceStateRequests) && ((deviceState = dUsbc->iStatusCallbackInfo.State(i)) != EUsbcNoState);
3020 __KTRACE_OPT(KUSB, Kern::Printf("StatusChangeCallBack status=%d", deviceState));
3021 if (deviceState & KUsbAlternateSetting)
3023 dUsbc->ProcessAlternateSetting(deviceState);
3027 dUsbc->ProcessDeviceState(deviceState);
3028 // Send Status to EP0 buffer.
3029 dUsbc->iBuffers[dUsbc->iEP0OutBuff].SendEp0StatusPacket(deviceState);
3032 // Only queue if userside is interested
3033 if (dUsbc->iDeviceStatusNeeded)
3035 dUsbc->iStatusFifo->AddStatusToQueue(deviceState);
3036 const TInt reqNo = (TInt) RDevUsbcScClient::ERequestAlternateDeviceStatusNotify;
3037 if (dUsbc->AlternateDeviceStateTestComplete())
3038 Kern::RequestComplete(dUsbc->iClient, dUsbc->iRequestStatus[reqNo], KErrNone);
3041 // We don't want to be interrupted in the middle of this:
3042 const TInt irqs = NKern::DisableInterrupts(2);
3043 dUsbc->iStatusCallbackInfo.ResetState();
3044 NKern::RestoreInterrupts(irqs);
3048 void DLddUsbcScChannel::OtgFeatureChangeCallback(TAny* aDLddUsbcScChannel)
3050 __KTRACE_OPT(KUSB, Kern::Printf("OtgFeatureChangeCallback"));
3051 DLddUsbcScChannel* dUsbc = (DLddUsbcScChannel*) aDLddUsbcScChannel;
3052 if (dUsbc->iChannelClosing)
3056 // No return value check. Assume OTG always supported here
3057 dUsbc->iController->GetCurrentOtgFeatures(features);
3059 const TInt reqNo = (TInt) RDevUsbcScClient::ERequestOtgFeaturesNotify;
3060 if (dUsbc->iRequestStatus[reqNo])
3062 __KTRACE_OPT(KUSB, Kern::Printf("OtgFeatureChangeCallback Notify status"));
3063 TInt r = Kern::ThreadRawWrite(dUsbc->iClient, dUsbc->iOtgFeatureChangePtr,
3064 &features, sizeof(TUint8), dUsbc->iClient);
3066 dUsbc->PanicClientThread(r);
3067 Kern::RequestComplete(dUsbc->iClient, dUsbc->iRequestStatus[reqNo], r);
3068 dUsbc->iOtgFeatureChangePtr = NULL;
3074 // SelectAlternateSetting
3077 TInt DLddUsbcScChannel::SelectAlternateSetting(TUint aAlternateSetting)
3079 TUsbcScEndpoint* ep;
3081 // First, find the alt setting record, which corresponds to the alt setting number.
3082 TUsbcScAlternateSetting* alternateSettingListRec;
3083 if(iAlternateSettingList)
3085 for (alternateSettingListRec = iAlternateSettingList->iHead; alternateSettingListRec; alternateSettingListRec = alternateSettingListRec->iNext)
3086 if (alternateSettingListRec->iSetting == aAlternateSetting)
3088 // Record has been located.
3090 // Update current ep setting vars
3091 iEndpoint = alternateSettingListRec->iEndpoint;
3092 iNumberOfEndpoints = alternateSettingListRec->iNumberOfEndpoints;
3096 // Reset buffers for new ep set
3097 for (TInt i = 1; i <= KMaxEndpointsPerClient; i++)
3099 ep = alternateSettingListRec->iEndpoint[i];
3101 ep->StartBuffer(); // Buffer::StartEndpoint(...) sets the necessary parameters to the buffer, for use for a perticular endpoint.
3110 /* The user calls this to move into the next alternate setting. After this call, it is assumed the user wants to
3111 Transmit using endpoints belonging to this alternate Setting. Writes to the IN endpoints will be allowed until
3112 the host changed the alternate setting again
3113 Returns a 32 int with the top 16 bits represents the sequance, and the botten, the alternatre setting no.
3115 TInt32 DLddUsbcScChannel::StartNextInAlternateSetting()
3117 iUserKnowsAltSetting = ETrue;
3118 return iAsSeq<<16 | iAlternateSetting;
3123 // EpFromAlternateSetting
3126 TInt DLddUsbcScChannel::EpFromAlternateSetting(TUint aAlternateSetting, TInt aEndpoint)
3128 TUsbcScAlternateSetting* alternateSettingListRec = iAlternateSettingList->iHead;
3129 while (alternateSettingListRec)
3131 if (alternateSettingListRec->iSetting == aAlternateSetting)
3133 if ((aEndpoint <= alternateSettingListRec->iNumberOfEndpoints) &&
3136 return alternateSettingListRec->iEndpoint[aEndpoint]->RealEpNumber();
3140 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: aEndpoint %d wrong for aAlternateSetting %d",
3141 aEndpoint, aAlternateSetting));
3142 return KErrNotFound;
3145 alternateSettingListRec = alternateSettingListRec->iNext;
3147 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: no aAlternateSetting %d found", aAlternateSetting));
3148 return KErrNotFound;
3152 // ProcessAlternateSetting
3155 TInt DLddUsbcScChannel::ProcessAlternateSetting(TUint aAlternateSetting)
3158 TUint newSetting = aAlternateSetting&(~KUsbAlternateSetting);
3159 __KTRACE_OPT(KUSB, Kern::Printf("ProcessAlternateSetting 0x%08x selecting alternate setting 0x%08x", aAlternateSetting, newSetting));
3160 iUserKnowsAltSetting=EFalse;
3161 iAlternateSetting = newSetting;
3164 ResetInterface(KErrUsbInterfaceChange); // kill any outstanding IN transfers
3166 TInt r = SelectAlternateSetting(newSetting);
3177 // ProcessDeviceState
3179 // Called from StatusChangeCallback.
3181 TInt DLddUsbcScChannel::ProcessDeviceState(TUsbcDeviceState aDeviceState)
3183 __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::ProcessDeviceState(%d -> %d)", iDeviceState, aDeviceState));
3184 if (iDeviceState == aDeviceState)
3186 __KTRACE_OPT(KUSB, Kern::Printf(" No state change => nothing to be done."));
3189 if (iDeviceState == EUsbcDeviceStateSuspended)
3191 __KTRACE_OPT(KUSB, Kern::Printf(" Coming out of Suspend: old state = %d", iOldDeviceState));
3192 iDeviceState = iOldDeviceState;
3193 if (iDeviceState == aDeviceState)
3195 __KTRACE_OPT(KUSB, Kern::Printf(" New state same as before Suspend => nothing to be done."));
3199 TBool renumerateState = (aDeviceState == EUsbcDeviceStateConfigured);
3200 TBool deconfigured = EFalse;
3201 TInt cancellationCode = KErrNone;
3202 if (aDeviceState == EUsbcDeviceStateSuspended)
3204 __KTRACE_OPT(KUSB, Kern::Printf(" Suspending..."));
3205 iOldDeviceState = iDeviceState;
3206 // Put PSL into low power mode here
3210 deconfigured = (iDeviceState == EUsbcDeviceStateConfigured &&
3211 aDeviceState != EUsbcDeviceStateConfigured);
3212 if (iDeviceState == EUsbcDeviceStateConfigured)
3214 if (aDeviceState == EUsbcDeviceStateUndefined)
3215 cancellationCode = KErrUsbCableDetached;
3216 else if (aDeviceState == EUsbcDeviceStateAddress)
3217 cancellationCode = KErrUsbDeviceNotConfigured;
3218 else if (aDeviceState == EUsbcDeviceStateDefault)
3219 cancellationCode = KErrUsbDeviceBusReset;
3221 cancellationCode = KErrUsbDeviceNotConfigured;
3224 iDeviceState = aDeviceState;
3225 if (iValidInterface || iOwnsDeviceControl)
3228 // This LDD may not own an interface. It could be some manager reenumerating
3229 // after its subordinate LDDs have setup their interfaces.
3232 DeConfigure(cancellationCode);
3234 else if (renumerateState)
3236 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChannel:: Reumerated!"));
3237 // Select main interface & latch in new endpoint set
3238 SelectAlternateSetting(0);
3239 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChannel:: StartReads!"));
3244 const TInt reqNo = (TInt) RDevUsbcScClient::ERequestReEnumerate;
3245 if (renumerateState && iRequestStatus[reqNo])
3247 // This lot must be done if we are reenumerated
3248 Kern::RequestComplete(iClient, iRequestStatus[reqNo], KErrNone);
3255 TBool DLddUsbcScChannel::AlternateDeviceStateTestComplete()
3257 TBool completeNow = EFalse;
3258 const TInt reqNo = (TInt) RDevUsbcScClient::ERequestAlternateDeviceStatusNotify;
3259 if (iRequestStatus[reqNo])
3261 // User req is outstanding
3262 TUint32 deviceState;
3263 if (iStatusFifo->GetDeviceQueuedStatus(deviceState) == KErrNone)
3265 // Device state waiting to be sent userside
3266 completeNow = ETrue;
3267 __KTRACE_OPT(KUSB, Kern::Printf("StatusChangeCallback Notify status"));
3268 // set client descriptor length to zero
3269 TInt r = Kern::ThreadRawWrite(iClient, iStatusChangePtr, &deviceState,
3270 sizeof(TUint32), iClient);
3272 PanicClientThread(r);
3273 iStatusChangePtr = NULL;
3280 void DLddUsbcScChannel::DeConfigure(TInt aErrorCode)
3282 __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DeConfigure()"));
3283 // Called after deconfiguration. Cancels transfers on all endpoints.
3284 ResetInterface(aErrorCode);
3285 // Cancel the endpoint status notify request if it is outstanding.
3286 const TInt KEpNotReq = RDevUsbcScClient::ERequestEndpointStatusNotify;
3287 if (iRequestStatus[KEpNotReq])
3289 CancelNotifyEndpointStatus();
3290 Kern::RequestComplete(iClient, iRequestStatus[KEpNotReq], aErrorCode);
3292 // We have to reset the alternate setting number when the config goes away.
3293 SelectAlternateSetting(0);
3294 iAlternateSetting = 0;
3298 void DLddUsbcScChannel::StartEpReads()
3300 // Queued after enumeration. Starts reads on all endpoints.
3301 // The endpoint itself decides if it can do a read
3302 __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 1"));
3307 for (i=0; i<iNumBuffers; i++)
3309 __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 2 %d",i));
3311 needsPacket = iBuffers[i].iNeedsPacket;
3314 __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 3"));
3315 iBuffers[i].UpdateBufferList(0,0,(needsPacket==TUsbcScBuffer::KEpIsStarting));
3319 __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 4"));
3322 iBuffers[iEP0OutBuff].Ep0CancelLddRead();
3323 iBuffers[iEP0OutBuff].UpdateBufferList(0,0);
3324 __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 5"));
3329 void DLddUsbcScChannel::ResetInterface(TInt aErrorCode)
3331 if (!iValidInterface && !iOwnsDeviceControl)
3335 for (i=0; i<iNumBuffers; i++)
3337 iBuffers[i].iNeedsPacket=TUsbcScBuffer::KNoEpAssigned;
3340 TUsbcScBuffer* buffer;
3342 for (i = 1; i <= iNumberOfEndpoints; i++)
3344 // Firstly, cancel ('garbge collect') any stale reads/writes into PIL.
3346 __KTRACE_OPT(KUSB, Kern::Printf("Cancelling transfer ep=%d", i));
3347 iEndpoint[i]->AbortTransfer();
3349 // All OUT endpoints need a packet sent, to indicate the termination of the current ep 'pipe'.
3350 // This will complete any current read, or will be read later.
3351 // All IN endpoints must be simply cancelled, including anything queued.
3352 // Ep0 operates outside alt settings, and so we don't cancel anything.
3354 buffer=iEndpoint[i]->GetBuffer();
3355 if (buffer->iDirection==KUsbcScIn)
3357 buffer->iStatusList.Complete(KErrCancel); //aErrorCode
3358 buffer->iStatusList.CancelQueued(); //aErrorCode
3361 buffer->iNeedsPacket=TUsbcScBuffer::KEpIsEnding; // We will send a packet on re-start, which doubles as a 'cancel'
3362 // for the old alt setting.
3368 void DLddUsbcScChannel::EmergencyCompleteDfc(TAny* aDLddUsbcScChannel)
3370 ((DLddUsbcScChannel*) aDLddUsbcScChannel)->DoEmergencyComplete();
3373 TInt DLddUsbcScChannel::DoEmergencyComplete()
3375 __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DoEmergencyComplete"));
3376 // cancel any pending DFCs
3377 // complete all client requests
3379 TUsbcScBuffer* buffer;
3381 // Complete EP0 request
3383 TInt direction=iEp0Endpoint->iRequestCallbackInfo->iTransferDir;
3384 if (direction==EControllerWrite)
3386 iBuffers[iEP0InBuff].iStatusList.CancelQueued();
3387 iBuffers[iEP0InBuff].iStatusList.Complete(KErrDisconnected);
3389 else if (direction==EControllerRead)
3391 iBuffers[iEP0OutBuff].iStatusList.CancelQueued();
3392 iBuffers[iEP0OutBuff].iStatusList.Complete(KErrDisconnected);
3395 // Complete other Eps request
3396 for (i = 1; i <= iNumberOfEndpoints; i++)
3398 __KTRACE_OPT(KUSB, Kern::Printf("Cancelling transfer ep=%d", i));
3399 buffer=iEndpoint[i]->GetBuffer();
3400 buffer->iStatusList.CancelQueued();
3401 buffer->iStatusList.Complete(KErrDisconnected);
3404 // Complete remaining requests
3406 for (TInt i = 0; i < KUsbcMaxRequests; i++)
3408 if (iRequestStatus[i])
3410 __KTRACE_OPT(KUSB, Kern::Printf("Complete request 0x%x", iRequestStatus[i]));
3411 Kern::RequestComplete(iClient, iRequestStatus[i], KErrDisconnected);
3414 iStatusCallbackInfo.Cancel();
3415 iEndpointStatusCallbackInfo.Cancel();
3416 iOtgFeatureCallbackInfo.Cancel();
3422 void DLddUsbcScChannel::PanicClientThread(TInt aReason)
3424 Kern::ThreadKill(iClient, EExitPanic, aReason, KUsbLDDKillCat);
3427 // End DLddUsbcScChannel
3429 /*****************************************************************************\
3434 \*****************************************************************************/
3438 TUsbcScEndpoint::TUsbcScEndpoint(DLddUsbcScChannel* aLDD, DUsbClientController* aController,
3439 const TUsbcScEndpointInfo* aEndpointInfo, TInt aEndpointNum
3441 : iRequestCallbackInfo(NULL),
3442 iController(aController),
3443 iEndpointInfo(*aEndpointInfo),
3444 iClientReadPending(EFalse),
3445 iClientWritePending(EFalse),
3446 iEndpointNumber(aEndpointNum),
3450 iBytesTransferred(0),
3453 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::TUsbcScEndpoint"));
3457 TInt TUsbcScEndpoint::Construct()
3459 __KTRACE_OPT(KUSB,Kern::Printf("TUsbcScEndpoint::TUsbcScEndpoint iEndpointNumber %d\n",iEndpointNumber));
3461 iRequestCallbackInfo = new TUsbcRequestCallback(iLdd,
3463 (iEndpointNumber==0)?DLddUsbcScChannel::RequestCallbackEp0:TUsbcScEndpoint::RequestCallback,
3464 (iEndpointNumber==0)? (TAny*) iLdd: (TAny*) this,
3466 KUsbRequestCallbackPriority);
3468 return (iRequestCallbackInfo == NULL)?KErrNoMemory:KErrNone;
3472 TUsbcScEndpoint::~TUsbcScEndpoint()
3474 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::~TUsbcScEndpoint(%d)", iEndpointNumber));
3476 delete iRequestCallbackInfo;
3479 // This is called by the PIL, on return from a read or write.
3480 // Inturn it calls either the read or write function for that buffer.
3482 void TUsbcScEndpoint::RequestCallback(TAny* aTUsbcScEndpoint)
3484 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::RequestCallback"));
3486 if (((TUsbcScEndpoint*)aTUsbcScEndpoint)->iLdd->ChannelClosing())
3488 __KTRACE_OPT(KUSB, Kern::Printf("Channel Closing: Completion not accepted!"));
3492 switch (((TUsbcScEndpoint*) aTUsbcScEndpoint)->iRequestCallbackInfo->iTransferDir)
3494 case EControllerWrite:
3495 ((TUsbcScEndpoint*) aTUsbcScEndpoint)->iBuffer->CompleteWrite();
3497 case EControllerRead:
3498 ((TUsbcScEndpoint*) aTUsbcScEndpoint)->iBuffer->CompleteRead();
3501 Kern::Printf("TUsbcScEndpoint::RequestCallback - Unexpected compleation direction %d",((TUsbcScEndpoint*) aTUsbcScEndpoint)->iRequestCallbackInfo->iTransferDir);
3502 Kern::Fault("TUsbcScEndpoint::RequestCallback", __LINE__);
3509 This is used to tidy up cancel calls into the PIL, regardless of them being reads or writes
3513 void TUsbcScEndpoint::AbortTransfer()
3515 if (!iLdd->iRealizeCalled)
3517 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::AbortTransfer Ep# %d Real Ep # %d - N.R.",iEndpointNumber, iRealEpNumber));
3522 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::AbortTransfer Ep# %d Real Ep # %d",iEndpointNumber, iRealEpNumber));
3526 if (iBuffer && (iBuffer->iStatusList.iState) || (!iRealEpNumber))
3528 if (iRequestCallbackInfo->iTransferDir==EControllerWrite)
3529 iController->CancelWriteBuffer(iLdd, iRealEpNumber);
3530 else if (iRequestCallbackInfo->iTransferDir==EControllerRead)
3531 iController->CancelReadBuffer(iLdd, iRealEpNumber);
3534 if (iEndpointNumber!=0) // endpoint zero starts off not sent in any direction, then keeps changing.
3536 __KTRACE_OPT(KUSB,Kern::Printf("\nTUsbcScEndpoint::AbortTransfer WARNING: Invalid Direction %d on (%d,%d)!\n",iRequestCallbackInfo->iTransferDir,iEndpointNumber, iRealEpNumber));
3540 __KTRACE_OPT(KUSB, Kern::Printf("\nTUsbcScEndpoint::AbortTransfer Can't stop direction %d on (%d,%d)!\n",iRequestCallbackInfo->iTransferDir,iEndpointNumber, iRealEpNumber));
3546 __KTRACE_OPT(KUSB,Kern::Printf("\nTUsbcScEndpoint::AbortTransfer WARNING: iBuffer is NULL on (%d,%d)\n",iEndpointNumber, iRealEpNumber));
3550 if (iRequestCallbackInfo)
3551 iRequestCallbackInfo->iDfc.Cancel();
3554 __KTRACE_OPT(KUSB,Kern::Printf("\nTUsbcScEndpoint::AbortTransfer WARNING: iRequestCallbackInfo is NULL\n"));
3557 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint Done."));
3560 // End TUsbcScEndpoint
3563 /*****************************************************************************\
3564 * TUsbcScAlternateSettingList *
3568 \*****************************************************************************/
3571 TUsbcScAlternateSetting::TUsbcScAlternateSetting()
3574 iNumberOfEndpoints(0),
3577 for (TInt i = 0; i <= KMaxEndpointsPerClient; i++)
3579 iEndpoint[i] = NULL;
3584 TUsbcScAlternateSetting::~TUsbcScAlternateSetting()
3586 __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScAlternateSetting::~TUsbcScAlternateSetting()"));
3587 for (TInt i = 0; i <= KMaxEndpointsPerClient; i++)
3589 delete iEndpoint[i];
3593 // End TUsbcScAlternateSettingList
3597 TUsbcScAlternateSettingList::TUsbcScAlternateSettingList()
3603 TUsbcScAlternateSettingList::~TUsbcScAlternateSettingList()
3609 /*****************************************************************************\
3610 * TUsbcDeviceStatusQueue *
3614 \*****************************************************************************/
3617 TUsbcDeviceStatusQueue::TUsbcDeviceStatusQueue()
3623 void TUsbcDeviceStatusQueue::FlushQueue()
3625 for (TInt i = 0; i < KUsbDeviceStatusQueueDepth; i++)
3627 iDeviceStatusQueue[i] = KUsbDeviceStatusNull;
3629 iStatusQueueHead = 0;
3633 void TUsbcDeviceStatusQueue::AddStatusToQueue(TUint32 aDeviceStatus)
3635 // Only add a new status if it is not a duplicate of the one at the head of the queue
3636 if (!(iStatusQueueHead != 0 &&
3637 iDeviceStatusQueue[iStatusQueueHead - 1] == aDeviceStatus))
3639 if (iStatusQueueHead == KUsbDeviceStatusQueueDepth)
3641 // Discard item at tail of queue
3643 GetDeviceQueuedStatus(status);
3645 iDeviceStatusQueue[iStatusQueueHead] = aDeviceStatus;
3651 TInt TUsbcDeviceStatusQueue::GetDeviceQueuedStatus(TUint32& aDeviceStatus)
3654 if (iStatusQueueHead <= 0)
3657 aDeviceStatus = KUsbDeviceStatusNull;
3661 aDeviceStatus = iDeviceStatusQueue[0];
3662 for(TInt i = 1; i < KUsbDeviceStatusQueueDepth; i++)
3664 TUint32 s = iDeviceStatusQueue[i];
3665 iDeviceStatusQueue[i - 1] = s;
3668 iDeviceStatusQueue[KUsbDeviceStatusQueueDepth - 1] = KUsbDeviceStatusNull;
3673 // End TUsbcDeviceStatusQueue