--- a/usbdrv/peripheral/ldd/perilddsc/src/d_usbcsc.cpp Tue Aug 31 17:01:47 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3663 +0,0 @@
-// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
-// All rights reserved.
-// This component and the accompanying materials are made available
-// under the terms of the License "Eclipse Public License v1.0"
-// which accompanies this distribution, and is available
-// at the URL "http://www.eclipse.org/legal/epl-v10.html".
-//
-// Initial Contributors:
-// Nokia Corporation - initial contribution.
-//
-// Contributors:
-//
-// Description:
-// e32\drivers\usbcsc\d_usbcsc.cpp
-// LDD for USB Device driver stack, using shared chunks:
-// The channel object.
-//
-//
-
-/**
- @file d_usbcsc.cpp
- @internalTechnology
-*/
-
-// #include <drivers/usbcsc.h>
-#include <usb/usbcsc.h>
-#include "platform.h"
-
-/*****************************************************************************\
-* DUsbcScLogDevice *
-* *
-* Inherits from DLogicalDevice, the USB Shared Chunk LDD factory class *
-* *
-\*****************************************************************************/
-
-_LIT(KUsbScLddName, "Usbcsc");
-
-static const TInt KUsbRequestCallbackPriority = 2;
-
-/** Real entry point from the Kernel: return a new driver.
- */
-DECLARE_STANDARD_LDD()
- {
- return new DUsbcScLogDevice;
- }
-
-/** Create a channel on the device.
-
- @internalComponent
-*/
-TInt DUsbcScLogDevice::Create(DLogicalChannelBase*& aChannel)
- {
- aChannel = new DLddUsbcScChannel;
- return aChannel ? KErrNone : KErrNoMemory;
- }
-
-
-DUsbcScLogDevice::DUsbcScLogDevice()
- {
- iParseMask = KDeviceAllowUnit;
- iUnitsMask = 0xffffffff; // Leave units decision to the Controller
- iVersion = TVersion(KUsbcScMajorVersion, KUsbcScMinorVersion, KUsbcScBuildVersion);
- }
-
-
-TInt DUsbcScLogDevice::Install()
- {
- // Only proceed if we have the Controller underneath us
- if (!DUsbClientController::UsbcControllerPointer())
- {
- __KTRACE_OPT(KPANIC, Kern::Printf("LDD Install: USB Controller Not Present"));
- return KErrGeneral;
- }
- return SetName(&KUsbScLddName);
- }
-
-
-//
-// Return the USB controller capabilities.
-//
-void DUsbcScLogDevice::GetCaps(TDes8& aDes) const
- {
- TPckgBuf<TCapsDevUsbc> b;
- b().version = iVersion;
- Kern::InfoCopy(aDes, b);
- }
-
-// End DUsbcScLogDevice
-
-/*****************************************************************************\
-* TUsbcScChunkInfo *
-* *
-* Where Chunk information is stored for the channel, and preseved for the *
-* life of the chunk. *
-* *
-\*****************************************************************************/
-
-void DfcChunkCleanup(TAny*);
-
-TUsbcScChunkInfo::TUsbcScChunkInfo(DLogicalDevice* aLdd)
- : iChunk(NULL),
- iCleanup((TDfcFn)&DfcChunkCleanup,this,Kern::SvMsgQue(),0),
- iChunkMem(NULL),
- iLdd(aLdd)
- {
- iPageNtz = (TInt8)__e32_find_ls1_32(Kern::RoundToPageSize(1));
- }
-
-TInt TUsbcScChunkInfo::CreateChunk(TInt aTotalSize)
- {
- // First, reserve an TUint of memory for each of pages needed to hold aTotalSize of memory.
- // This will form the chunk map, so that we can look up the memory geometry.
- iAllocatedSize = (aTotalSize>>iPageNtz)*sizeof(TUint);
- iPhysicalMap = (TUint*) Kern::AllocZ(iAllocatedSize);
- TInt r;
- if (iPhysicalMap==NULL)
- r = KErrNoMemory;
- else
- {
- TChunkCreateInfo chunkInfo;
- chunkInfo.iType = TChunkCreateInfo::ESharedKernelMultiple;
- chunkInfo.iMaxSize = aTotalSize;
- chunkInfo.iMapAttr = EMapAttrCachedMax;
- chunkInfo.iOwnsMemory = EFalse;
- chunkInfo.iDestroyedDfc = &iCleanup;
-
- TLinAddr chunkMem;
- r = Kern::ChunkCreate(chunkInfo, iChunk, chunkMem, iChunkMapAttr);
- iChunkMem = (TInt8*) chunkMem;
- if (r==KErrNone)
- iLdd->Open();
- }
-
- return r;
-}
-
-
-// This method requests closing the chunk.
-// Note that nothing may happen immediately, as something else may have the chunk open.
-void TUsbcScChunkInfo::Close()
-{
- Kern::ChunkClose(iChunk);
-}
-
-
-TInt TUsbcScChunkInfo::ChunkAlloc(TInt aOffset, TInt aSize)
- {
- TUint pageMask = (~0)<<iPageNtz;
- TUint rleMask = ~pageMask;
- TUint pageSize = rleMask+1;
- TInt r;
- TLinAddr physAddr;
-
- __KTRACE_OPT(KUSB, Kern::Printf("::chunkalloc AllocPhysicalRam aSize %d", aSize));
-
- r = Epoc::AllocPhysicalRam(aSize, physAddr);
- __KTRACE_OPT(KUSB, if (r!=KErrNone) Kern::Printf("::chunkalloc AllocPhysicalRam r=%d (Error!)", r));
- if (r==KErrNone)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("::chunkalloc ChunkCommitPhysical iChunk 0x%x size(%d), aOffset 0x%x, aSize 0x%x phsAddr 0x%x",
- iChunk, sizeof(DChunk), aOffset, aSize,physAddr ));
-
- r = Kern::ChunkCommitPhysical(iChunk, aOffset, aSize, physAddr);
- __KTRACE_OPT(KUSB, if (r!=KErrNone) Kern::Printf("::chunkalloc ChunkCommitPhysical r=%d (Error!)", r));
-
- if (r!=KErrNone)
- Epoc::FreePhysicalRam(physAddr, aSize);
- else
- { // record physical address and length in physical map
- TInt rle;
- TInt i=0;
- for (rle=(aSize>>iPageNtz); rle>0; rle--, i++,physAddr+=pageSize)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("::phys offset 0x%x = 0x%x",
- (aOffset>>iPageNtz)+i, (physAddr & pageMask) | ((rle>(TInt)rleMask)?(TInt)rleMask:rle)));
- iPhysicalMap[(aOffset>>iPageNtz)+i] = (physAddr & pageMask) | ((rle>(TInt)rleMask)?(TInt)rleMask:rle);
- }
- }
- }
- else if (r==KErrNoMemory)
- r = -KErrNoMemory; // Semi-expected error.
- return r;
- }
-
-/**
-This method retrieves the physical address of a given offset into the Chunk, and returns
-the length of contiguous physical memory from this point.
-
-@param aOffset the offset from the start of the chunk, to be queried.
-@param aPhysical a pointer to a TPhysAddr, to be filled with the physical
- address of the memory at the given offset.
-
-@returns the length of contiguous physical memory from the given offset.
-*/
-
-TInt TUsbcScChunkInfo::GetPhysical(TInt aOffset, TPhysAddr* aPhysical)
- {
- // Use masks, to retrieve the two components from the physical map, we created of the memory.
- TUint pageMask = (~0)<<iPageNtz;
- TUint val = iPhysicalMap[aOffset>>iPageNtz];
- *aPhysical=(val & pageMask)+(aOffset & ~pageMask);
- return ((val & ~pageMask)<<iPageNtz) - (aOffset & ~pageMask);
- }
-
-
-// DFC calls this fuction, which invokes the cleanup method.
-
-void DfcChunkCleanup(TAny* aChunkInfo)
- {
- ((TUsbcScChunkInfo*) aChunkInfo)->ChunkCleanup();
- }
-
-
-void TUsbcScChunkInfo::ChunkCleanup()
-{
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChunkInfo::ChunkCleanup()"));
- TUint physAddr;
- TInt length;
- TInt offset = 0;
-
- // The part of the field used for the physical page address.
- TUint pageMask = (~0)<<iPageNtz;
-
- // The part of the field used for the run length encoding, of the contiguous pages.
- TUint rleMask = ~pageMask;
- TInt records=(iAllocatedSize>>2);
-
- while (offset < records)
- {
- physAddr = iPhysicalMap[offset] & pageMask;
- length = iPhysicalMap[offset] & rleMask;
-
- if (physAddr>0)
- Epoc::FreePhysicalRam(physAddr, length);
-
- offset += (length>0)?length:1;
- }
- Kern::Free(iPhysicalMap);
-
- DLogicalDevice* ldd = iLdd;
- delete this;
- ldd->Close(NULL);
-}
-
-TInt TUsbcScChunkInfo::New(TUsbcScChunkInfo*& aChunk, TInt aSize, DLogicalDevice* aLdd)
-{
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChunkInfo::New totalSize %d", aSize));
-
- aChunk = new TUsbcScChunkInfo(aLdd);
- if (aChunk==NULL)
- {
- return KErrNoMemory;
- }
-
- TInt r = aChunk->CreateChunk(aSize);
- if (r!=KErrNone)
- {
- delete aChunk;
- aChunk=NULL;
- return r;
- }
-
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChunkInfo::New Created at 0x%x", aChunk->iChunkMem ));
- return KErrNone;
-}
-
-// End TUsbcScChunkInfo
-
-/*****************************************************************************\
-* TUsbcScBuffer *
-* *
-* Represents a buffer, within a chunk. Each buffers can be used by *
-* differt endpoint on differnt alt settings *
-* *
-\*****************************************************************************/
-
-
-TInt TUsbcScBuffer::Construct(TInt aDirection, DLddUsbcScChannel* aLdd, TInt aBufferOffset, TInt aBufferEndOffset, TInt aMinReadSize, TInt aMaxPacketSize, TInt aMaxReadSize)
- {
- TInt r;
-#ifdef _DEBUG
- iSequence = aBufferOffset; // Initialized at this, so that each buffer starts with a diffrent sequence number
-#endif
- iMinReadSize = aMinReadSize;
- TInt size = (aBufferEndOffset - aBufferOffset);
- TInt pageSize = Kern::RoundToPageSize(1);
- if (aMaxReadSize > 0)
- iMaxReadSize = aMaxReadSize;
- else
- iMaxReadSize = pageSize + ((size/3) & ~(pageSize -1));
- iLdd = aLdd;
- iDirection = aDirection;
- iMode=0;
- iChunkInfo = aLdd->iChunkInfo;
- iChunkAddr = (TLinAddr) (aLdd->iChunkInfo->iChunkMem); //aChunkAddr;
-
- TInt headerSize = sizeof(TUsbcScTransferHeader)-4; // TransferHeader includes 4 bytes of data.
-
-
- TUint maxAlignment; // Note: This is a mask for max Alignment,
-
- if (aMaxPacketSize)
- { // EP0 packets are not DMAed, and so dont need ialignment.
- iAlignMask = ~3;
- maxAlignment = 3;
- }
- else
- maxAlignment = 1023; // We don't know what the alignment requirement will be until enumeration, so assume worse case.
-
- iFirstPacket = aBufferOffset + sizeof(SUsbcScBufferHeader) + headerSize;
- iFirstPacket = (iFirstPacket + maxAlignment) & ~maxAlignment;
-
- iBufferStart = (SUsbcScBufferHeader *) (iChunkAddr+aBufferOffset);
- iBufferEnd = aBufferEndOffset;
-
- if ((iDirection&1)==KUsbcScOut)
- iHead = iFirstPacket-headerSize;//aBufferOffset + sizeof(SUsbcScBufferHeader);
- else
- iSent = 0;
-
- iStalled=0;
- iMaxPacketSize=0;
-
- r = iStatusList.Construct((aDirection==KUsbcScIn)?KUsbcScInRequests:KUsbcScOutRequests, iLdd->iClient);
- if (!r)
- {
- iMaxPacketSize = aMaxPacketSize; // Indicates configured if ep0, otherwise not.
- }
- return r;
- }
-
-
-void TUsbcScBuffer::CreateChunkBufferHeader()
-{
- if ((iDirection&1)==KUsbcScOut)
- {
- iBufferStart->iHead= iHead;
- iBufferStart->iTail= iHead; // Initially no data!
- iBufferStart->iBilTail=iHead;
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: iHead 0x%x bufferHeader 0x%x", iHead,iBufferStart ));
-
- // Dont need to round here, as we will round it up on endpoint change. (configuration)
- }
-}
-
-/*
-TUsbcScBuffer::StartEndpoint
-
-This method sets the nessesary paramenters to the buffer, for use for a particular endpoint.
-
-*/
-void TUsbcScBuffer::StartEndpoint(TUsbcRequestCallback* aRequestInfo, TUint aFlags)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartEndpoint (0x%x) : ep %d(%d)",this,aRequestInfo->iEndpointNum, aRequestInfo->iRealEpNum));
-
- iCallback=aRequestInfo;
- iMaxPacketSize = iLdd->iController->EndpointPacketSize(iLdd, aRequestInfo->iRealEpNum);
- iAlignMask = ~(((iMaxPacketSize+1) & 0xFFFFFFF8)-1);
- iMode = aFlags;
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartEndpoint : max Packets %d, mask 0x%x flags 0x%x", iMaxPacketSize, iAlignMask, iMode));
- if ((iDirection&1)==KUsbcScOut)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UsbcScOut\n"));
- // Add dummy packet (doesnt have to be aligned, which avoids what if it changes issue)
- // And Start next read.
- iNeedsPacket=KEpIsStarting;
- }
- }
-
-
-
-void TUsbcScBuffer::Destroy()
-{
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::Destroy()"));
- Cancel(KErrCancel);
- if (iLdd->iController && ((iDirection&1)==KUsbcScOut))
- { // Me must cancel reads to LDD to, an there will be no list for the callbacks to look into.
- iLdd->iController->CancelReadBuffer(iLdd, iCallback->iRealEpNum);
- }
- iStatusList.Destroy();
-}
-
-
-
-TInt TUsbcScBuffer::StartDataRead()
-{
- if (!iMaxPacketSize)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataRead() - Not Configured"));
- return KErrNone;
- }
- if (iStatusList.iState!=ENotRunning)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataRead() - Already Stated! (%d)",iStatusList.iState));
- return KErrNone;
- }
-
- TInt maxLength;
- TInt freeSpace;
- TPhysAddr physAddr;
-
- // get next request
- TUsbcScStatusElement* nextJob = iStatusList.Next();
- if (nextJob == NULL)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("No more jobs"));
- if (iMode && KUsbScCoupledRead)
- return KErrEof;
- iStatusList.iState=EReadingAhead;
- }
- else
- iStatusList.iState=EInProgress;
-
- TInt tail = iBufferStart->iTail;
- TInt headerSize = sizeof(TUsbcScTransferHeader)-4; // TransferHeader includes 4 bytes of data.
- maxLength = iChunkInfo->GetPhysical(iHead + headerSize, &physAddr); //returns all the bytes available after iHead + headerSize)
-
- __ASSERT_DEBUG(maxLength>0,Kern::Fault("TUsbcScBuffer::StartDataRead(", __LINE__));
-
-
- if (tail>iHead) // # # # H _ _ _ T # # # #
- {
- __KTRACE_OPT(KUSB,Kern::Printf("TUsbcScBuffer::StartDataRead() - tail 0x%x>head 0x%x, maxlength 0x%x", tail, iHead, maxLength));
-
- freeSpace = (tail & iAlignMask) - (iHead +headerSize + (~iAlignMask+1) ); // Cant read right up to last buffer, or head/tail will cross.
-
- if (freeSpace<iMinReadSize)
- {
- iStatusList.iState=ENotRunning;
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataRead() - Stall!!"));
- return KErrOverflow; // Read STALL !! !! !!
- }
-
- if (freeSpace<maxLength)
- maxLength = freeSpace;
- }
- if (maxLength> iMaxReadSize)
- maxLength = iMaxReadSize;
- // else tail<iHead (or empty) _ _ _ T # # # H _ _ _ _
- // We would not have set iHead here if too small. So must be ok.
-
- __ASSERT_DEBUG(maxLength>=iMinReadSize,Kern::Fault("TUsbcScBuffer::StartDataRead(", __LINE__));
-
- TUint8* data = ((TUsbcScTransferHeader *) (iHead + iChunkAddr))->iData.b;
- // set up callback stucture
-
- iCallback->SetRxBufferInfo(data, physAddr, iIndexArray, iSizeArray,maxLength);
- TInt r;
- // Go!!
- r = iLdd->iController->SetupReadBuffer(*iCallback);
- if (r!=KErrNone)
- {
- __KTRACE_OPT(KUSB,Kern::Printf("SetupReadBuffer Error: %d, RT %d",r, iStatusList.iState));
- iStatusList.Complete(r);
- }
- // After this, TUsbcScEndpoint::RequestCallback is called in a DFC.
- // This in turn calls either TUsbcScBuffer::CompleteRead.
- return KErrNone;
-}
-
-
-void TUsbcScBuffer::CompleteRead(TBool aStartNextRead)
-{
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::CompleteRead buff=%x",this));
-
- // The first packet always contains the total #of bytes
- const TInt byteCount = iCallback->iPacketSize[0];
- const TInt packetCount = iCallback->iRxPackets;
- iCallback->iRxPackets=0;
- TUint flags = 0;
-
- if (iCallback->iPacketSize[packetCount - 1] < (TUint) iMaxPacketSize)
- flags = KUsbcScShortPacket;
-
- UpdateBufferList(byteCount, flags, aStartNextRead);
-}
-
-
-// This method "submits" the current transfer, and starts off the next read.
-
-void TUsbcScBuffer::UpdateBufferList(TInt aByteCount,TUint aFlags, TBool aStartNextRead)
- {
-
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst aByteCount %d, flags 0x%x iHead 0x%x", aByteCount, aFlags, iHead));
-
- TInt headerSize = sizeof(TUsbcScTransferHeader)-4; // TransferHeader includes 4 bytes of data.
- TLinAddr dummy;
- __KTRACE_OPT(KUSB, Kern::Printf("iHead 0x%x headerSize 0x%x",iHead, headerSize));
-
- // Find iNext
-
- TInt next = iHead + headerSize + aByteCount; // next unused byte in buffer.
- TInt maxLength;
-
- // This may take a few loops before we settle on a value.
- do
- {
- // round up.
- next = (next + headerSize + ~iAlignMask) & iAlignMask;
- maxLength = iChunkInfo->GetPhysical(next, &dummy);
-
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst next %x buffer end %x min-read: %x maxRun %x", next, iBufferEnd, iMinReadSize, maxLength));
- // At the end of the buffer - wrap it if needbe.
- if ((TUint)(next + iMinReadSize) > iBufferEnd)
- {
- next = iFirstPacket;
- continue;
- }
- // Not enough space, move onto next block.
- if (maxLength<iMinReadSize)
- {
- next+=maxLength;
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst Skip exhausted block. next %x max %d", next, maxLength));
- continue;
- }
- }
- while (EFalse);
-
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst next (pre deduct): %x, Fill in header at head: 0x%x, BuffStart: 0x%x.", next, iHead, iBufferStart));
-
- next -= headerSize; // Move next back from the data start position, to the header start.
-
- TUsbcScTransferHeader* header = (TUsbcScTransferHeader*) (iHead + iChunkAddr);
-
-// Create Header
-#ifdef _DEBUG
- header->iHashId=59*(iLdd->iAlternateSetting+1)+iCallback->iRealEpNum; // Alt setting realated....
- header->iSequence=iSequence;
- iSequence++;
-#endif
- header->iBytes=aByteCount;
- header->iNext=next;
- header->iAltSettingSeq=iLdd->iAsSeq;
- header->iAltSetting=iLdd->iAlternateSetting;
- header->iFlags=aFlags;
- __KTRACE_OPT(KUSB, Kern::Printf("We set next to 0x%x", next));
-
- iStatusList.iState=ENotRunning;
- if (next==iBufferStart->iTail) //or (othwise is as good as full)
- {
- iStalled=next;
- }
- else
- {
-
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst StartRead?? "));
- TInt oldHead=iHead;
- iHead = next;
-
- if ((aStartNextRead) && (StartDataRead() == KErrOverflow))
- { // Oh crumbs, set state as slalled.
- if (oldHead != iBufferStart->iBilTail)
- // If user has not read everything in the buffer
- // then set up a stall, so that ldd get to be woken early
- {
- iStalled=next;
- iHead=oldHead;
- }
- else // otherwise if everything is read
- // no choice but to return what we have
- {
- iBufferStart->iHead = iHead;
- }
- }
- else
- {
- iBufferStart->iHead = next;
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst Compleating\n"));
- }
- // Complete userside
- iStatusList.Complete();
- }
- }
-
-void TUsbcScBuffer::PopStall()
- {
- if (iStalled==iBufferStart->iTail)
- return; // Still stalled.
-
- if (iStalled!=-1) // If not Alt packet only stall
- {
- // pop off packet
- iHead = iStalled;
- }
- iStalled=0;
- // If Alt setting of the popped packet is different to now
- // Add alt setting change packet.
-
-
- if (StartDataRead() == KErrOverflow)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::PopStall Warning: Transfer was freed, but still no space!\n"));
- }
-
- iBufferStart->iHead = iHead;
- }
-
-
-
-void TUsbcScBuffer::StartDataWrite()
- {
-
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite()"));
- TUsbcScStatusElement* nextJob = iStatusList.Next();
- TBool zlpReqd;
- TInt length;
- TUint start;
- TUint8* startAddr;
- TInt maxLength;
- TPhysAddr physAddr;
- TInt r;
- if (!iMaxPacketSize)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite() - Not Configured"));
- return;
- }
-
- if (nextJob == NULL)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite() - No more jobs d=%d", iDirection));
- if (iDirection==KUsbcScBiIn) // assume this is EP0, if this is true.
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite() Queue Read on EP0."));
- // Start other read again.
- iLdd->iBuffers[iLdd->iEP0OutBuff].StartDataRead();
- }
- }
- else
- {
- if (iStatusList.iState==ENotRunning)
- iSent=0;
- iStatusList.iState=EInProgress;
-
- start = nextJob->iStart;
- startAddr = (TUint8*) (start + ((TUint) (iChunkInfo->iChunkMem)));
-
- length = nextJob->iLength;
- zlpReqd = (nextJob->iFlags & KUsbcScWriteFlagsZlp) !=0;
- // get max read length
- maxLength = iChunkInfo->GetPhysical( start, &physAddr);
-
- if (maxLength < length)
- {
- // modify request.
- nextJob->iStart += maxLength;
- nextJob->iLength -= maxLength;
- // start this request.
- iStatusList.iState=EFramgementInProgress;
- zlpReqd=EFalse;
- length = maxLength;
- }
-
- if (iDirection==KUsbcScBiIn) // this is for EP0
- {
- iLdd->iController->CancelReadBuffer(iLdd, iCallback->iRealEpNum);
- iLdd->iBuffers[iLdd->iEP0OutBuff].iStatusList.iState=ENotRunning;
- }
-
- iCallback->SetTxBufferInfo(startAddr, physAddr, length);
- iCallback->iZlpReqd = zlpReqd;
- r = iLdd->iController->SetupWriteBuffer(*iCallback);
- if (r!=KErrNone)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("SetupWriteBUffer Error: %d",r));
- iStatusList.Complete(r);
- }
- }
-
- }
-
-void TUsbcScBuffer::CompleteWrite()
- {
- TInt error = iCallback->iError;
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::CompleteWrite buff=%x, err=%d",this, error));
- iSent+= iCallback->iTxBytes;
-
- // More to send?
- if (error || iStatusList.iState!=EFramgementInProgress)
- {
- // complete request with error (if one).
- // Some data could have been transmitted, even with an error.
- iStatusList.Complete(error);
- }
-
- // Start next request, or next part of this one.
- StartDataWrite();
-
- }
-
-// Cancels the current request's callback.
-// This is not to say it will cancel the actual operation,
-// However it will cancel any further sections of the user perceived operation
-// that are not yet started.
-void TUsbcScBuffer::Cancel(TInt aErrorCode)
- {
- iStatusList.CancelQueued();
- if (iLdd->iController && ((iDirection&1)==KUsbcScIn))
- {
- iLdd->iController->CancelWriteBuffer(iLdd, iCallback->iRealEpNum);
- }
-
- iStatusList.Complete(aErrorCode);
- }
-
-void TUsbcScBuffer::Ep0CancelLddRead()
- {
- // Stopping a read isn't as easy as one might think.
- // We cancel the callback, but then check if any data was received (but not returned to us).
- // If so, we must de-queue the request, and call the completion code.
-
- iLdd->iController->CancelReadBuffer(iLdd, iCallback->iRealEpNum);
- if (iCallback->iRxPackets) // received data?
- {
- // remove DFC (if infact sent)
- iCallback->iDfc.Cancel();
-
- // process the callback now, but dont start another
- CompleteRead(EFalse);
- }
- }
-
-void TUsbcScBuffer::SendEp0StatusPacket(TInt aState)
-{
- __KTRACE_OPT(KUSB, Kern::Printf(" TUsbcScBuffer::SendEp0StatusPacket(%d)", aState));
-
- // We need to add a packet to the buffer, so we must stop the pending read, and start
- // another after we have added out packet.
- Ep0CancelLddRead();
-
- TUint* state = ((TUsbcScTransferHeader *) (iHead + iChunkAddr))->iData.i;
- *state = aState;
- UpdateBufferList(4,KUsbcScStateChange);
-}
-
-// End TUsbcScBuffer
-
-/*****************************************************************************\
-* TUsbcScStatusList *
-* *
-* This is a list of read or write requests, containing user status *
-* requests, that should later be completed. *
-* *
-\*****************************************************************************/
-
-/**
-Constructor for TUsbcScStatusList.
-
-@param aSize is the number of requests to allow at any one time. This value
- must be a power of two, for correct operation.
-
-@returns KErrNoMemory if memory allocation failure, otherwise KErrNone.
-*/
-
-TInt TUsbcScStatusList::Construct(TInt aSize, DThread* aClient)
- {
- iSize=aSize;
- iHead = 0;
- iLength = 0;
- iClient = aClient;
- iElements=(TUsbcScStatusElement *) Kern::AllocZ(sizeof(TUsbcScStatusElement)*aSize);
- return (iElements==NULL)?KErrNoMemory:KErrNone;
- };
-
-
-// StatusList must be inactive before destroying.
-void TUsbcScStatusList::Destroy()
- {
- if (iState!=ENotRunning)
- Kern::Fault("TUsbcScStatusList::Destroy", __LINE__);
- if (iElements)
- {
- Kern::Free(iElements);
- iElements=NULL;
- }
- iClient=NULL;
-}
-
-void TUsbcScStatusList::Pop()
- {
- if (iLength>0)
- {
- iLength--;
- iHead = ((iHead+1) & (iSize-1));
- }
- }
-
-TUsbcScStatusElement* TUsbcScStatusList::Next()
- {
- return (iLength==0)?NULL:&(iElements[iHead]);
- }
-
-TInt TUsbcScStatusList ::Add(TRequestStatus* aStatus, TInt aLength, TUint aStart, TUint aFlags)
- {
- __KTRACE_OPT(KUSB,Kern::Printf("Adding request. iLength %d iSize %d", iLength, iSize));
- if (iLength<iSize)
- {
- TUsbcScStatusElement& e = iElements[((iHead+iLength) & (iSize-1))];
- e.iStatus = aStatus;
- e.iLength = aLength;
- e.iStart = aStart;
- e.iFlags = aFlags;
- iLength++;
- __KTRACE_OPT(KUSB,Kern::Printf("Adding request. new iLength %d", iLength));
-
- return KErrNone;
- }
- else
- return KErrInUse;
- }
-
-
-
-// This method cancels any requests that have yet to be started.
-
-void TUsbcScStatusList::CancelQueued(TInt aError)
-{
- if ((iLength==0) || ((iState!=ENotRunning) && (iLength==1))) // Nothing to do.
- return;
- TInt elements2Complete = iLength - (iState?1:0);
- TInt head = iHead;
- iLength = 0;
- if (iState) // If (iState != ENotRunning), complete all elements excepting the one at head
- {
- head = ((head+1) & (iSize-1)); // To iterate through the queue
- iLength = 1;
- }
- // complete them all.
- for (; elements2Complete>0; elements2Complete--)
- {
- Kern::RequestComplete(iClient, iElements[head].iStatus, aError);
- head = ((head+1) & (iSize-1));
- }
-
-}
-
-
-/* This method Completes the head status request, and pops it from its list.
-This version of Complete is to be used in cases where the next request is not
-chained - usually because of an error.
-
-@Param aError - the code to complete with.
-
-returns KErrNotFound if there was no request to complete
-*/
-
-
-TInt TUsbcScStatusList::Complete(TInt aError)
- {
- if (iState==ENotRunning)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScStatusList::Complete() - iState == ENotRunning!"));
- }
- else
- {
- iState=ENotRunning;
- if (iLength==0)
- return KErrNotFound;
-
- Kern::RequestComplete(iClient, iElements[iHead].iStatus, aError);
-
- iLength--;
- iHead = ((iHead+1) & (iSize-1));
- }
- return KErrNone;
- }
-
-
-/* This method Completes the head status request, and pops it from its list. (If found.)
-This version of Complete is to be used in cases where the request is successful, and
- next request after this has (if present) been chained.
-*/
-
-void TUsbcScStatusList::Complete()
- {
- if (iLength==0)
- return;
- __KTRACE_OPT(KUSB, Kern::Printf("Completing request. iLength %d", iLength));
-
- Kern::RequestComplete(iClient, iElements[iHead].iStatus, KErrNone);
-
- iLength--;
- iHead = ((iHead+1) & (iSize-1));
- }
-
-// End TUsbcScStatusList
-
-/*****************************************************************************\
-* TRealizeInfo *
-* *
-* Used by DLddUsbcScChannel::RealizeInterface to set up the chunk *
-* *
-\*****************************************************************************/
-
-// Init
-//
-// This method works out the number potential maximum number of endpoints
-// and the number of alt settings. With this information it allocs
-// the necessary space for the given stucture to store information about
-// the endpoints.
-// This is intended to be called by RealizeInterface. This stucture is
-// intended to be only temporary, and the space will be freed with Free()
-// before RealizeInteface has finished.
-
-void TRealizeInfo::Init(TUsbcScAlternateSettingList* aAlternateSettingList)
-{
- iAlternateSettingList = aAlternateSettingList;
- iMaxEndpoints=0;
- iTotalSize =0;
- iTotalBuffers=0;
- iAltSettings =0;
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: work out max endpoint"));
- // Work out max endpoints and number of alternate settings.
-
- if (iAlternateSettingList)
- {
- TUsbcScAlternateSetting* alt = iAlternateSettingList->iHead;
- while (alt != NULL)
- {
- iAltSettings++;
- if (alt->iNumberOfEndpoints>iMaxEndpoints)
- iMaxEndpoints = alt->iNumberOfEndpoints;
- // could work out in/out specifics, but unnecessary.
- alt = alt->iNext;
- };
- }
-
- // Alloc some temporary working space for temp endpoint metadata
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: Alloc temp. Maxendpoints %d", iMaxEndpoints));
- TInt inout;
- for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
- {
- iBufs[inout].iEp = (TUsbcScEndpoint **) Kern::AllocZ(iAltSettings*iMaxEndpoints*sizeof(TUsbcScEndpoint *));
- iBufs[inout].iSizes = (TInt *) Kern::AllocZ(iMaxEndpoints*sizeof(TInt));
- }
-}
-
-// CopyAndSortEndpoints
-//
-// This method copies pointers to the endpoint records into TRealizeInfo
-// such that they are sorted in order of size per alt setting.
-// In and Out endpoints are separated, and kept separate.
-// The provided data structure is assumed to have been initialised with
-// Realize_InitRealizeInfo.
-//
-// Return KErrArgument if the direction field is neither In or Out.
-//
-
-TInt TRealizeInfo::CopyAndSortEndpoints()
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: copy And sort"));
-
- TInt altSetting = 0;
- TInt endpointOffs;
- TInt endpoint;
- TInt altEp;
- TInt inout;
- TBool placed;
- TUsbcScAlternateSetting* alt;
- TEndpointSortBufs* bufsd;
-
- if (iAlternateSettingList)
- {
- for (alt = iAlternateSettingList->iHead;alt!=NULL;alt = alt->iNext )
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: AlternateSetting %x", alt));
-
- iBufs[KUsbcScIn].iEps =0;
- iBufs[KUsbcScOut].iEps =0;
-
- // For alt setting, iterate eps
- for (altEp=1; altEp <= alt->iNumberOfEndpoints; altEp++)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: Endpoint to add: %d",altEp));
-
- TUsbcScEndpoint* nextEp = alt->iEndpoint[altEp];
-
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: ep Buffer Size: %d",nextEp->EndpointInfo()->iBufferSize));
-
- inout = (nextEp->EndpointInfo()->iDir==UsbShai::KUsbEpDirIn)?KUsbcScIn:
- (nextEp->EndpointInfo()->iDir==UsbShai::KUsbEpDirOut)?KUsbcScOut:KUsbcScUnknown;
- if (inout==KUsbcScUnknown)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: KUsbcScUnknown %x",nextEp->EndpointInfo()->iDir));
- return KErrArgument;
- }
-
- bufsd = &(iBufs[inout]);
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: ep direction: %x # endpoints %d", inout, bufsd->iEps));
-
-
- // find and position ep, and insert.
-
- if (bufsd->iEps==0) // First entry.
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: Add first endpoint"));
- endpointOffs = altSetting*iMaxEndpoints;
- bufsd->iEp[endpointOffs] = nextEp;
- }
- else
- {
- placed = EFalse;
- // Move down the list, until we find the right place.
- for (endpoint=bufsd->iEps-1; endpoint>-1; endpoint--)
- {
- endpointOffs = altSetting*iMaxEndpoints + endpoint;
- if (bufsd->iEp[endpointOffs]->EndpointInfo()->iBufferSize < nextEp->EndpointInfo()->iBufferSize)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: Shift Endpoint %d", endpoint));
-
- bufsd->iEp[endpointOffs+1] = bufsd->iEp[endpointOffs];
- }
- else
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: Insert After Endpoint %d", endpoint));
-
- bufsd->iEp[endpointOffs+1] = nextEp;
- placed = ETrue;
- break;
- }
- } // end for endpoint
- if (!placed) // if we didn't place it, it must be the biggest so far, so goes at the top.
- bufsd->iEp[0] = nextEp;
- } // endif
- bufsd->iEps++;
- } // for altEp
- altSetting++;
- } // for alt
- }// if iAltsettingList
- return KErrNone;
- }
-
-// CalcBuffSizes
-//
-// This works out the sizes of all the buffers, and stores the result in aBufInfo
-// based on the buffer information provided in the same structure.
-// Realize_CopyAndSortEndpoints is used to fill the structure with the informaition
-// required.
-
-void TRealizeInfo::CalcBuffSizes()
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: Calculate Buffers"));
-
- TInt endpoint;
- TInt inout;
- TInt altSetting;
- TUsbcScEndpoint* nextEp;
- TInt bufferSize;
- TEndpointSortBufs* bufsd;
-
- for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: Direction: %d", inout));
-
-
- bufsd = &(iBufs[inout]);
- // for each row, ie, buffer, find largest buffer need.
- for (endpoint=0; endpoint<iMaxEndpoints; endpoint++)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: endpoint %d", endpoint));
- TInt bufMaxSize=0;
- for (altSetting=0; altSetting< iAltSettings; altSetting++)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: altSetting %d", altSetting));
- nextEp= bufsd->iEp[altSetting* iMaxEndpoints + endpoint];
- if (nextEp!=NULL)
- {
- bufferSize = nextEp->EndpointInfo()->iBufferSize;
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: comparing size %d", bufferSize));
- if (bufferSize> bufMaxSize)
- bufMaxSize = bufferSize;
- }
- } // for altsetting
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: bufMaxSize %d", bufMaxSize));
- bufsd->iSizes[endpoint] = bufMaxSize;
- if (bufMaxSize>0)
- {
- iTotalSize += bufsd->iSizes[endpoint];
- iTotalBuffers++;
- }
- } // for endpoint
- } // for in/out
-}
-
-// Free
-//
-// Cleans up after Init()
-
-void TRealizeInfo::Free()
- {
- TInt inout;
- for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
- {
- Kern::Free(iBufs[inout].iEp);
- Kern::Free(iBufs[inout].iSizes);
- }
- }
-
-// End TRealizeInfo
-
-
-// LayoutChunkHeader
-//
-// Sets up some geometry for the chunk;
-
-void TRealizeInfo::LayoutChunkHeader(TUsbcScChunkInfo* aChunkInfo)
-{
- // First set up the indexes to the header structures.
- TUsbcScChunkHdrOffs* chkHdr = (TUsbcScChunkHdrOffs*) aChunkInfo->iChunkMem;
-
- chkHdr->iBuffers = sizeof(TUsbcScChunkHdrOffs); // First struct just after this one.
- iChunkStuct = (TUsbcScChunkBuffersHeader*) ( (TInt) aChunkInfo->iChunkMem + chkHdr->iBuffers);
-
- // Store number of buffers in chunk
- iChunkStuct->iRecordSize = sizeof(TUsbcScBufferRecord);
- iChunkStuct->iNumOfBufs=iTotalBuffers;
-
- iAltSettingsTbl = (TUsbcScChunkAltSettingHeader*) &(iChunkStuct->iBufferOffset[(iTotalBuffers+2)*sizeof(TUsbcScBufferRecord)]); // 2 extra for EP0 in and out.
-
- chkHdr->iAltSettings = (TUint) iAltSettingsTbl - (TUint) aChunkInfo->iChunkMem;
-
- iAltSettingsTbl->iEpRecordSize = sizeof(TUint);
- iAltSettingsTbl->iNumOfAltSettings = iAltSettings;
-
-
- TInt tableOffset = (TUint) iAltSettingsTbl->iAltTableOffset - (TUint) aChunkInfo->iChunkMem + iAltSettings*sizeof(TInt);
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: table offset: 0x%x, altTble %x iChnkMem %x altSettings %x",tableOffset, iAltSettingsTbl, aChunkInfo->iChunkMem, iAltSettings ));
-
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: populate chunk - create alt settings table"));
-
- // Create alt settings table. Set each element of altsettings table, to each induivatual alt setting table.
- // then fill in the number of endpoints for that alt setting, in the table.
-
- TInt* noEpForAlt;
- TInt altSetting;
- TUsbcScAlternateSetting* alt;
- if (iAlternateSettingList)
- {
- alt = iAlternateSettingList->iHead;
- for (altSetting=0; altSetting<iAltSettings; altSetting++)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: altSetting %d, tableOffset %d", altSetting, tableOffset));
-
- iAltSettingsTbl->iAltTableOffset[altSetting] = tableOffset;
- noEpForAlt = (TInt*) &aChunkInfo->iChunkMem[tableOffset];
-
- *noEpForAlt = alt->iNumberOfEndpoints; // Set NumberofEndpoints field in Altsetting table
- tableOffset+= sizeof(TInt)+ alt->iNumberOfEndpoints*sizeof(TUsbcScHdrEndpointRecord);
- alt = alt->iNext;
- }
- }
-
-} // end LayoutChunkHeader
-
-
-
-/*****************************************************************************\
-* DLddUsbcScChannel *
-* *
-* Inherits from DLogicalDevice, the USB Shared Chunk LDD factory class *
-* *
-\*****************************************************************************/
-
-//
-// Constructor
-//
-DLddUsbcScChannel::DLddUsbcScChannel()
- : iValidInterface(EFalse),
- iAlternateSettingList(NULL),
- iEndpoint(NULL),
- iCompleteAllCallbackInfo(this, DLddUsbcScChannel::EmergencyCompleteDfc, KUsbRequestCallbackPriority),
- iStatusChangePtr(NULL),
- iStatusCallbackInfo(this, DLddUsbcScChannel::StatusChangeCallback, KUsbRequestCallbackPriority),
- iEndpointStatusChangePtr(NULL),
- iEndpointStatusCallbackInfo(this, DLddUsbcScChannel::EndpointStatusChangeCallback,
- KUsbRequestCallbackPriority),
- iOtgFeatureChangePtr(NULL),
- iOtgFeatureCallbackInfo(this, DLddUsbcScChannel::OtgFeatureChangeCallback, KUsbRequestCallbackPriority),
- iNumberOfEndpoints(0),
- iDeviceState(UsbShai::EUsbPeripheralStateUndefined),
- iOwnsDeviceControl(EFalse),
- iAlternateSetting(0),
- iAsSeq(0),
- iStatusFifo(NULL),
- iUserKnowsAltSetting(ETrue),
- iDeviceStatusNeeded(EFalse),
- iChannelClosing(EFalse),
- iRealizeCalled(EFalse),
- iChunkInfo(NULL),
- iNumBuffers(-1),
- iBuffers(NULL),
- iEp0Endpoint(NULL)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DLddUsbcScChannel()"));
- iClient = &Kern::CurrentThread();
- iClient->Open();
- for (TInt i = 1; i < KUsbcMaxRequests; i++)
- {
- iRequestStatus[i] = NULL;
- }
- }
-
-
-//
-// Destructor
-//
-
-DLddUsbcScChannel::~DLddUsbcScChannel()
- {
- __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::~DLddUsbcScChannel()"));
- if (iController)
- {
- iController->DeRegisterClient(this);
- iStatusCallbackInfo.Cancel();
- iEndpointStatusCallbackInfo.Cancel();
- iOtgFeatureCallbackInfo.Cancel();
- iCompleteAllCallbackInfo.Cancel();
- DestroyAllInterfaces();
- if (iOwnsDeviceControl)
- {
- iController->ReleaseDeviceControl(this);
- iOwnsDeviceControl = EFalse;
- }
- iController=NULL;
- DestroyEp0();
- if (iStatusFifo!=NULL)
- {
- delete iStatusFifo;
- }
- }
- __KTRACE_OPT(KUSB, Kern::Printf("Closing buffers"));
- if (iBuffers)
- {
- TInt i;
- for (i=0; i<(iNumBuffers+2); i++)
- {
- iBuffers[i].Destroy();
- }
- Kern::Free(iBuffers);
- }
-
- if (iRealizeCalled)
- {
- // Close Chunk
- iChunkInfo->Close();
- // ChunkInfo will delete itself with DFC, but the pointer here is no longer needed.
- iChunkInfo=NULL;
- }
- __KTRACE_OPT(KUSB, Kern::Printf("about to SafeClose"));
- Kern::SafeClose((DObject*&)iClient, NULL);
- }
-
-
-//
-// DoCreate - Create channel
-//
-
-TInt DLddUsbcScChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("LDD DoCreateL 1 Ver = %02d %02d %02d",
- aVer.iMajor, aVer.iMinor, aVer.iBuild));
- if (!Kern::CurrentThreadHasCapability(ECapabilityCommDD,
- __PLATSEC_DIAGNOSTIC_STRING("Checked by USBCSC.LDD (USB Driver)")))
- {
- return KErrPermissionDenied;
- }
-
- iController = DUsbClientController::UsbcControllerPointer();
-
- if (!iController)
- {
- return KErrGeneral;
- }
-
- iStatusFifo = new TUsbcDeviceStatusQueue;
- if (iStatusFifo == NULL)
- {
- return KErrNoMemory;
- }
-
- if (!Kern::QueryVersionSupported(TVersion(KUsbcScMajorVersion, KUsbcScMinorVersion, KUsbcScBuildVersion), aVer))
- {
- return KErrNotSupported;
- }
-
- // set up the correct DFC queue
- SetDfcQ(iController->DfcQ(0)); // sets the channel's dfc queue
- iCompleteAllCallbackInfo.SetDfcQ(iDfcQ);
- iStatusCallbackInfo.SetDfcQ(iDfcQ); // use the channel's dfcq for this dfc
- iEndpointStatusCallbackInfo.SetDfcQ(iDfcQ); // use the channel's dfcq for this dfc
- iOtgFeatureCallbackInfo.SetDfcQ(iDfcQ);
- iMsgQ.Receive(); //start up the message q
- TInt r = iController->RegisterClientCallback(iCompleteAllCallbackInfo);
- if (r != KErrNone)
- return r;
- r = iController->RegisterForStatusChange(iStatusCallbackInfo);
- if (r != KErrNone)
- return r;
- r = iController->RegisterForEndpointStatusChange(iEndpointStatusCallbackInfo);
- if (r != KErrNone)
- return r;
- r = iController->RegisterForOtgFeatureChange(iOtgFeatureCallbackInfo);
- if (r != KErrNone)
- return r;
-
- return r;
- }
-// end DoCreate.
-
-
-//
-// HandleMsg
-//
-// Events from userside arrive here, and delegated to either DoRequest, DoControl or DoCancel.
-//
-
-void DLddUsbcScChannel::HandleMsg(TMessageBase* aMsg)
- {
- TThreadMessage& m = *(TThreadMessage*)aMsg;
- TInt id = m.iValue;
- __KTRACE_OPT(KUSB, Kern::Printf("HandleMsg 0x%x", id));
-
- if (id == (TInt) ECloseMsg)
- {
- iChannelClosing = ETrue;
- m.Complete(KErrNone, EFalse);
- return;
- }
-
- TInt r;
- if (id < 0)
- {
- // DoRequest
- TRequestStatus* pS = (TRequestStatus*) m.Ptr0();
- r = DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
- m.Complete(r, ETrue);
- }
- else if (id & RDevUsbcScClient::ERequestCancel)
- {
- // DoCancel
- r = DoCancel(id, (TUint) m.Ptr0(), (TUint) m.Ptr1());
- m.Complete(r, ETrue);
- }
- else
- {
- // DoControl
- r = DoControl(id, m.Ptr0(), m.Ptr1());
- m.Complete(r, ETrue);
- }
- }
-// end HandleMsg.
-
-
-#define BREAK_IF_NULL_ARG(a,r) if (a==NULL) { r = KErrArgument; __KTRACE_OPT(KUSB,Kern::Printf("NULL Argument")); break; }
-
-//
-// DoRequest - Asynchronous requests
-//
-// Overrides pure virtual, called by HandleMsg. (Above)
-//
-TInt DLddUsbcScChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
- {
- TInt reqNo = aReqNo & RDevUsbcScClient::KFieldIdMask;
- TInt r = KErrNone; // return via request notify
- TBool needsCompletion =EFalse;
-
- __KTRACE_OPT(KUSB, Kern::Printf("DoRequest 0x%08x", aReqNo));
-
- if ((reqNo>RDevUsbcScClient::ERequestReadDataNotify) &&
- (reqNo<RDevUsbcScClient::ERequestMaxRequests))
- {
- if (iRequestStatus[reqNo])
- {
- PanicClientThread(ERequestAlreadyPending);
- return 0;
- }
- iRequestStatus[reqNo] = aStatus;
- }
-
- switch (reqNo)
- {
- case RDevUsbcScClient::ERequestWriteData:
- {
- TInt buffer = (aReqNo>>RDevUsbcScClient::KFieldBuffPos)&RDevUsbcScClient::KFieldBuffMask;
- __KTRACE_OPT(KUSB, Kern::Printf("ERequestWriteData"));
- BREAK_IF_NULL_ARG(a2,r);
-
- r = DoWriteData( aStatus, buffer, (TInt) a1 /*Start*/, (TInt) a2 /* Length */,
- aReqNo>>RDevUsbcScClient::KFieldFlagsPos ); // Flags
- break;
- }
- case RDevUsbcScClient::ERequestReadDataNotify:
- {
- __KTRACE_OPT(KUSB, Kern::Printf("ERequestReadDataNotify"));
- return DoReadDataNotify(aStatus, (TInt) a1, (TInt) a2); // a1 = aBufferNumber, a2 - aLength;
- }
-
- case RDevUsbcScClient::ERequestAlternateDeviceStatusNotify:
- {
- __KTRACE_OPT(KUSB, Kern::Printf("ERequestAlternateDeviceStatusNotify"));
- BREAK_IF_NULL_ARG(a1,r);
- iDeviceStatusNeeded = ETrue;
- iStatusChangePtr = a1;
- needsCompletion = AlternateDeviceStateTestComplete();
- break;
- }
- case RDevUsbcScClient::ERequestReEnumerate:
- {
- __KTRACE_OPT(KUSB, Kern::Printf("ERequestReEnumerate"));
- // If successful, this will complete via the status notification.
- r = iController->ReEnumerate();
- break;
- }
- case RDevUsbcScClient::ERequestEndpointStatusNotify:
- {
- __KTRACE_OPT(KUSB, Kern::Printf("ERequestEndpointStatusNotify"));
- BREAK_IF_NULL_ARG(a1,r);
-
- iEndpointStatusChangePtr = a1;
- break;
- }
- case RDevUsbcScClient::ERequestOtgFeaturesNotify:
- {
- __KTRACE_OPT(KUSB, Kern::Printf("ERequestOtgFeaturesNotify"));
- BREAK_IF_NULL_ARG(a1,r);
-
- iOtgFeatureChangePtr = a1;
- break;
- }
- default:
- r = KErrNotSupported;
- }
-
- if ((needsCompletion) || (r != KErrNone))
- {
- iRequestStatus[reqNo] = aStatus;
- Kern::RequestComplete(iClient, iRequestStatus[reqNo], r);
- }
- return KErrNone;
- }
-// end DoRequest.
-
-
-//
-// DoReadDataNotify
-//
-// This method sets up the request to facilitate the userside being notifed when new data has been read.
-//
-TInt DLddUsbcScChannel::DoReadDataNotify(TRequestStatus* aStatus, TInt aBufferNum, TInt aLength)
- {
- __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify(x, %d, 0x%x)", aBufferNum, aLength));
- TInt r = KErrNone;
- // check range
- if ((aBufferNum<0) || (aBufferNum>=iNumBuffers)) // Indirectly checks that we are set up.
- {
- if (aBufferNum!=KUsbcScEndpointZero)
- {
- __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify : Bad Buffer Number!"));
- return KErrArgument;
- }
- else
- {
- aBufferNum = iEP0OutBuff;
- }
- }
- else
- {
- // check direction
- if (iBuffers[aBufferNum].iDirection!=KUsbcScOut)
- {
- __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify : Bad Buffer Direction!"));
- return KErrNotSupported;
- }
- if (!Configured())
- return KErrUsbInterfaceNotReady;
- }
- SUsbcScBufferHeader* scBuffer = (SUsbcScBufferHeader*) iBuffers[aBufferNum].iBufferStart;
-
- __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify head %x tail %x", iBuffers[aBufferNum].iHead , scBuffer->iTail ));
-
- if (iBuffers[aBufferNum].iHead != scBuffer->iBilTail)
- r = KErrCompletion;
- else
- if (iBuffers[aBufferNum].iStalled)
- {
- iBuffers[aBufferNum].PopStall();
- return KErrCompletion;
- }
- else
- r = iBuffers[aBufferNum].iStatusList.Add(aStatus, aLength, 0,0);
-
- if (iBuffers[aBufferNum].iStatusList.iState==ENotRunning)
- {
- iBuffers[aBufferNum].StartDataRead();
- }
- else
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Job in Progress!"));
- }
- return r;
- }
-// end DoReadDataNotify.
-
-
-
-//
-// DoWriteData
-//
-// This method sets up the request to write data to USB from userside.
-//
-TInt DLddUsbcScChannel::DoWriteData(TRequestStatus* aStatus,TInt aBufferNum, TUint aStart, TUint aLength, TUint aFlags)
- {
- __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData(%d, 0x%x, 0x%x, 0x%x)", aBufferNum, aStart, aLength, aFlags));
- if (!iUserKnowsAltSetting)
- return KErrEof;
- // Check Buffer Number
- if ((aBufferNum<0) || (aBufferNum>=iNumBuffers))
- {
- if ((TUint)aBufferNum!=RDevUsbcScClient::KFieldBuffMask) // KUsbcScEndpointZero & KFieldBuffMas = KFieldBuffMas;
- {
- __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData : Bad Buffer Number!"));
- return KErrArgument;
- }
- else
- {
- aBufferNum = iEP0InBuff;
- }
- }
- else
- {
- // check direction
- if (iBuffers[aBufferNum].iDirection!=KUsbcScIn)
- {
- __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData Bad endpoint Direction"));
- return KErrArgument;
- }
- }
-
- TUsbcScBuffer& buf=iBuffers[aBufferNum];
-
- if ((aStart< (((TLinAddr) buf.iBufferStart)-buf.iChunkAddr)) || ((aStart+aLength)>iBuffers[aBufferNum].iBufferEnd))
- {
- __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 ));
- return KErrArgument;
- }
-
- if ( (aBufferNum != iEP0InBuff) && !Configured())
- return KErrUsbInterfaceNotReady;
-
- if (aStart & ~buf.iAlignMask)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::DoDataWrite: address 0x%x unaligned.",aStart));
- return KErrArgument;
- }
-
- TInt r = iBuffers[aBufferNum].iStatusList.Add(aStatus, aLength, aStart, aFlags); //update
-
- if (iBuffers[aBufferNum].iStatusList.iState==ENotRunning)
- {
- iBuffers[aBufferNum].StartDataWrite();
- }
- else
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Job in Progress!"));
- }
-
-
- return r;
- }
-// end DoWriteData.
-
-
-//
-// Cancel an outstanding request // Cancel need reworking.
-//
-TInt DLddUsbcScChannel::DoCancel(TInt aReqNo, TUint aBuff, TUint aSpair)
- {
- TInt r = KErrNone;
- TInt direction=KUsbcScOut;
-
- __KTRACE_OPT(KUSB, Kern::Printf("DoCancel: 0x%x aBuff 0x%x", aReqNo, aBuff));
- switch (aReqNo)
- {
- case RDevUsbcScClient::ERequestCancel:
- TInt buffer;
- TInt mask;
-
- for (buffer=1, mask=1; buffer<iNumBuffers; buffer++,mask<<=1)
- if (aBuff&mask)
- iBuffers[buffer].Cancel(KErrCancel);
-
- return KErrNone;
-
- // coverity[missing_break]
- case RDevUsbcScClient::ERequestWriteDataCancel:
- direction = KUsbcScIn;
- case RDevUsbcScClient::ERequestReadDataNotifyCancel:
- __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Direction %d endpoints: 0x%x",direction, aReqNo));
-
- if (((TInt)aBuff)==KUsbcScEndpointZero) // EP0 is bi-directional, so pick correct buffer for call type
- {
- __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Cancel Endpoint 0/%d",direction));
- iEp0Endpoint->AbortTransfer();
- if (direction==KUsbcScIn)
- aBuff=iEP0InBuff;
- else
- aBuff=iEP0OutBuff;
- }
- else if ((TInt)aBuff >= iNumBuffers) // check buff no range.
- {
- __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Error: Bad buffer number"));
- return KErrArgument;
- }
-
- if ((iBuffers[aBuff].iDirection&1)!=direction) // Does direction match call type?
- {
- __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Error: Bad buffer direction"));
- return KErrArgument;
- }
- iBuffers[aBuff].iStatusList.CancelQueued();
- iBuffers[aBuff].Cancel(KErrCancel);
-
- return KErrNone;
-
- case RDevUsbcScClient::ERequestAlternateDeviceStatusNotifyCancel:
- __KTRACE_OPT(KUSB, Kern::Printf("DoCancel: ERequestAlternateDeviceStatusNotify 0x%x", aReqNo));
- iDeviceStatusNeeded = EFalse;
- iStatusFifo->FlushQueue();
- if (iStatusChangePtr)
- {
- TInt deviceState = iController->GetDeviceStatus();
- r = Kern::ThreadRawWrite(iClient, iStatusChangePtr, &deviceState, sizeof(deviceState), iClient);
- if (r != KErrNone)
- PanicClientThread(r);
- iStatusChangePtr = NULL;
- }
- break;
-
- case RDevUsbcScClient::ERequestReEnumerateCancel:
- __KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestReEnumerate: 0x%x", aReqNo));
- break;
-
- case RDevUsbcScClient::ERequestEndpointStatusNotifyCancel:
- __KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestEndpointStatusNotify: 0x%x", aReqNo));
- CancelNotifyEndpointStatus();
- break;
-
- case RDevUsbcScClient::ERequestOtgFeaturesNotifyCancel:
- __KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestOtgFeaturesNotify: 0x%x", aReqNo));
- CancelNotifyOtgFeatures();
- break;
-
- default:
- __KTRACE_OPT(KUSB, Kern::Printf("DoCancel Unknown! 0x%x", aReqNo));
- return KErrArgument;
- }
-
- Kern::RequestComplete(iClient,iRequestStatus[aReqNo & ~RDevUsbcScClient::ERequestCancel], KErrCancel);
- return r;
- }
-
-
-void DLddUsbcScChannel::CancelNotifyEndpointStatus()
- {
- if (iEndpointStatusChangePtr)
- {
- TUint epBitmap = 0;
- for (TInt i = 1; i <= iNumberOfEndpoints; i++)
- {
- TInt v = iController->GetEndpointStatus(this, iEndpoint[i]->RealEpNumber());
- TUint b;
- (v == EEndpointStateStalled) ? b = 1 : b = 0;
- epBitmap |= b << i;
- }
- TInt r=Kern::ThreadRawWrite(iClient, iEndpointStatusChangePtr, (TUint8*) &epBitmap, sizeof(epBitmap), iClient);
- if (r != KErrNone)
- PanicClientThread(r);
- iEndpointStatusChangePtr = NULL;
- }
- }
-
-void DLddUsbcScChannel::CancelNotifyOtgFeatures()
- {
- if (iOtgFeatureChangePtr)
- {
- TUint8 features;
- iController->GetCurrentOtgFeatures(features);
- TInt r=Kern::ThreadRawWrite(iClient, iOtgFeatureChangePtr, (TUint8*)&features, sizeof(features), iClient);
- if (r != KErrNone)
- PanicClientThread(r);
- iOtgFeatureChangePtr = NULL;
- }
- }
-
-
-
-//
-// DoControl - Synchronous requests
-//
-// Called from HandleMsg.
-
-TInt DLddUsbcScChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("DoControl: %d", aFunction));
-
- TInt r = KErrNone;
- TInt ep, param;
- TUsbcScEndpoint* pEndpoint;
- TPtrC8 pZeroDesc(NULL, 0);
- TEndpointDescriptorInfo epInfo;
- TUsbcScIfcInfo ifcInfo;
- TCSDescriptorInfo desInfo;
- TUsbcEndpointResource epRes;
-
- switch (aFunction)
- {
- case RDevUsbcScClient::EControlEndpointZeroRequestError:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointZeroRequestError"));
- r = KErrNone;
- if (iOwnsDeviceControl || (iValidInterface && iDeviceState == UsbShai::EUsbPeripheralStateConfigured))
- {
- iController->Ep0Stall(this);
- }
- else
- {
- if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
- r = KErrUsbDeviceNotConfigured;
- else
- r = KErrUsbInterfaceNotReady;
- }
- break;
-
- case RDevUsbcScClient::EControlGetAlternateSetting:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetAlternateSetting"));
- if (iValidInterface && iDeviceState == UsbShai::EUsbPeripheralStateConfigured)
- {
- r = iController->GetInterfaceNumber(this, param);
- if (r == KErrNone)
- {
- r = Kern::ThreadRawWrite(iClient, a1, ¶m, sizeof(param), iClient);
- if (r != KErrNone)
- PanicClientThread(r);
- }
- }
- else
- {
- if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
- r = KErrUsbDeviceNotConfigured;
- else
- r = KErrUsbInterfaceNotReady;
- }
- break;
-
- case RDevUsbcScClient::EControlDeviceStatus:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceStatus"));
- param = iController->GetDeviceStatus();
- r = Kern::ThreadRawWrite(iClient, a1, ¶m, sizeof(param), iClient);
- if (r != KErrNone)
- PanicClientThread(r);
- break;
-
- case RDevUsbcScClient::EControlEndpointStatus:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointStatus"));
- if (iValidInterface && ValidEndpoint((TInt) a1))
- {
- pEndpoint = iEndpoint[(TInt)a1];
- if (pEndpoint == NULL)
- r = KErrNotSupported;
- else
- {
- param = iController->GetEndpointStatus(this, iEndpoint[(TInt)a1]->RealEpNumber());
- r = Kern::ThreadRawWrite(iClient, a2, ¶m, sizeof(param), iClient);
- if (r != KErrNone)
- PanicClientThread(r);
- }
- }
- else
- {
- if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
- r = KErrUsbDeviceNotConfigured;
- else
- r = KErrUsbInterfaceNotReady;
- }
- break;
-
- case RDevUsbcScClient::EControlEndpointCaps:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointCaps"));
- r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
- if (r != KErrNone)
- PanicClientThread(r);
- iController->EndpointCaps(this, *((TDes8*) a1));
- break;
-
- case RDevUsbcScClient::EControlDeviceCaps:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceCaps"));
- r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
- if (r != KErrNone)
- PanicClientThread(r);
- iController->DeviceCaps(this, *((TDes8*) a1));
- break;
-
- case RDevUsbcScClient::EControlSendEp0StatusPacket:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSendEp0StatusPacket"));
- iController->SendEp0StatusPacket(this);
- break;
-
- case RDevUsbcScClient::EControlHaltEndpoint:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlHaltEndpoint"));
- if (iValidInterface && ValidEndpoint((TInt) a1))
- {
- r = iController->HaltEndpoint(this, iEndpoint[(TInt)a1]->RealEpNumber());
- }
- else
- {
- if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
- r = KErrUsbDeviceNotConfigured;
- else
- r = KErrUsbInterfaceNotReady;
- }
- break;
-
- case RDevUsbcScClient::EControlClearHaltEndpoint:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlClearHaltEndpoint"));
- if (iValidInterface && ValidEndpoint((TInt) a1))
- {
- r = iController->ClearHaltEndpoint(this, iEndpoint[(TInt)a1]->RealEpNumber());
- }
- else
- {
- if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured)
- r = KErrUsbDeviceNotConfigured;
- else
- r = KErrUsbInterfaceNotReady;
- }
- break;
-
- case RDevUsbcScClient::EControlDumpRegisters:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlDumpRegisters"));
- iController->DumpRegisters();
- break;
-
- case RDevUsbcScClient::EControlReleaseDeviceControl:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlReleaseDeviceControl"));
- iController->ReleaseDeviceControl(this);
- iOwnsDeviceControl = EFalse;
- break;
-
- case RDevUsbcScClient::EControlEndpointZeroMaxPacketSizes:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointZeroMaxPacketSizes"));
- r = iController->EndpointZeroMaxPacketSizes();
- break;
-
- case RDevUsbcScClient::EControlSetEndpointZeroMaxPacketSize:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetEndpointZeroMaxPacketSize"));
- r = iController->SetEndpointZeroMaxPacketSize(reinterpret_cast<TInt>(a1));
- break;
-
- case RDevUsbcScClient::EControlGetEndpointZeroMaxPacketSize:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointZeroMaxPacketSize"));
- r = iController->Ep0PacketSize();
- break;
-
- case RDevUsbcScClient::EControlGetDeviceDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceDescriptor"));
- r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
- if (r != KErrNone)
- PanicClientThread(r);
- r = iController->GetDeviceDescriptor(iClient, *((TDes8*) a1));
- break;
-
- case RDevUsbcScClient::EControlSetDeviceDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceDescriptor"));
- BREAK_IF_NULL_ARG(a1,r);
- r = iController->SetDeviceDescriptor(iClient, *((TDes8*) a1));
- break;
-
- case RDevUsbcScClient::EControlGetDeviceDescriptorSize:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceDescriptorSize"));
- BREAK_IF_NULL_ARG(a1,r);
- r = iController->GetDeviceDescriptorSize(iClient, *((TDes8*) a1));
- break;
-
- case RDevUsbcScClient::EControlGetConfigurationDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationDescriptor"));
- r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0 , 0, iClient);
- if (r != KErrNone)
- PanicClientThread(r);
- r = iController->GetConfigurationDescriptor(iClient, *((TDes8*) a1));
- break;
-
- case RDevUsbcScClient::EControlGetConfigurationDescriptorSize:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationDescriptorSize"));
- if (a1 != NULL)
- {
- r = iController->GetConfigurationDescriptorSize(iClient, *((TDes8*) a1));
- }
- else
- r = KErrArgument;
- break;
-
- case RDevUsbcScClient::EControlSetConfigurationDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetConfigurationDescriptor"));
- r = iController->SetConfigurationDescriptor(iClient, *((TDes8*) a1));
- break;
-
- case RDevUsbcScClient::EControlGetInterfaceDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetInterfaceDescriptor"));
- r = iController->GetInterfaceDescriptor(iClient, this, (TInt) a1, *((TDes8*) a2));
- break;
-
- case RDevUsbcScClient::EControlGetInterfaceDescriptorSize:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetInterfaceDescriptorSize"));
- r = iController->GetInterfaceDescriptorSize(iClient, this, (TInt) a1, *(TDes8*) a2);
- break;
-
- case RDevUsbcScClient::EControlSetInterfaceDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetInterfaceDescriptor"));
- r = iController->SetInterfaceDescriptor(iClient, this, (TInt) a1, *((TDes8*) a2));
- break;
-
- case RDevUsbcScClient::EControlGetEndpointDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointDescriptor"));
- r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
- if (r != KErrNone)
- PanicClientThread(r);
- ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
- r = (ep<0)?ep:iController->GetEndpointDescriptor(iClient, this, epInfo.iSetting,
- ep, *(TDes8*) epInfo.iArg);
- break;
-
- case RDevUsbcScClient::EControlGetEndpointDescriptorSize:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointDescriptorSize"));
- r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
- if (r != KErrNone)
- PanicClientThread(r);
- ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
- r = iController->GetEndpointDescriptorSize(iClient, this, epInfo.iSetting,
- ep, *(TDes8*) epInfo.iArg);
- break;
-
- case RDevUsbcScClient::EControlSetEndpointDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetEndpointDescriptor"));
- r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
- if (r != KErrNone)
- PanicClientThread(r);
- ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
- r = iController->SetEndpointDescriptor(iClient, this, epInfo.iSetting,
- ep, *(TDes8*)epInfo.iArg);
- break;
-
- case RDevUsbcScClient::EControlGetDeviceQualifierDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceQualifierDescriptor"));
- r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
- if (r != KErrNone)
- PanicClientThread(r);
- r = iController->GetDeviceQualifierDescriptor(iClient, *((TDes8*) a1));
- break;
-
- case RDevUsbcScClient::EControlSetDeviceQualifierDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceQualifierDescriptor"));
- BREAK_IF_NULL_ARG(a1,r);
- r = iController->SetDeviceQualifierDescriptor(iClient, *((TDes8*) a1));
- break;
-
- case RDevUsbcScClient::EControlGetOtherSpeedConfigurationDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetOtherSpeedConfigurationDescriptor"));
- r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0 , 0, iClient);
- if (r != KErrNone)
- PanicClientThread(r);
- r = iController->GetOtherSpeedConfigurationDescriptor(iClient, *((TDes8*) a1));
- break;
-
- case RDevUsbcScClient::EControlSetOtherSpeedConfigurationDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetOtherSpeedConfigurationDescriptor"));
- r = iController->SetOtherSpeedConfigurationDescriptor(iClient, *((TDes8*) a1));
- break;
-
-
- case RDevUsbcScClient::EControlGetCSInterfaceDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSInterfaceDescriptor"));
- r = iController->GetCSInterfaceDescriptorBlock(iClient, this, (TInt) a1, *((TDes8*) a2));
- break;
-
- case RDevUsbcScClient::EControlGetCSInterfaceDescriptorSize:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSInterfaceDescriptorSize"));
- r = iController->GetCSInterfaceDescriptorBlockSize(iClient, this, (TInt) a1, *(TDes8*) a2);
- break;
-
- case RDevUsbcScClient::EControlGetCSEndpointDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSEndpointDescriptor"));
- r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
- if (r != KErrNone)
- PanicClientThread(r);
- ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
- r = iController->GetCSEndpointDescriptorBlock(iClient, this, epInfo.iSetting,
- ep, *(TDes8*) epInfo.iArg);
- break;
-
- case RDevUsbcScClient::EControlGetCSEndpointDescriptorSize:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSEndpointDescriptorSize"));
- r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
- if (r != KErrNone)
- PanicClientThread(r);
- ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
- r = iController->GetCSEndpointDescriptorBlockSize(iClient, this, epInfo.iSetting,
- ep, *(TDes8*) epInfo.iArg);
- break;
-
- case RDevUsbcScClient::EControlSignalRemoteWakeup:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSignalRemoteWakeup"));
- r = iController->SignalRemoteWakeup();
- break;
-
- case RDevUsbcScClient::EControlDeviceDisconnectFromHost:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceDisconnectFromHost"));
- r = iController->UsbDisconnect();
- break;
-
- case RDevUsbcScClient::EControlDeviceConnectToHost:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceConnectToHost"));
- r = iController->UsbConnect();
- break;
-
- case RDevUsbcScClient::EControlDevicePowerUpUdc:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlDevicePowerUpUdc"));
- r = iController->PowerUpUdc();
- break;
-
- case RDevUsbcScClient::EControlSetDeviceControl:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceControl"));
- r = iController->SetDeviceControl(this);
- if (r == KErrNone)
- {
- iOwnsDeviceControl = ETrue;
- if (iEp0Endpoint == NULL)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceControl"));
- r = SetupEp0();
- if (r != KErrNone)
- {
- __KTRACE_OPT(KPANIC, Kern::Printf(" Error: SetupEp0() failed"));
- iController->ReleaseDeviceControl(this);
- iOwnsDeviceControl=EFalse;
- DestroyEp0();
- }
- }
- }
- else
- r = KErrInUse;
- break;
-
- case RDevUsbcScClient::EControlCurrentlyUsingHighSpeed:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlCurrentlyUsingHighSpeed"));
- r = iController->CurrentlyUsingHighSpeed();
- break;
-
- case RDevUsbcScClient::EControlSetInterface:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetInterface"));
- r = Kern::ThreadRawRead(iClient, a2, &ifcInfo, sizeof(ifcInfo));
- if (r != KErrNone)
- PanicClientThread(r);
- r = SetInterface((TInt) a1, &ifcInfo);
- break;
-
- case RDevUsbcScClient::EControlReleaseInterface:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlReleaseInterface"));
- if (!iRealizeCalled)
- {
- r = iController->ReleaseInterface(this, (TInt) a1);
- if (r == KErrNone)
- {
- DestroyInterface((TUint) a1);
- }
- else
- {
- __KTRACE_OPT(KPANIC, Kern::Printf(" Error in PIL: LDD interface won't be released."));
- }
- }
- else
- r = KErrUsbAlreadyRealized;
- break;
-
- case RDevUsbcScClient::EControlSetCSInterfaceDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetCSInterfaceDescriptor"));
- r = Kern::ThreadRawRead(iClient, a1, &desInfo, sizeof(desInfo));
- if (r != KErrNone)
- PanicClientThread(r);
- r = iController->SetCSInterfaceDescriptorBlock(iClient, this, desInfo.iSetting,
- *reinterpret_cast<const TDes8*>(desInfo.iArg),
- desInfo.iSize);
- break;
-
- case RDevUsbcScClient::EControlSetCSEndpointDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetCSEndpointDescriptor"));
- r = Kern::ThreadRawRead(iClient, a1, &desInfo, sizeof(desInfo));
- if (r != KErrNone)
- PanicClientThread(r);
- ep = EpFromAlternateSetting(desInfo.iSetting, desInfo.iEndpoint);
- r = iController->SetCSEndpointDescriptorBlock(iClient, this, desInfo.iSetting, ep,
- *reinterpret_cast<const TDes8*>(desInfo.iArg),
- desInfo.iSize);
- break;
-
- case RDevUsbcScClient::EControlGetStringDescriptorLangId:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetStringDescriptorLangId"));
- r = iController->GetStringDescriptorLangId(iClient, *((TDes8*) a1));
- break;
-
- case RDevUsbcScClient::EControlSetStringDescriptorLangId:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetStringDescriptorLangId"));
- r = iController->SetStringDescriptorLangId(reinterpret_cast<TUint>(a1));
- break;
-
- case RDevUsbcScClient::EControlGetManufacturerStringDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetManufacturerStringDescriptor"));
- r = iController->GetManufacturerStringDescriptor(iClient, *((TPtr8*) a1));
- break;
-
- case RDevUsbcScClient::EControlSetManufacturerStringDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetManufacturerStringDescriptor"));
- r = iController->SetManufacturerStringDescriptor(iClient, *((TPtr8*) a1));
- break;
-
- case RDevUsbcScClient::EControlRemoveManufacturerStringDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveManufacturerStringDescriptor"));
- r = iController->RemoveManufacturerStringDescriptor();
- break;
-
- case RDevUsbcScClient::EControlGetProductStringDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetProductStringDescriptor"));
- r = iController->GetProductStringDescriptor(iClient, *((TPtr8*) a1));
- break;
-
- case RDevUsbcScClient::EControlSetProductStringDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetProductStringDescriptor"));
- r = iController->SetProductStringDescriptor(iClient, *((TPtr8*) a1));
- break;
-
- case RDevUsbcScClient::EControlRemoveProductStringDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveProductStringDescriptor"));
- r = iController->RemoveProductStringDescriptor();
- break;
-
- case RDevUsbcScClient::EControlGetSerialNumberStringDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetSerialNumberStringDescriptor"));
- r = iController->GetSerialNumberStringDescriptor(iClient, *((TPtr8*) a1));
- break;
-
- case RDevUsbcScClient::EControlSetSerialNumberStringDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetSerialNumberStringDescriptor"));
- r = iController->SetSerialNumberStringDescriptor(iClient, *((TPtr8*) a1));
- break;
-
- case RDevUsbcScClient::EControlRemoveSerialNumberStringDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveSerialNumberStringDescriptor"));
- r = iController->RemoveSerialNumberStringDescriptor();
- break;
-
- case RDevUsbcScClient::EControlGetConfigurationStringDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationStringDescriptor"));
- r = iController->GetConfigurationStringDescriptor(iClient, *((TPtr8*) a1));
- break;
-
- case RDevUsbcScClient::EControlSetConfigurationStringDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetConfigurationStringDescriptor"));
- r = iController->SetConfigurationStringDescriptor(iClient, *((TPtr8*) a1));
- break;
-
- case RDevUsbcScClient::EControlRemoveConfigurationStringDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveConfigurationStringDescriptor"));
- r = iController->RemoveConfigurationStringDescriptor();
- break;
-
- case RDevUsbcScClient::EControlGetStringDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetStringDescriptor"));
- r = iController->GetStringDescriptor(iClient, (TUint8) (TInt) a1, *((TPtr8*) a2));
- break;
-
- case RDevUsbcScClient::EControlSetStringDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetStringDescriptor"));
- r = iController->SetStringDescriptor(iClient, (TUint8) (TInt) a1, *((TPtr8*) a2));
- break;
-
- case RDevUsbcScClient::EControlRemoveStringDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveStringDescriptor"));
- r = iController->RemoveStringDescriptor((TUint8) (TInt) a1);
- break;
-
- case RDevUsbcScClient::EControlQueryEndpointResourceUse:
- {
- __KTRACE_OPT(KUSB, Kern::Printf("EControlQueryEndpointResourceUse"));
- epRes = (TUsbcEndpointResource)((TInt) a2);
- TInt realEp=-1;
- r = GetRealEpForEpResource((TInt)a1, realEp);
- if (r==KErrNone)
- r = iController->QueryEndpointResource(this, realEp, epRes);
- break;
- }
- case RDevUsbcScClient::EControlSetOtgDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlSetOtgDescriptor"));
- r = iController->SetOtgDescriptor(iClient, *((const TDesC8*)a1));
- break;
-
- case RDevUsbcScClient::EControlGetOtgDescriptor:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetOtgDescriptor"));
- r = iController->GetOtgDescriptor(iClient, *((TDes8*)a1));
- break;
-
- case RDevUsbcScClient::EControlGetOtgFeatures:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlGetOtgFeatures"));
- r = iController->GetOtgFeatures(iClient, *((TDes8*)a1));
- break;
-
- case RDevUsbcScClient::EControlRealizeInterface:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlRealizeInterface"));
- r = RealizeInterface();
- break;
- case RDevUsbcScClient::EControlStartNextInAlternateSetting:
- __KTRACE_OPT(KUSB, Kern::Printf("EControlStartNextInAlternateSetting"));
- r = StartNextInAlternateSetting();
- break;
-
- default:
- __KTRACE_OPT(KUSB, Kern::Printf("Function code not supported"));
- r = KErrNotSupported;
- }
-
- return r;
- }
-// end DoControl.
-
-
-
-//
-// Overriding DObject virtual
-//
-TInt DLddUsbcScChannel::RequestUserHandle(DThread* aThread, TOwnerType /*aType*/)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::RequestUserHandle"));
- // The USB client LDD is not designed for a channel to be shared between
- // threads. It saves a pointer to the current thread when it is opened, and
- // uses this to complete any asynchronous requests.
- // It is therefore not acceptable for the handle to be duplicated and used
- // by another thread:
- if (aThread == iClient)
- {
- return KErrNone;
- }
- else
- {
- return KErrAccessDenied;
- }
- }
-
-inline TInt DLddUsbcScChannel::GetRealEpForEpResource(TInt aEndpoint, TInt& aRealEp)
- {
- if (iEndpoint) // if we've enumerated at least once, proceed as normal.
- {
- if (aEndpoint <= iNumberOfEndpoints && aEndpoint >= 0)
- {
- aRealEp=iEndpoint[aEndpoint]->RealEpNumber();
- return KErrNone;
- }
- }
- else // Assume alternate setting 0.
- {
- if (iAlternateSettingList) // Check it has been set up.
- {
- TUsbcScAlternateSetting* alt = iAlternateSettingList->iHead;
- if (alt && (aEndpoint <= alt->iNumberOfEndpoints && aEndpoint >= 0))
- {
- aRealEp= alt->iEndpoint[aEndpoint]->RealEpNumber();
- return KErrNone;
- }
- }
- }
- return KErrUsbDeviceNotConfigured;
- }
-
-
-TUsbcEndpointInfoArray::TUsbcEndpointInfoArray(const TUsbcScEndpointInfo* aData, TInt aDataSize)
- {
- iType = EUsbcScEndpointInfo;
- iData = (TUint8*) aData;
- if (aDataSize>0)
- iDataSize = aDataSize;
- else
- iDataSize = sizeof(TUsbcScEndpointInfo);
- }
-
-
-//
-// SetInterface
-//
-// Called from DoControl. Sets the configuration of a given Interface. // Needs changing
-// All interfaces must be configured before one can be used.
-//
-
-TInt DLddUsbcScChannel::SetInterface(TInt aInterfaceNumber, TUsbcScIfcInfo* aInfoBuf)
- {
- // Copy interface description.
-
- if (iRealizeCalled)
- return KErrUsbAlreadyRealized;
-
- if (!iAlternateSettingList)
- {
- iAlternateSettingList = new TUsbcScAlternateSettingList;
- if (iAlternateSettingList==NULL)
- {
- return KErrNoMemory;
- }
- }
-
- // Read descriptor in
- TUsbcScInterfaceInfoBuf ifc_info_buf;
- TUsbcScInterfaceInfoBuf* const ifc_info_buf_ptr = aInfoBuf->iInterfaceData;
- const TInt srcLen = Kern::ThreadGetDesLength(iClient, ifc_info_buf_ptr);
-
- __KTRACE_OPT(KUSB, Kern::Printf("SetInterface srcLen = %d len = %d", srcLen, ifc_info_buf.Length() ));
-
- if (srcLen < ifc_info_buf.Length())
- {
- __KTRACE_OPT(KUSB, Kern::Printf("SetInterface can't copy"));
- PanicClientThread(EDesOverflow);
- }
-
- TInt r = Kern::ThreadDesRead(iClient, ifc_info_buf_ptr, ifc_info_buf, 0, KChunkShiftBy0);
- if (r != KErrNone)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("SetInterface Copy failed reason=%d", r));
- PanicClientThread(r);
- }
-
- // The list of endpoints is within the interface info.
- TUsbcScEndpointInfo* pEndpointData = ifc_info_buf().iEndpointData;
-
- const TInt num_endpoints = ifc_info_buf().iTotalEndpointsUsed;
- __KTRACE_OPT(KUSB, Kern::Printf("SetInterface num_endpoints=%d", num_endpoints));
- if (num_endpoints>KMaxEndpointsPerClient)
- return KErrOverflow;
-
-
- // Initialize real ep numbers list.
- TInt i;
- TInt real_ep_numbers[KMaxEndpointsPerClient+1]; // range 1->KMaxEndpointsPerClient (0 not used)
- for (i=0; i<=KMaxEndpointsPerClient; i++)
- real_ep_numbers[i] = -1;
-
-
- // See if PIL will accept this interface
- __KTRACE_OPT(KUSB, Kern::Printf("SetInterface Calling controller"));
- TUsbcEndpointInfoArray endpointData = TUsbcEndpointInfoArray(ifc_info_buf().iEndpointData);
-
- r = iController->SetInterface(this,
- iClient,
- aInterfaceNumber,
- ifc_info_buf().iClass,
- aInfoBuf->iString,
- (TInt) ifc_info_buf().iTotalEndpointsUsed,
- endpointData,
- &real_ep_numbers[0],
- ifc_info_buf().iFeatureWord);
-
- __KTRACE_OPT(KUSB, Kern::Printf("SetInterface controller returned %d", r));
- if (r != KErrNone)
- {
- __KTRACE_OPT(KPANIC, Kern::Printf("SetInterface failed reason=%d", r));
- return r;
- }
-
- // create alternate setting record
- TUsbcScAlternateSetting* alternateSettingListRec = new TUsbcScAlternateSetting;
- if (!alternateSettingListRec)
- {
- r = KErrNoMemory;
- goto ReleaseInterface;
- }
-
- // other endpoints
- for (TInt i = 1; i <= num_endpoints; i++, pEndpointData++)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("SetInterface for ep=%d", i));
-
- if ((pEndpointData->iType==UsbShai::KUsbEpTypeControl)
- || (pEndpointData->iDir != UsbShai::KUsbEpDirIn && pEndpointData->iDir != UsbShai::KUsbEpDirOut)
- || (pEndpointData->iSize > 1024) || (pEndpointData->iSize<=0))
- {
- r = KErrUsbBadEndpoint;
- goto CleanUp;
- }
- // Check data
-
- TUint* bufferSize = &(pEndpointData->iBufferSize);
- if (*bufferSize==0)
- *bufferSize= KUsbcScDefaultBufferSize;
-
- TInt pageSize = Kern::RoundToPageSize(1);
- // Round buffersize up to nearest pagesize.
- *bufferSize = (*bufferSize+pageSize-1) & ~(pageSize-1);
-
- TUsbcScEndpoint* ep = new TUsbcScEndpoint(this, iController, pEndpointData, i);
- alternateSettingListRec->iEndpoint[i] = ep;
- if (!ep)
- {
- r = KErrNoMemory;
- goto CleanUp;
- }
- if (ep->Construct() != KErrNone)
- {
- r = KErrNoMemory;
- goto CleanUp;
- }
-
-
- __KTRACE_OPT(KUSB, Kern::Printf("SetInterface for ep=%d rec=0x%08x ep==0x%08x",
- i, alternateSettingListRec, ep));
- }
-
- if (iAlternateSettingList->iHead)
- {
- iAlternateSettingList->iTail->iNext = alternateSettingListRec;
- alternateSettingListRec->iPrevious = iAlternateSettingList->iTail;
- iAlternateSettingList->iTail = alternateSettingListRec;
- }
- else
- {
- iAlternateSettingList->iHead = alternateSettingListRec;
- iAlternateSettingList->iTail = alternateSettingListRec;
- }
-
- alternateSettingListRec->iNext = NULL;
- alternateSettingListRec->iSetting = aInterfaceNumber;
- alternateSettingListRec->iNumberOfEndpoints = num_endpoints;
-
- // Record the 'real' endpoint number used by the PDD in both the Ep and
- // the Req callback:
- for (TInt i = 1; i <= num_endpoints; i++)
- {
- alternateSettingListRec->iEndpoint[i]->SetRealEpNumber(real_ep_numbers[i]);
- }
-
- return KErrNone;
-
- CleanUp:
- delete alternateSettingListRec;
- //Fall Through
-
- ReleaseInterface:
-#if _DEBUG
- TInt r1 = iController->ReleaseInterface(this, aInterfaceNumber);
- __KTRACE_OPT(KUSB, Kern::Printf("Release Interface controller returned %d", r1));
-#else
- (void) iController->ReleaseInterface(this, aInterfaceNumber);
-#endif
- return r;
- }
-// end SetInterface
-
-
-
-#ifdef _DEBUG
-void RealizeInterface_Dump(TUint* aMem)
- {
- TUint *mem= NULL;
- __KTRACE_OPT(KUSB, mem = aMem);
- if (mem!=NULL)
- {
- TInt j;
- Kern::Printf("Final chunk header State:");
- for (j=0; j<30; j+=8)
- 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] );
- };
- };
-#endif
-
-
-/*
-Chunk Created, filled with structure, and passed back to userside.
-*/
-TInt DLddUsbcScChannel::RealizeInterface(void)
-{
- if (iRealizeCalled)
- return KErrUsbAlreadyRealized;
-
- TRealizeInfo bufInfo;
-
- TInt errorOrChunk = KErrNone;
- TBool openedCS = EFalse;
- TInt offset =0;
-
- // Start by creating a temporary scratchpad for endpoint calculations.
- bufInfo.Init(iAlternateSettingList);
-
- // Fill in our scratchpad with all the required endpoints, sorting them
- // in order of size required.
- errorOrChunk = bufInfo.CopyAndSortEndpoints();
- if (errorOrChunk!=KErrNone)
- {
- goto realize_end;
- }
-
- // We now have endpoints sorted in order of size for each altsetting.
- // The very largest for each endpoint will share the first buffer, and all of
- // the second largest ends points will share the second buffer, and so on.
- // Find the highest buffer size for each row, to determine the buffer size,
- // and keep a total of total space needed.
- bufInfo.CalcBuffSizes();
-
- // We now have the max sizes wanted for each endpoint buffer.
- // we also have to total size for all endpoints.
- // and finally we have the total number of buffers.
-
- // Add on size for header, then add on size for guard pages.
- bufInfo.iTotalSize+= KHeaderSize + bufInfo.iTotalBuffers * KGuardSize;
-
- // Create shared Chunk . . . . . . . . . .
- if (iChunkInfo==NULL)
- {
- NKern::ThreadEnterCS();
- openedCS = ETrue;
- errorOrChunk = TUsbcScChunkInfo::New(iChunkInfo, bufInfo.iTotalSize, (DLogicalDevice*) iDevice);
- if (errorOrChunk!=KErrNone)
- {
- goto realize_end;
- }
- }
- else
- {
- // As of writing, the was no way for iChunk to be anything other then NULL.
- // You cannot 'unrealise' and iChunk cannot be set any other way.
- Kern::Fault("DLddUsbcScChannel::RealizeInterface", __LINE__);
- }
-
- // Populate the shared chunk . . . . . . .
-
-
- // First create chunk header.
- errorOrChunk = iChunkInfo->ChunkAlloc(offset, KHeaderSize);
- if (errorOrChunk!=KErrNone)
- {
- if (errorOrChunk==-KErrNoMemory)
- errorOrChunk=KErrNoMemory;
- goto realize_end;
- }
-
-
- offset+=KHeaderSize + KGuardSize; // Also any more for EP0?
-
- // Next, lay out the geometry of the chunk header.
-
- bufInfo.LayoutChunkHeader(iChunkInfo);
-
-
- { // Scope ep0Size
- TInt ep0Size=0;
-
- // Create K-side buffer table
- if (!iBuffers)
- iBuffers = (TUsbcScBuffer *) Kern::AllocZ(sizeof(TUsbcScBuffer) * (bufInfo.iTotalBuffers+2)); // +2 is for ep0.
- if (!iBuffers)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: Error: Alloc iBufers failed!"));
- errorOrChunk = KErrNoMemory;
- goto realize_end;
- }
-
-
- errorOrChunk = SetupEp0();
- if (errorOrChunk)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: SetupEp0 . ERROR %d",errorOrChunk));
- goto realize_end;
- }
-
- ep0Size = iEp0Endpoint->EndpointInfo()->iSize;
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: Setup EP0. max packet size %d", ep0Size));
-
- // Create EP0 buffers
- iEP0OutBuff=bufInfo.iTotalBuffers;
- errorOrChunk = iBuffers[iEP0OutBuff].Construct(KUsbcScBiOut, this, KUsbScEP0OutBufPos, KUsbScEP0OutBufEnd, ep0Size, ep0Size, ep0Size);
- if (errorOrChunk)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: Setup EP0 Out. ERROR %d",errorOrChunk));
- goto realize_end;
- }
-
- iBuffers[iEP0OutBuff].CreateChunkBufferHeader();
- iBuffers[iEP0OutBuff].iCallback = iEp0Endpoint->iRequestCallbackInfo;
- ((TUsbcScBufferRecord*) &(
- bufInfo.iChunkStuct->iBufferOffset[KUsbcScEp0OutBuff*sizeof(TUsbcScBufferRecord)]
- )) ->Set(KUsbScEP0OutBufPos, KUsbScEP0OutBufEnd);
-
-
- iEP0InBuff=bufInfo.iTotalBuffers+1;
- errorOrChunk = iBuffers[iEP0InBuff].Construct( KUsbcScBiIn , this, KUsbScEP0InBufPos , KUsbScEP0InBufEnd , ep0Size, ep0Size, ep0Size);
- if (errorOrChunk)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: Setup EP0 In. ERROR %d",errorOrChunk));
- goto realize_end;
- }
-
- iBuffers[iEP0InBuff].iCallback = iEp0Endpoint->iRequestCallbackInfo;
-
- ((TUsbcScBufferRecord*) &(
- bufInfo.iChunkStuct->iBufferOffset[KUsbcScEp0InBuff*sizeof(TUsbcScBufferRecord)]
- ))->Set(KUsbScEP0InBufPos, KUsbScEP0InBufEnd);
-
-
- } // end ep0Size scope
-
- // Create resources and tables. . . . . .
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: Create resources tables"));
-
- { // scope of bufNum
- // For each EP buffer
- TInt buffNum=0;
- TInt buffMinSize;
- TInt endpointNumber;
- TUsbcScEndpoint* endpointRecord;
- TInt endpoint;
- TInt inout;
- TEndpointSortBufs* bufsd;
- TUsbcScHdrEndpointRecord* epRecord;
- for (endpoint=0; endpoint<bufInfo.iMaxEndpoints; endpoint++) // endpoint = buf row.
- {
- for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
- {
- buffMinSize = KUsbSc_BigBuff_MinimumRamRun;
-
- TInt needed = bufInfo.iBufs[inout].iSizes[endpoint];
- if (needed)
- {
- TInt bufStart = offset;
-
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: buf row:%d inout %d, iBufferOffset[%d+2]=%x",endpoint, inout, buffNum, bufStart));
-
- bufsd = &(bufInfo.iBufs[inout]);
- // and then point all endpoints that use it, towards it.
- TInt altSetting;
- TUint maxReadSize = ~0;
- for (altSetting=0; altSetting < bufInfo.iAltSettings; altSetting++)
- {
- endpointRecord =bufsd->iEp[altSetting*bufInfo.iMaxEndpoints + endpoint];
- if (endpointRecord)
- {
- endpointNumber = endpointRecord->EpNumber();
- endpointRecord->SetBuffer(&iBuffers[buffNum]);
-
- epRecord = (TUsbcScHdrEndpointRecord*) &iChunkInfo->iChunkMem[
- (bufInfo.iAltSettingsTbl->iAltTableOffset[altSetting]) // i.e. Just after altSettingsTbl
- +sizeof(TInt) // after number of endpoints field
- +(endpointNumber-1)*sizeof(TUsbcScHdrEndpointRecord)
- ];
- epRecord->iBufferNo = (TUint8) buffNum;
-
- TInt epType=(endpointRecord->EndpointInfo()->iType);
- epType= (epType& UsbShai::KUsbEpTypeControl)?KUsbScHdrEpTypeControl:
- (epType& UsbShai::KUsbEpTypeIsochronous)?KUsbScHdrEpTypeIsochronous:
- (epType& UsbShai::KUsbEpTypeBulk)?KUsbScHdrEpTypeBulk:
- (epType& UsbShai::KUsbEpTypeInterrupt)?KUsbScHdrEpTypeInterrupt:KUsbScHdrEpTypeUnknown;
-
- epRecord->iType = (inout+1) | (epType<<2);
-
- if (endpointRecord->EndpointInfo()->iReadSize)
- maxReadSize = (maxReadSize <= endpointRecord->EndpointInfo()->iReadSize) ? maxReadSize : endpointRecord->EndpointInfo()->iReadSize;
-
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: endpointNum %d in altSetting %d, alt table @ %d",
- endpointNumber, altSetting,bufInfo.iAltSettingsTbl->iAltTableOffset[altSetting]));
- }
- else
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: endpointNum NA in altSetting %d", altSetting));
- }
-
- } // end for
-
-
- // Alloc memory for buffer.
- TInt grabSize = needed;
- // Generally, a buffer fragmented into smaller memory regions will reduce the efficiency
- // of reading or writing data, and so avoiding the allocation of very small sections
- // is advantageous.
- // However, if only a small amount is being allocated to start with, it is likely
- // smaller amounts of data are to be sent (reducing this advantage), and 1 memory page
- // is a much bigger proportion of the buffer, and so more worth allocating individually.
-
- TInt minimumGrab;
- if (needed<KUsbScBigBuffIs)
- {
- minimumGrab=Kern::RoundToPageSize(1);
- buffMinSize = KUsbSc_SmallBuff_MinimumRamRun; // 1k
- }
- else
- {
- minimumGrab = buffMinSize+Kern::RoundToPageSize(1);
- }
-
- // Grab required memory, in bits as big as possible, down to the minimum size.
- while (needed >= minimumGrab)
- {
- TInt r;
- r = iChunkInfo->ChunkAlloc(offset, grabSize);
- if (r==KErrNone)
- {
- offset+=grabSize;
- needed-=grabSize;
- }
- else
- {
- if (r==-KErrNoMemory)
- {
- grabSize>>=1;
- }
- if ((grabSize<minimumGrab) || (r!=-KErrNoMemory))
- {
- errorOrChunk = r;
- goto realize_end;
- }
- }
- } // end while needed
-
- // Initialize buffer
- iBuffers[buffNum].Construct(inout, this, bufStart, offset, buffMinSize, 0, maxReadSize);
- iBuffers[buffNum].CreateChunkBufferHeader();
- ((TUsbcScBufferRecord*) &(
- bufInfo.iChunkStuct->iBufferOffset[(buffNum+2)*sizeof(TUsbcScBufferRecord)]
- ))->Set(bufStart, offset);
-
-
- // inc pointers for next buffer
- buffNum++;
- offset+=KGuardSize;
- } // end if needed
-
- } // end for inout
- } // end for each buffer
- } // scope of bufNum
-
-#ifdef _DEBUG
- RealizeInterface_Dump((TUint*) iChunkInfo->iChunkMem); // Debug only tracing
-#endif
-
-realize_end:
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: cleanup. Err=%d", errorOrChunk));
- // Here we clean up after either success, or after bailing out early.
-
- bufInfo.Free();
-
- if (iChunkInfo)
- {
- if (errorOrChunk==KErrNone)
- {
- // Everything is looking good - create RChunk for Userside.
- errorOrChunk = Kern::MakeHandleAndOpen(iClient, iChunkInfo->iChunk);
- iRealizeCalled = (errorOrChunk>=0);
- } // endif errorOrChunk
-
- if (errorOrChunk<0) // If error, destroy the chunk.
- {
- iChunkInfo->Close();
- // ChunkInfo will delete itself with DFC, but the pointer here is no longer needed.
- iChunkInfo=NULL;
-
- // Destroy iBuffers
- if (iBuffers)
- {
- TInt i;
- for (i=0; i<(iNumBuffers+2); i++)
- {
- iBuffers[i].iStatusList.Destroy();
- }
- Kern::Free(iBuffers);
- iBuffers=NULL;
- }
-
- }
- else
- {
- iNumBuffers = bufInfo.iTotalBuffers;
- iValidInterface = ETrue; // Let the games commence!
- }
-
- } // endif iChunkInfo
- if (openedCS)
- NKern::ThreadLeaveCS();
-
- __KTRACE_OPT(KUSB, Kern::Printf("Realize: returning %x (%d)", errorOrChunk, errorOrChunk));
- return errorOrChunk;
-} // End RealizeInterface
-
-
-//
-// DestroyAllInterfaces
-//
-
-void DLddUsbcScChannel::DestroyAllInterfaces()
- {
- __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyAllInterfaces"));
- // Removes all interfaces
- if (iAlternateSettingList)
- {
- if (iAlternateSettingList->iHead != NULL)
- {
- TUsbcScAlternateSetting* alternateSettingListRec = iAlternateSettingList->iTail;
- while (alternateSettingListRec)
- {
- iAlternateSettingList->iTail = alternateSettingListRec->iPrevious;
- // If this contains NULL now that is only possible if the record to be deleted was at the head
- __KTRACE_OPT(KUSB, Kern::Printf("Release interface %d \n", alternateSettingListRec->iSetting));
- iController->ReleaseInterface(this, alternateSettingListRec->iSetting);
- delete alternateSettingListRec;
- if (iAlternateSettingList->iTail == NULL) //No more interfaces left
- break;
- else
- {
- iAlternateSettingList->iTail->iNext = NULL;
- alternateSettingListRec = iAlternateSettingList->iTail;
- }
- }
- }
- delete iAlternateSettingList;
- }
-
- iNumberOfEndpoints = 0;
- iAlternateSettingList = NULL;
- iValidInterface = EFalse;
-
- __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyAllInterfaces done"));
- }
-
-
-
-
-
-//
-// DestroyInterface
-//
-
-void DLddUsbcScChannel::DestroyInterface(TUint aInterfaceNumber)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyInterface \n"));
-
- if (iAlternateSetting == aInterfaceNumber)
- {
- ResetInterface(KErrUsbInterfaceNotReady);
- iValidInterface = EFalse;
- iNumberOfEndpoints = 0;
- }
- if (iAlternateSettingList)
- {
- TUsbcScAlternateSetting* alternateSettingListRec = iAlternateSettingList->iTail;
- TUsbcScAlternateSetting* alternateSettingListRecFound = NULL;
- while (alternateSettingListRec)
- {
- if (alternateSettingListRec->iSetting == aInterfaceNumber)
- {
- alternateSettingListRecFound = alternateSettingListRec;
- if (alternateSettingListRec->iPrevious == NULL) //Interface is at HEAD OF List, Should only be if Interface is also at Tail of list
- {
- iAlternateSettingList->iHead = alternateSettingListRec->iNext; // Should be NULL
- if (alternateSettingListRec->iNext)
- iAlternateSettingList->iHead->iPrevious = NULL;
- }
- else if (alternateSettingListRec->iNext == NULL) //Interface is at TAIL OF List
- {
- iAlternateSettingList->iTail = alternateSettingListRecFound->iPrevious;
- iAlternateSettingList->iTail->iNext = NULL;
- }
- else //Somewhere in the middle (would not expect this in normal operation, but here for completeness)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyInterface Middle interface!\n"));
- alternateSettingListRec->iPrevious->iNext = alternateSettingListRec->iNext;
- alternateSettingListRec->iNext->iPrevious = alternateSettingListRec->iPrevious;
- }
-
- delete alternateSettingListRecFound;
- break;
- }
- alternateSettingListRec = alternateSettingListRec->iPrevious;
- }
- }
- }
-
-//
-// SetupEp0
-//
-
-TInt DLddUsbcScChannel::SetupEp0()
- {
- __ASSERT_ALWAYS(iEp0Endpoint==NULL, Kern::Fault("DLddUsbcScChannel::SetupEp0", __LINE__));
-
- TUsbcScEndpointInfo ep0Info = TUsbcScEndpointInfo(UsbShai::KUsbEpTypeControl, UsbShai::KUsbEpDirBidirect);
- ep0Info.iSize = iController->Ep0PacketSize();
-
- TUsbcScEndpoint* ep0 = new TUsbcScEndpoint(this, iController, &ep0Info, 0);
- if (ep0 == NULL)
- {
- return KErrNoMemory;
- }
-
- TInt r = ep0->Construct();
- if (r != KErrNone)
- {
- delete ep0;
- return KErrNoMemory;
- }
-
- ep0->SetRealEpNumber(0);
- ep0->SetBuffer(NULL); // Cannot find it this way.
-
- iEp0Endpoint = ep0;
- return KErrNone;
- }
-
-//
-// DestroyEp0
-//
-
-void DLddUsbcScChannel::DestroyEp0()
- {
- __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DestroyEp0"));
- delete iEp0Endpoint;
- iEp0Endpoint = NULL;
- }
-
-
-void DLddUsbcScChannel::RequestCallbackEp0(TAny* aDLddUsbcScChannel)
- {
- DLddUsbcScChannel* channel = (DLddUsbcScChannel*) aDLddUsbcScChannel;
-
- __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::RequestCallbackEp0"));
-
- if (channel->ChannelClosing())
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Channel Closing: Completion not accepted!"));
- return;
- }
-
- switch (channel->iEp0Endpoint->iRequestCallbackInfo->iTransferDir)
- {
- case UsbShai::EControllerWrite:
- channel->iBuffers[channel->iEP0InBuff].CompleteWrite();
- return;
- case UsbShai::EControllerRead:
- channel->iBuffers[channel->iEP0OutBuff].CompleteRead();
- return;
- default:
- Kern::Printf("DLddUsbcScChannel::RequestCallbackEp0 - Unexpected completion direction %d",channel->iEp0Endpoint->iRequestCallbackInfo->iTransferDir);
- Kern::Fault("DLddUsbcScChannel::RequestCallbackEp0", __LINE__);
- }
- }
-
-
-
-
-
-
-//
-// EndpointStatusChangeCallback
-//
-
-void DLddUsbcScChannel::EndpointStatusChangeCallback(TAny* aDLddUsbcScChannel)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("EndpointStatusChangeCallback"));
- DLddUsbcScChannel* dUsbc = (DLddUsbcScChannel*) aDLddUsbcScChannel;
- if (dUsbc->iChannelClosing)
- return;
- TUint endpointState = dUsbc->iEndpointStatusCallbackInfo.State();
- const TInt reqNo = (TInt) RDevUsbcScClient::ERequestEndpointStatusNotify;
- if (dUsbc->iRequestStatus[reqNo])
- {
- __KTRACE_OPT(KUSB, Kern::Printf("EndpointStatusChangeCallback Notify status"));
- DThread* client = dUsbc->iClient;
- // set client descriptor length to zero
- TInt r = Kern::ThreadRawWrite(client, dUsbc->iEndpointStatusChangePtr, &endpointState,
- sizeof(TUint), client);
- if (r != KErrNone)
- dUsbc->PanicClientThread(r);
- Kern::RequestComplete(dUsbc->iClient, dUsbc->iRequestStatus[reqNo], r);
- dUsbc->iEndpointStatusChangePtr = NULL;
- }
- }
-
-
-//
-// StatusChangeCallback
-//
-
-void DLddUsbcScChannel::StatusChangeCallback(TAny* aDLddUsbcScChannel)
- {
- DLddUsbcScChannel* dUsbc = (DLddUsbcScChannel*) aDLddUsbcScChannel;
- if (dUsbc->iChannelClosing)
- return;
-
- TUsbcDeviceState deviceState;
- TInt i;
- for (i = 0;
- (i < KUsbcDeviceStateRequests) && ((deviceState = dUsbc->iStatusCallbackInfo.State(i)) != UsbShai::EUsbPeripheralNoState);
- ++i)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("StatusChangeCallBack status=%d", deviceState));
- if (deviceState & KUsbAlternateSetting)
- {
- dUsbc->ProcessAlternateSetting(deviceState);
- }
- else
- {
- dUsbc->ProcessDeviceState(deviceState);
- // Send Status to EP0 buffer.
- // Before the client calls RDevUsbcScClient::FinalizeInterface(),
- // this function might be called.
- // So we add a guard for dUsbc->iBuffers
- if( dUsbc->iBuffers )
- {
- dUsbc->iBuffers[dUsbc->iEP0OutBuff].SendEp0StatusPacket(deviceState);
- }
- }
-
- // Only queue if userside is interested
- if (dUsbc->iDeviceStatusNeeded)
- {
- dUsbc->iStatusFifo->AddStatusToQueue(deviceState);
- const TInt reqNo = (TInt) RDevUsbcScClient::ERequestAlternateDeviceStatusNotify;
- if (dUsbc->AlternateDeviceStateTestComplete())
- Kern::RequestComplete(dUsbc->iClient, dUsbc->iRequestStatus[reqNo], KErrNone);
- }
- }
- // We don't want to be interrupted in the middle of this:
- const TInt irqs = NKern::DisableInterrupts(2);
- dUsbc->iStatusCallbackInfo.ResetState();
- NKern::RestoreInterrupts(irqs);
- }
-
-
-void DLddUsbcScChannel::OtgFeatureChangeCallback(TAny* aDLddUsbcScChannel)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("OtgFeatureChangeCallback"));
- DLddUsbcScChannel* dUsbc = (DLddUsbcScChannel*) aDLddUsbcScChannel;
- if (dUsbc->iChannelClosing)
- return;
-
- TUint8 features;
- // No return value check. Assume OTG always supported here
- dUsbc->iController->GetCurrentOtgFeatures(features);
-
- const TInt reqNo = (TInt) RDevUsbcScClient::ERequestOtgFeaturesNotify;
- if (dUsbc->iRequestStatus[reqNo])
- {
- __KTRACE_OPT(KUSB, Kern::Printf("OtgFeatureChangeCallback Notify status"));
- TInt r = Kern::ThreadRawWrite(dUsbc->iClient, dUsbc->iOtgFeatureChangePtr,
- &features, sizeof(TUint8), dUsbc->iClient);
- if (r != KErrNone)
- dUsbc->PanicClientThread(r);
- Kern::RequestComplete(dUsbc->iClient, dUsbc->iRequestStatus[reqNo], r);
- dUsbc->iOtgFeatureChangePtr = NULL;
- }
- }
-
-
-//
-// SelectAlternateSetting
-//
-
-TInt DLddUsbcScChannel::SelectAlternateSetting(TUint aAlternateSetting)
- {
- TUsbcScEndpoint* ep;
-
- // First, find the alt setting record, which corresponds to the alt setting number.
- TUsbcScAlternateSetting* alternateSettingListRec;
- if(iAlternateSettingList)
- {
- for (alternateSettingListRec = iAlternateSettingList->iHead; alternateSettingListRec; alternateSettingListRec = alternateSettingListRec->iNext)
- if (alternateSettingListRec->iSetting == aAlternateSetting)
- {
- // Record has been located.
-
- // Update current ep setting vars
- iEndpoint = alternateSettingListRec->iEndpoint;
- iNumberOfEndpoints = alternateSettingListRec->iNumberOfEndpoints;
-
-
-
- // Reset buffers for new ep set
- for (TInt i = 1; i <= KMaxEndpointsPerClient; i++)
- {
- ep = alternateSettingListRec->iEndpoint[i];
- if (ep!=NULL)
- ep->StartBuffer(); // Buffer::StartEndpoint(...) sets the necessary parameters to the buffer, for use for a perticular endpoint.
- }
-
- return KErrNone;
- }
- }
- return KErrGeneral;
- }
-
-/* The user calls this to move into the next alternate setting. After this call, it is assumed the user wants to
-Transmit using endpoints belonging to this alternate Setting. Writes to the IN endpoints will be allowed until
-the host changed the alternate setting again
-Returns a 32 int with the top 16 bits represents the sequance, and the botten, the alternatre setting no.
-*/
-TInt32 DLddUsbcScChannel::StartNextInAlternateSetting()
- {
- iUserKnowsAltSetting = ETrue;
- return iAsSeq<<16 | iAlternateSetting;
- }
-
-
-//
-// EpFromAlternateSetting
-//
-
-TInt DLddUsbcScChannel::EpFromAlternateSetting(TUint aAlternateSetting, TInt aEndpoint)
- {
- TUsbcScAlternateSetting* alternateSettingListRec = iAlternateSettingList->iHead;
- while (alternateSettingListRec)
- {
- if (alternateSettingListRec->iSetting == aAlternateSetting)
- {
- if ((aEndpoint <= alternateSettingListRec->iNumberOfEndpoints) &&
- (aEndpoint > 0))
- {
- return alternateSettingListRec->iEndpoint[aEndpoint]->RealEpNumber();
- }
- else
- {
- __KTRACE_OPT(KPANIC, Kern::Printf(" Error: aEndpoint %d wrong for aAlternateSetting %d",
- aEndpoint, aAlternateSetting));
- return KErrNotFound;
- }
- }
- alternateSettingListRec = alternateSettingListRec->iNext;
- }
- __KTRACE_OPT(KPANIC, Kern::Printf(" Error: no aAlternateSetting %d found", aAlternateSetting));
- return KErrNotFound;
- }
-
-//
-// ProcessAlternateSetting
-//
-
-TInt DLddUsbcScChannel::ProcessAlternateSetting(TUint aAlternateSetting)
- {
-
- TUint newSetting = aAlternateSetting&(~KUsbAlternateSetting);
- __KTRACE_OPT(KUSB, Kern::Printf("ProcessAlternateSetting 0x%08x selecting alternate setting 0x%08x", aAlternateSetting, newSetting));
- iUserKnowsAltSetting=EFalse;
- iAlternateSetting = newSetting;
- iAsSeq++;
-
- ResetInterface(KErrUsbInterfaceChange); // kill any outstanding IN transfers
-
- TInt r = SelectAlternateSetting(newSetting);
- if (r != KErrNone)
- return r;
-
-
- StartEpReads();
- return KErrNone;
- }
-
-
-//
-// ProcessDeviceState
-//
-// Called from StatusChangeCallback.
-
-TInt DLddUsbcScChannel::ProcessDeviceState(TUsbcDeviceState aDeviceState)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::ProcessDeviceState(%d -> %d)", iDeviceState, aDeviceState));
- if (iDeviceState == aDeviceState)
- {
- __KTRACE_OPT(KUSB, Kern::Printf(" No state change => nothing to be done."));
- return KErrNone;
- }
- if (iDeviceState == UsbShai::EUsbPeripheralStateSuspended)
- {
- __KTRACE_OPT(KUSB, Kern::Printf(" Coming out of Suspend: old state = %d", iOldDeviceState));
- iDeviceState = iOldDeviceState;
- if (iDeviceState == aDeviceState)
- {
- __KTRACE_OPT(KUSB, Kern::Printf(" New state same as before Suspend => nothing to be done."));
- return KErrNone;
- }
- }
- TBool renumerateState = (aDeviceState == UsbShai::EUsbPeripheralStateConfigured);
- TBool deconfigured = EFalse;
- TInt cancellationCode = KErrNone;
- if (aDeviceState == UsbShai::EUsbPeripheralStateSuspended)
- {
- __KTRACE_OPT(KUSB, Kern::Printf(" Suspending..."));
- iOldDeviceState = iDeviceState;
- // Put PSL into low power mode here
- }
- else
- {
- deconfigured = (iDeviceState == UsbShai::EUsbPeripheralStateConfigured &&
- aDeviceState != UsbShai::EUsbPeripheralStateConfigured);
- if (iDeviceState == UsbShai::EUsbPeripheralStateConfigured)
- {
- if (aDeviceState == UsbShai::EUsbPeripheralStateUndefined)
- cancellationCode = KErrUsbCableDetached;
- else if (aDeviceState == UsbShai::EUsbPeripheralStateAddress)
- cancellationCode = KErrUsbDeviceNotConfigured;
- else if (aDeviceState == UsbShai::EUsbPeripheralStateDefault)
- cancellationCode = KErrUsbDeviceBusReset;
- else
- cancellationCode = KErrUsbDeviceNotConfigured;
- }
- }
- iDeviceState = aDeviceState;
- if (iValidInterface || iOwnsDeviceControl)
- {
-
- // This LDD may not own an interface. It could be some manager reenumerating
- // after its subordinate LDDs have setup their interfaces.
- if (deconfigured)
- {
- DeConfigure(cancellationCode);
- }
- else if (renumerateState)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChannel:: Reumerated!"));
- // Select main interface & latch in new endpoint set
- SelectAlternateSetting(0);
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChannel:: StartReads!"));
- StartEpReads();
- }
- }
-
- const TInt reqNo = (TInt) RDevUsbcScClient::ERequestReEnumerate;
- if (renumerateState && iRequestStatus[reqNo])
- {
- // This lot must be done if we are reenumerated
- Kern::RequestComplete(iClient, iRequestStatus[reqNo], KErrNone);
- }
-
- return KErrNone;
- }
-
-
-TBool DLddUsbcScChannel::AlternateDeviceStateTestComplete()
- {
- TBool completeNow = EFalse;
- const TInt reqNo = (TInt) RDevUsbcScClient::ERequestAlternateDeviceStatusNotify;
- if (iRequestStatus[reqNo])
- {
- // User req is outstanding
- TUint32 deviceState;
- if (iStatusFifo->GetDeviceQueuedStatus(deviceState) == KErrNone)
- {
- // Device state waiting to be sent userside
- completeNow = ETrue;
- __KTRACE_OPT(KUSB, Kern::Printf("StatusChangeCallback Notify status"));
- // set client descriptor length to zero
- TInt r = Kern::ThreadRawWrite(iClient, iStatusChangePtr, &deviceState,
- sizeof(TUint32), iClient);
- if (r != KErrNone)
- PanicClientThread(r);
- iStatusChangePtr = NULL;
- }
- }
- return completeNow;
- }
-
-
-void DLddUsbcScChannel::DeConfigure(TInt aErrorCode)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DeConfigure()"));
- // Called after deconfiguration. Cancels transfers on all endpoints.
- ResetInterface(aErrorCode);
- // Cancel the endpoint status notify request if it is outstanding.
- const TInt KEpNotReq = RDevUsbcScClient::ERequestEndpointStatusNotify;
- if (iRequestStatus[KEpNotReq])
- {
- CancelNotifyEndpointStatus();
- Kern::RequestComplete(iClient, iRequestStatus[KEpNotReq], aErrorCode);
- }
- // We have to reset the alternate setting number when the config goes away.
- SelectAlternateSetting(0);
- iAlternateSetting = 0;
- }
-
-
-void DLddUsbcScChannel::StartEpReads()
- {
- // Queued after enumeration. Starts reads on all endpoints.
- // The endpoint itself decides if it can do a read
- __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 1"));
-
- TInt i;
- TInt8 needsPacket;
-
- for (i=0; i<iNumBuffers; i++)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 2 %d",i));
-
- needsPacket = iBuffers[i].iNeedsPacket;
- if (needsPacket)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 3"));
- iBuffers[i].UpdateBufferList(0,0,(needsPacket==TUsbcScBuffer::KEpIsStarting));
- }
- }
-
- __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 4"));
-
- // now update ep0
- iBuffers[iEP0OutBuff].Ep0CancelLddRead();
- iBuffers[iEP0OutBuff].UpdateBufferList(0,0);
- __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 5"));
-
- }
-
-
-void DLddUsbcScChannel::ResetInterface(TInt aErrorCode)
- {
- if (!iValidInterface && !iOwnsDeviceControl)
- return;
-
- TInt i;
- for (i=0; i<iNumBuffers; i++)
- {
- iBuffers[i].iNeedsPacket=TUsbcScBuffer::KNoEpAssigned;
- }
-
- TUsbcScBuffer* buffer;
-
- for (i = 1; i <= iNumberOfEndpoints; i++)
- {
- // Firstly, cancel ('garbge collect') any stale reads/writes into PIL.
-
- __KTRACE_OPT(KUSB, Kern::Printf("Cancelling transfer ep=%d", i));
- iEndpoint[i]->AbortTransfer();
-
- // All OUT endpoints need a packet sent, to indicate the termination of the current ep 'pipe'.
- // This will complete any current read, or will be read later.
- // All IN endpoints must be simply cancelled, including anything queued.
- // Ep0 operates outside alt settings, and so we don't cancel anything.
-
- buffer=iEndpoint[i]->GetBuffer();
- if (buffer->iDirection==KUsbcScIn)
- {
- buffer->iStatusList.Complete(KErrCancel); //aErrorCode
- buffer->iStatusList.CancelQueued(); //aErrorCode
- }
- else
- buffer->iNeedsPacket=TUsbcScBuffer::KEpIsEnding; // We will send a packet on re-start, which doubles as a 'cancel'
- // for the old alt setting.
- }
- }
-
-
-
-void DLddUsbcScChannel::EmergencyCompleteDfc(TAny* aDLddUsbcScChannel)
- {
- ((DLddUsbcScChannel*) aDLddUsbcScChannel)->DoEmergencyComplete();
- }
-
-TInt DLddUsbcScChannel::DoEmergencyComplete()
- {
- __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DoEmergencyComplete"));
- // cancel any pending DFCs
- // complete all client requests
-
- TUsbcScBuffer* buffer;
- TInt i;
- // Complete EP0 request
-
- TInt direction=iEp0Endpoint->iRequestCallbackInfo->iTransferDir;
- if (direction==UsbShai::EControllerWrite)
- {
- iBuffers[iEP0InBuff].iStatusList.CancelQueued();
- iBuffers[iEP0InBuff].iStatusList.Complete(KErrDisconnected);
- }
- else if (direction==UsbShai::EControllerRead)
- {
- iBuffers[iEP0OutBuff].iStatusList.CancelQueued();
- iBuffers[iEP0OutBuff].iStatusList.Complete(KErrDisconnected);
- }
-
- // Complete other Eps request
- for (i = 1; i <= iNumberOfEndpoints; i++)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Cancelling transfer ep=%d", i));
- buffer=iEndpoint[i]->GetBuffer();
- buffer->iStatusList.CancelQueued();
- buffer->iStatusList.Complete(KErrDisconnected);
- }
-
- // Complete remaining requests
-
- for (TInt i = 0; i < KUsbcMaxRequests; i++)
- {
- if (iRequestStatus[i])
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Complete request 0x%x", iRequestStatus[i]));
- Kern::RequestComplete(iClient, iRequestStatus[i], KErrDisconnected);
- }
- }
- iStatusCallbackInfo.Cancel();
- iEndpointStatusCallbackInfo.Cancel();
- iOtgFeatureCallbackInfo.Cancel();
-
- return KErrNone;
- }
-
-
-void DLddUsbcScChannel::PanicClientThread(TInt aReason)
- {
- Kern::ThreadKill(iClient, EExitPanic, aReason, KUsbLDDKillCat);
- }
-
-// End DLddUsbcScChannel
-
-/*****************************************************************************\
-* TUsbcScEndpoint *
-* *
-* *
-* *
-\*****************************************************************************/
-
-
-// Constructor
-TUsbcScEndpoint::TUsbcScEndpoint(DLddUsbcScChannel* aLDD, DUsbClientController* aController,
- const TUsbcScEndpointInfo* aEndpointInfo, TInt aEndpointNum
- )
- : iRequestCallbackInfo(NULL),
- iController(aController),
- iEndpointInfo(*aEndpointInfo),
- iClientReadPending(EFalse),
- iClientWritePending(EFalse),
- iEndpointNumber(aEndpointNum),
- iRealEpNumber(-1),
- iLdd(aLDD),
- iError(KErrNone),
- iBytesTransferred(0),
- iBuffer(NULL)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::TUsbcScEndpoint"));
- }
-
-
-TInt TUsbcScEndpoint::Construct()
- {
- __KTRACE_OPT(KUSB,Kern::Printf("TUsbcScEndpoint::TUsbcScEndpoint iEndpointNumber %d\n",iEndpointNumber));
-
- iRequestCallbackInfo = new TUsbcRequestCallback(iLdd,
- iEndpointNumber,
- (iEndpointNumber==0)?DLddUsbcScChannel::RequestCallbackEp0:TUsbcScEndpoint::RequestCallback,
- (iEndpointNumber==0)? (TAny*) iLdd: (TAny*) this,
- iLdd->iDfcQ,
- KUsbRequestCallbackPriority);
-
- return (iRequestCallbackInfo == NULL)?KErrNoMemory:KErrNone;
- }
-
-
-TUsbcScEndpoint::~TUsbcScEndpoint()
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::~TUsbcScEndpoint(%d)", iEndpointNumber));
- AbortTransfer();
- delete iRequestCallbackInfo;
- }
-
-// This is called by the PIL, on return from a read or write.
-// Inturn it calls either the read or write function for that buffer.
-
-void TUsbcScEndpoint::RequestCallback(TAny* aTUsbcScEndpoint)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::RequestCallback"));
-
- if (((TUsbcScEndpoint*)aTUsbcScEndpoint)->iLdd->ChannelClosing())
- {
- __KTRACE_OPT(KUSB, Kern::Printf("Channel Closing: Completion not accepted!"));
- return;
- }
-
- switch (((TUsbcScEndpoint*) aTUsbcScEndpoint)->iRequestCallbackInfo->iTransferDir)
- {
- case UsbShai::EControllerWrite:
- ((TUsbcScEndpoint*) aTUsbcScEndpoint)->iBuffer->CompleteWrite();
- return;
- case UsbShai::EControllerRead:
- ((TUsbcScEndpoint*) aTUsbcScEndpoint)->iBuffer->CompleteRead();
- return;
- default:
- Kern::Printf("TUsbcScEndpoint::RequestCallback - Unexpected compleation direction %d",((TUsbcScEndpoint*) aTUsbcScEndpoint)->iRequestCallbackInfo->iTransferDir);
- Kern::Fault("TUsbcScEndpoint::RequestCallback", __LINE__);
- }
- }
-
-
-/*
-
-This is used to tidy up cancel calls into the PIL, regardless of them being reads or writes
-
-*/
-
-void TUsbcScEndpoint::AbortTransfer()
- {
- if (!iLdd->iRealizeCalled)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::AbortTransfer Ep# %d Real Ep # %d - N.R.",iEndpointNumber, iRealEpNumber));
- return;
- }
- else
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::AbortTransfer Ep# %d Real Ep # %d",iEndpointNumber, iRealEpNumber));
- }
-
-
- if (iBuffer && (iBuffer->iStatusList.iState) || (!iRealEpNumber))
- {
- if (iRequestCallbackInfo->iTransferDir==UsbShai::EControllerWrite)
- iController->CancelWriteBuffer(iLdd, iRealEpNumber);
- else if (iRequestCallbackInfo->iTransferDir==UsbShai::EControllerRead)
- iController->CancelReadBuffer(iLdd, iRealEpNumber);
- else
- {
- if (iEndpointNumber!=0) // endpoint zero starts off not sent in any direction, then keeps changing.
- {
- __KTRACE_OPT(KUSB,Kern::Printf("\nTUsbcScEndpoint::AbortTransfer WARNING: Invalid Direction %d on (%d,%d)!\n",iRequestCallbackInfo->iTransferDir,iEndpointNumber, iRealEpNumber));
- }
- else
- {
- __KTRACE_OPT(KUSB, Kern::Printf("\nTUsbcScEndpoint::AbortTransfer Can't stop direction %d on (%d,%d)!\n",iRequestCallbackInfo->iTransferDir,iEndpointNumber, iRealEpNumber));
- }
- }
- }
- else if (!iBuffer)
- {
- __KTRACE_OPT(KUSB,Kern::Printf("\nTUsbcScEndpoint::AbortTransfer WARNING: iBuffer is NULL on (%d,%d)\n",iEndpointNumber, iRealEpNumber));
- return;
- }
-
- if (iRequestCallbackInfo)
- iRequestCallbackInfo->iDfc.Cancel();
- else
- {
- __KTRACE_OPT(KUSB,Kern::Printf("\nTUsbcScEndpoint::AbortTransfer WARNING: iRequestCallbackInfo is NULL\n"));
- }
-
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint Done."));
- }
-
-// End TUsbcScEndpoint
-
-
-/*****************************************************************************\
-* TUsbcScAlternateSettingList *
-* *
-* *
-* *
-\*****************************************************************************/
-
-
-TUsbcScAlternateSetting::TUsbcScAlternateSetting()
- : iNext(NULL),
- iPrevious(NULL),
- iNumberOfEndpoints(0),
- iSetting(0)
- {
- for (TInt i = 0; i <= KMaxEndpointsPerClient; i++)
- {
- iEndpoint[i] = NULL;
- }
- }
-
-
-TUsbcScAlternateSetting::~TUsbcScAlternateSetting()
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScAlternateSetting::~TUsbcScAlternateSetting()"));
- for (TInt i = 0; i <= KMaxEndpointsPerClient; i++)
- {
- delete iEndpoint[i];
- }
- }
-
-// End TUsbcScAlternateSettingList
-
-
-
-TUsbcScAlternateSettingList::TUsbcScAlternateSettingList()
- : iHead(NULL),
- iTail(NULL)
- {
- }
-
-TUsbcScAlternateSettingList::~TUsbcScAlternateSettingList()
- {
- }
-
-
-
-/*****************************************************************************\
-* TUsbcDeviceStatusQueue *
-* *
-* *
-* *
-\*****************************************************************************/
-
-
-TUsbcDeviceStatusQueue::TUsbcDeviceStatusQueue()
- {
- FlushQueue();
- }
-
-
-void TUsbcDeviceStatusQueue::FlushQueue()
- {
- for (TInt i = 0; i < KUsbDeviceStatusQueueDepth; i++)
- {
- iDeviceStatusQueue[i] = KUsbDeviceStatusNull;
- }
- iStatusQueueHead = 0;
- }
-
-
-void TUsbcDeviceStatusQueue::AddStatusToQueue(TUint32 aDeviceStatus)
- {
- // Only add a new status if it is not a duplicate of the one at the head of the queue
- if (!(iStatusQueueHead != 0 &&
- iDeviceStatusQueue[iStatusQueueHead - 1] == aDeviceStatus))
- {
- if (iStatusQueueHead == KUsbDeviceStatusQueueDepth)
- {
- // Discard item at tail of queue
- TUint32 status;
- GetDeviceQueuedStatus(status);
- }
- iDeviceStatusQueue[iStatusQueueHead] = aDeviceStatus;
- iStatusQueueHead++;
- }
- }
-
-
-TInt TUsbcDeviceStatusQueue::GetDeviceQueuedStatus(TUint32& aDeviceStatus)
- {
- TInt r = KErrNone;
- if (iStatusQueueHead <= 0)
- {
- r = KErrGeneral;
- aDeviceStatus = KUsbDeviceStatusNull;
- }
- else
- {
- aDeviceStatus = iDeviceStatusQueue[0];
- for(TInt i = 1; i < KUsbDeviceStatusQueueDepth; i++)
- {
- TUint32 s = iDeviceStatusQueue[i];
- iDeviceStatusQueue[i - 1] = s;
- }
- iStatusQueueHead--;
- iDeviceStatusQueue[KUsbDeviceStatusQueueDepth - 1] = KUsbDeviceStatusNull;
- }
- return r;
- }
-
-// End TUsbcDeviceStatusQueue
-
-//---
-