--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/usbcsc/usbcsc_bil.cpp Thu Dec 17 09:24:54 2009 +0200
@@ -0,0 +1,633 @@
+// Copyright (c) 2008-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\usbcsc_bil.cpp
+//
+//
+
+#include <e32std.h>
+#include <e32std_private.h>
+#include <d32usbcsc.h>
+#include <e32debug.h>
+
+/** @file usbcsc_bil.cpp
+
+ Buffer Interface Layer for USB Client Device driver stack, using shared chunks.
+
+ @internalTechnology
+*/
+
+EXPORT_C TInt RDevUsbcScClient::FinalizeInterface()
+ {
+ TInt errorOrhandle = DoControl(EControlRealizeInterface); //returns a error value or chunk handle
+ TInt r = iSharedChunk.SetReturnedHandle(errorOrhandle);
+ iEndpointStatus = 0x00; //all endpoints are closed at the moment
+ iAlternateSetting = 0;
+ iNewAltSetting = 0;
+ iAltSettingSeq = 0;
+ return r;
+ }
+
+
+EXPORT_C TInt RDevUsbcScClient::FinalizeInterface(RChunk*& aChunk)
+ {
+ TInt errorOrhandle = DoControl(EControlRealizeInterface);
+ iSharedChunk.SetReturnedHandle(errorOrhandle);
+ iEndpointStatus = 0x00; //all endpoints are closed at the moment
+ iAlternateSetting = 0;
+ return aChunk->SetReturnedHandle(errorOrhandle);
+ }
+
+
+EXPORT_C TInt RDevUsbcScClient::OpenEndpoint(TEndpointBuffer& aEpB, TInt aEpI)
+ {
+ TUsbcScHdrEndpointRecord* endpointInf = NULL;
+ TBuf8<KUsbDescSize_Endpoint> descriptor;
+ TUsbcScChunkHeader chunkHeader(iSharedChunk);
+ //Do some validity checks
+ if((aEpB.iInState != TEndpointBuffer::ENotValid) && (aEpB.iOutState != TEndpointBuffer::ENotValid))
+ return KErrArgument;
+
+ TInt nEndpoints = chunkHeader.GetNumberOfEndpoints(iAlternateSetting);
+ if ((aEpI < KEp0Number) && (aEpI > nEndpoints)) // Check endpoint number range
+ return KErrNotFound;
+
+ if(iEndpointStatus & (1 << aEpI)) // Check that endpoint isn't already opene
+ return KErrInUse;
+
+ if(aEpI == KEp0Number) //endpoint 0
+ {
+ TUsbcScHdrEndpointRecord ep0= TUsbcScHdrEndpointRecord(KUsbcScEndpointZero, KUsbScHdrEpDirectionBiDir | KUsbScHdrEpTypeControl);
+ aEpB.Construct(this,iSharedChunk.Base(), &ep0 ,aEpI,
+ (SUsbcScBufferHeader*) ((TUint)iSharedChunk.Base() + (chunkHeader.iBuffers)->Ep0Out()->Offset()));
+
+ aEpB.iBufferStartAddr = (TUint8*) ((TUint)iSharedChunk.Base() + (chunkHeader.iBuffers)->Ep0In()->Offset());
+ aEpB.iSize = chunkHeader.iBuffers->Ep0In()->Size();
+ }
+ else // If normal endpoint (!ep0)
+ {
+ TUsbcScBufferRecord* buf = chunkHeader.GetBuffer(iAlternateSetting,aEpI,endpointInf);
+ if (!buf)
+ return KErrGeneral;
+ // Set up endpoint members
+ aEpB.iBufferStartAddr = (TUint8*) (buf->Offset() + (TUint)iSharedChunk.Base());
+ aEpB.iSize = buf->Size();
+ TInt r = GetEndpointDescriptor(iAlternateSetting, aEpI, descriptor);
+ if(r != KErrNone) // We need this to be able to calculate alignment
+ {
+ return r;
+ }
+
+ if (endpointInf->Direction()&KUsbScHdrEpDirectionIn)
+ { //in case of IN endpoints, first endpoint buffer location points to end offset
+ aEpB.Construct(this,iSharedChunk.Base(),endpointInf,aEpI);
+ if (iInAltSetting==KErrEof)
+ aEpB.iInState=TEndpointBuffer::EEOF;
+
+ }
+ else
+ {
+ SUsbcScBufferHeader *endpointHdr = (SUsbcScBufferHeader *) aEpB.iBufferStartAddr;
+ //In this case,SUsbcScBufferHeader points to full OUT endpoint header
+ aEpB.Construct(this,iSharedChunk.Base(),endpointInf,aEpI, endpointHdr);
+ }
+ }
+ iEndpointStatus |= (1 << aEpI);
+
+#ifdef _DEBUG
+ aEpB.Dump();
+ RDebug::Printf("iEndpointStatus: %x \n",iEndpointStatus);
+#endif
+ return KErrNone;
+ }
+
+
+//Internal, used by RDevUsbcScClient::StartNextOutAlternateSetting(...)
+//This drains any old data from an OUT buffer, and gets it ready for reading an ep.
+//aBufferOffset - The offset, into the chunk, that the buffer in question, may be found.
+
+TInt RDevUsbcScClient::Drain(TUint aBufferOffset)
+{
+ TUint8* base = iSharedChunk.Base();
+ SUsbcScBufferHeader* endpointHdr = (SUsbcScBufferHeader*) (aBufferOffset+base);
+ TUint localTail = endpointHdr->iBilTail;
+ TUsbcScTransferHeader* currentTransfer;
+ TUint16 next = (iAltSettingSeq+1)&0xFFFF;
+ TInt err=KErrNone;
+
+ while (ETrue)
+ {
+ if (localTail == (TUint) endpointHdr->iHead)
+ {
+ err = KErrNotReady;
+ break;
+ }
+ currentTransfer = (TUsbcScTransferHeader*) (base + localTail);
+
+ if (currentTransfer->iAltSettingSeq == next)
+ {
+ iNewAltSetting=currentTransfer->iAltSetting; // record new alt setting
+ break;
+ }
+ else
+ {
+ localTail = currentTransfer->iNext;
+ }
+ } // end while
+ endpointHdr->iBilTail = localTail;
+ endpointHdr->iTail = localTail;
+ return err;
+}
+
+//Internal, used by RDevUsbcScClient::StartNextOutAlternateSetting(...)
+//This method checks that the OUT buffer is ready for reading an ep.
+//aBufferOffset - The offset, into the chunk, that the buffer in question, may be found.
+
+TInt RDevUsbcScClient::Peek(TUint aBufferOffset)
+{
+ TUint8* base = iSharedChunk.Base();
+ SUsbcScBufferHeader* endpointHdr = (SUsbcScBufferHeader*) (aBufferOffset+base);
+ TUint localTail = endpointHdr->iBilTail;
+ TUsbcScTransferHeader* currentTransfer = (TUsbcScTransferHeader*) (base + localTail);
+
+ if ((localTail == (TUint)endpointHdr->iHead) || (currentTransfer->iAltSettingSeq != (iAltSettingSeq+1)&0xFFFF))
+ // if alternate setting has not changed
+ return KErrNotReady;
+ else
+ {
+ iNewAltSetting=currentTransfer->iAltSetting;
+ return KErrNone;
+ }
+}
+
+//Internal, used by RDevUsbcScClient::StartNextOutAlternateSetting(...)
+//This method is called if an alternate setting change happens from a set of ONLY IN endpoints.
+//Used to find the least possible alternate setting it can return to the user, stored in iNewAltSetting
+//Returns the sequence number of the 'latest' alternate setting it can switch to
+
+TInt RDevUsbcScClient::FindNextAlternateSetting()
+ {
+ TUsbcScChunkHeader chunkHeader(iSharedChunk);
+ TUsbcScHdrEndpointRecord* endpointInf = NULL;
+ TUint bufOff;
+ TInt altSet;
+ TInt ep;
+ TInt bufNum;
+
+ RArray <TInt> bufferOffset; // Array to contain all OUT enpoint buffer offsets
+ // Populate array
+ for (altSet = 0; altSet < chunkHeader.iAltSettings->iNumOfAltSettings ; altSet++)
+ {
+ TInt numEndpoints = chunkHeader.GetNumberOfEndpoints(altSet);
+ for (ep = 1; ep <= numEndpoints ; ep ++)
+ {
+ bufOff = chunkHeader.GetBuffer(altSet, ep, endpointInf)->Offset();
+ if ((endpointInf->Direction() & KUsbScHdrEpDirectionOut) && (bufferOffset.Find(bufOff) == KErrNotFound))
+ {
+ bufferOffset.Append(bufOff);
+ }
+ }
+ }
+
+ TInt err = KErrNotFound;
+ TUint16 altSetSeqDelta = 0;
+ TUint16 currentaltSetSeqDelta = 0;
+ TBool noNewSettingFound = ETrue;
+ TInt altSetSeq = iAltSettingSeq;
+ TUint8* base = iSharedChunk.Base();
+
+ for (bufNum = 0; bufNum < bufferOffset.Count(); bufNum++) // Scan all OUT buffers
+ {
+ SUsbcScBufferHeader* endpointHdr = (SUsbcScBufferHeader*) (bufferOffset[bufNum] + base);
+ TUint localTail = endpointHdr->iBilTail;
+ TUsbcScTransferHeader* currentTransfer;
+ TUint16 next = (iAltSettingSeq+1)&0xFFFF;
+
+ while (ETrue)
+ {
+ if (localTail == (TUint) endpointHdr->iHead)
+ {
+ break; // This OUT endpoint buffer has no data, proceed checking with other OUT endpoint buffers
+ }
+ currentTransfer = (TUsbcScTransferHeader*) (base + localTail);
+
+ if (currentTransfer->iAltSettingSeq != iAltSettingSeq)
+ {
+ if (currentTransfer->iAltSettingSeq == next)
+ {
+ altSetSeq = currentTransfer->iAltSettingSeq;
+ iNewAltSetting = currentTransfer->iAltSetting; // record new alt setting
+ err = KErrNone;
+ break;
+ }
+
+ if (noNewSettingFound)
+ {
+ altSetSeqDelta = Abs(iAltSettingSeq - currentTransfer->iAltSettingSeq);
+ altSetSeq = currentTransfer->iAltSettingSeq;
+ iNewAltSetting = currentTransfer->iAltSetting; // record new alt setting
+ noNewSettingFound = EFalse;
+ }
+ else
+ {
+ currentaltSetSeqDelta = Abs(iAltSettingSeq - currentTransfer->iAltSettingSeq);
+ if (currentaltSetSeqDelta < altSetSeqDelta)
+ {
+ altSetSeqDelta = currentaltSetSeqDelta;
+ altSetSeq = currentTransfer->iAltSettingSeq;
+ iNewAltSetting = currentTransfer->iAltSetting;
+ }
+ }
+ break;
+ }
+
+ localTail = currentTransfer->iNext;
+ } // end while
+
+ if (!err) // Found an alt set sequence one after iAltSettingSeq
+ {
+ break; // found 'the next' alternate setting, exit for loop
+ }
+
+ }// for loop
+
+ return altSetSeq;
+ }
+
+EXPORT_C TInt RDevUsbcScClient::StartNextOutAlternateSetting(TBool aFlush)
+ {
+ TUsbcScChunkHeader chunkHeader(iSharedChunk);
+
+ //if endpoints are still open, return KErrInUse
+ if((iEndpointStatus&~1) != 0)
+ {
+ return KErrInUse;
+ }
+
+ TInt r;
+ TInt ep;
+ TInt noEp;
+ TUint bufOff;
+ TBool inEndpointSet = ETrue;
+ TUsbcScHdrEndpointRecord* endpointInf = NULL;
+
+ // check if alternate setting contains all IN endpoints
+ noEp = chunkHeader.GetNumberOfEndpoints(iAlternateSetting);
+
+ // for each used buffer.
+ for (ep=1;ep<=noEp;ep++)
+ {
+ bufOff = chunkHeader.GetBuffer(iAlternateSetting,ep,endpointInf)->Offset();
+
+ if (endpointInf->Direction() & KUsbScHdrEpDirectionOut)
+ {
+ inEndpointSet = EFalse;
+ if (aFlush)
+ r = Drain(bufOff); // we need to remove anythng in the way, and get it ready for reading.
+ else
+ r = Peek(bufOff); // we need to check it is ready for reading!
+ if (r)
+ return r;
+ }
+ }
+
+
+ TInt altSeq = 0;
+ if (inEndpointSet) // If all endpoints in the current alternate setting are IN endpoints
+ { // go through all OUT buffers for alternate setting change
+ altSeq = FindNextAlternateSetting();
+ }
+
+ if((iNewAltSetting == iAlternateSetting) && (!inEndpointSet))
+ {
+ return KErrNotReady;
+ }
+
+ // Find/Set IN alternate setting
+ TInt ret = StartNextInAlternateSetting();
+ SUsbcScAlternateSetting* altrec = ((SUsbcScAlternateSetting*) (&ret));
+
+ if (altrec->iSequence==iAltSettingSeq+1)
+ {
+ if (altrec->iSetting!=iNewAltSetting)
+ return KErrGeneral;
+ iInAltSetting=iNewAltSetting;
+ }
+ else
+ {
+ if (inEndpointSet)
+ {
+ if ((altSeq == iAltSettingSeq) || (iAltSettingSeq == altrec->iSequence))
+ {
+ return KErrNotReady;
+ }
+ else if (altSeq != altrec->iSequence)
+ {
+ iInAltSetting=KErrEof;
+ }
+ }
+ iInAltSetting=KErrEof;
+ }
+
+ iAlternateSetting = iNewAltSetting;
+ iAltSettingSeq += 1;
+
+ return iAlternateSetting;
+ }
+
+
+EXPORT_C TInt RDevUsbcScClient::GetDataTransferChunk(RChunk* & aChunk)
+ {
+ aChunk = &iSharedChunk;
+ return KErrNone;
+ }
+
+// Constructor
+
+EXPORT_C TEndpointBuffer::TEndpointBuffer()
+ :iInState(ENotValid),
+ iOutState(ENotValid),
+ iEndpointNumber(-1),
+ iBufferNum(-1),
+ iBufferStartAddr(0),
+ iSize(0)
+ {
+ }
+
+// Internal, called by RDevUsbcScClient::OpenEndpoint.
+void TEndpointBuffer::Construct(RDevUsbcScClient* aClient, TUint8* aBaseAddr, const TUsbcScHdrEndpointRecord* aEpType , TInt aEndpointNumber,SUsbcScBufferHeader* aEndpointHdr)
+ {
+ iClient = aClient;
+ iBaseAddr = (TUint) aBaseAddr;
+ iInState = (((aEpType->Direction())&KUsbScHdrEpDirectionIn) ? EValid : ENotValid);
+ iOutState = (((aEpType->Direction())&KUsbScHdrEpDirectionOut) ? EValid : ENotValid);
+ iBufferNum = (aEpType->iBufferNo==(KUsbcScEndpointZero&0xFF))?KUsbcScEndpointZero:aEpType->iBufferNo;
+ iEndpointNumber = aEndpointNumber;
+
+ iEndpointHdr = aEndpointHdr;
+ };
+
+EXPORT_C TInt TEndpointBuffer::GetInBufferRange(TAny*& aStart, TUint& aSize)
+ {
+ if ((iInState))
+ {
+ return iInState;
+ }
+ aStart= iBufferStartAddr;
+ aSize= iSize;
+ return KErrNone;
+ };
+
+EXPORT_C TInt TEndpointBuffer::GetInBufferRange(TUint& aStart, TUint& aSize)
+ {
+ if ((iInState))
+ return iInState;
+ aStart= (TUint) iBufferStartAddr - iBaseAddr;
+ aSize= iSize;
+ return KErrNone;
+ }
+
+
+EXPORT_C TInt TEndpointBuffer::GetBuffer(TAny*& aBuffer,TUint& aSize,TBool& aZLP,TRequestStatus& aStatus,TUint aLength)
+ {
+ if (iOutState)
+ return iOutState;
+
+ TUsbcScTransferHeader* currentTransfer;
+ TInt r;
+ do // until we have a transfer with data.
+ {
+ iEndpointHdr->iTail = iEndpointHdr->iBilTail;
+ if(iEndpointHdr->iBilTail == iEndpointHdr->iHead) //If no new data, create request
+ {
+ r = iClient->ReadDataNotify(iBufferNum,aStatus);
+ if (r!=KErrCompletion) // Data could arrive since we checked.
+ return r;
+ }
+ currentTransfer = (TUsbcScTransferHeader*) (iBaseAddr + iEndpointHdr->iBilTail);
+
+ iEndpointHdr->iBilTail = currentTransfer->iNext;
+ aZLP = (currentTransfer->iFlags & KUsbcScShortPacket)!=EFalse;
+
+ if(currentTransfer->iAltSettingSeq != (iClient->iAltSettingSeq)) // if alternate setting has changed
+ {
+ if (currentTransfer->iAltSettingSeq == (iClient->iAltSettingSeq+1)) //Note- KIS ATM, if multiple alternate setting changes happen
+ iClient->iNewAltSetting = currentTransfer->iAltSetting; //before StartNextOutAlternateSetting is called,
+ //this variable will reflect the latest requested AlternateSetting
+
+
+ if (iEndpointNumber != KEp0Number)
+ {
+// iOutState = EEOF;
+ return KErrEof;
+ }
+ else if ((currentTransfer->iBytes==0) && (!aZLP))
+ {
+ return KErrAlternateSettingChanged;
+ }
+ }
+
+ }
+ while ((currentTransfer->iBytes==0) && (!aZLP)); // ignore empty transfers
+
+ aBuffer = currentTransfer->iData.i;
+ aSize = currentTransfer->iBytes;
+ return (currentTransfer->iFlags & KUsbcScStateChange)?KStateChange:KErrCompletion;
+ }
+
+EXPORT_C TInt TEndpointBuffer::TakeBuffer(TAny*& aBuffer,TUint& aSize,TBool& aZLP,TRequestStatus& aStatus,TUint aLength)
+ {
+ if (iOutState)
+ return iOutState;
+
+ TUsbcScTransferHeader* currentTransfer;
+ TInt r;
+ do // until we have a transfer with data.
+ {
+ if(iEndpointHdr->iBilTail == iEndpointHdr->iHead) //If no new data, create request
+ {
+ r = iClient->ReadDataNotify(iBufferNum,aStatus);
+ if (r!=KErrCompletion) // Data could arrive since we checked.
+ {
+ return r;
+ }
+ }
+
+ currentTransfer = (TUsbcScTransferHeader*) (iBaseAddr + iEndpointHdr->iBilTail);
+ iEndpointHdr->iBilTail = currentTransfer->iNext;
+ aZLP = (currentTransfer->iFlags & KUsbcScShortPacket)!=EFalse; // True if short packet else false
+
+ if(currentTransfer->iAltSettingSeq != (iClient->iAltSettingSeq)) // if alternate setting has changed
+ {
+ if (currentTransfer->iAltSettingSeq == (iClient->iAltSettingSeq+1)) //Note- KIS ATM, if multiple alternate setting changes happen
+ iClient->iNewAltSetting = currentTransfer->iAltSetting; //before StartNextOutAlternateSetting is called,
+ //this variable will reflect the latest requested AlternateSetting
+ Expire(currentTransfer->iData.i);
+ if (iEndpointNumber != KEp0Number)
+ {
+// iOutState = EEOF;
+ return KErrEof;
+ }
+ else if ((currentTransfer->iBytes==0) && (!aZLP))
+ {
+ return KErrAlternateSettingChanged;
+ }
+
+ }
+
+ if ((currentTransfer->iBytes==0) && (!aZLP)) // here , if empty transfer with alt setting information, Call expire
+ {
+ Expire(currentTransfer->iData.i);
+ }
+ }
+ while ((currentTransfer->iBytes==0) && (!aZLP)); // ignore empty transfers
+
+ aBuffer = currentTransfer->iData.i;
+ aSize = currentTransfer->iBytes;
+ return (currentTransfer->iFlags & KUsbcScStateChange)?KStateChange:KErrCompletion;
+ }
+
+EXPORT_C TInt TEndpointBuffer::Expire()
+ {
+ if (!(iOutState != ENotValid))
+ return iOutState;
+
+ if (iEndpointHdr->iTail != iEndpointHdr->iBilTail)
+ {
+ TUsbcScTransferHeader* currentTransfer = (TUsbcScTransferHeader*) (iBaseAddr + iEndpointHdr->iTail);
+ iEndpointHdr->iTail = currentTransfer->iNext;
+ }
+ return KErrNone;
+ }
+
+EXPORT_C TInt TEndpointBuffer::Expire(TAny* aAddress)
+ {
+ if (!(iOutState != ENotValid))
+ return iOutState;
+
+ TUint headerSize = sizeof(TUsbcScTransferHeader)-4; // TransferHeader includes 4 bytes of data.
+ TInt transferToExpire = ((TUint) aAddress - headerSize);
+ TInt offsetToExpire = transferToExpire - iBaseAddr;
+
+ TInt currentTail = iEndpointHdr->iTail;
+
+ TInt prevTail = NULL;
+ TBool found = EFalse;
+ while (currentTail != iEndpointHdr->iBilTail)
+ {
+ TUsbcScTransferHeader* currentTransfer = (TUsbcScTransferHeader*) (iBaseAddr + currentTail);
+ if (currentTail == offsetToExpire) // found which to expire
+ {
+ found = ETrue;
+ // This offset is to be expired
+ if (prevTail == NULL)
+ {
+ // The offset is at the list head
+ iEndpointHdr->iTail = currentTransfer->iNext;
+ }
+ else
+ {
+ // The offset is NOT at the list head
+ // This leaves a GAP in the buffer which will not be filled unless the 'transfers' before 'currentTail' are expired
+ currentTail = currentTransfer->iNext;
+ TUsbcScTransferHeader* prevTransfer = (TUsbcScTransferHeader*) (iBaseAddr + prevTail);
+ prevTransfer->iNext = currentTail;
+ }
+ break;
+ }
+ prevTail = currentTail;
+ currentTail = currentTransfer->iNext;
+ }
+ return found ? KErrNone : KErrNotFound;
+ }
+
+
+EXPORT_C TInt TEndpointBuffer::WriteBuffer(TAny* aBuffer,TUint aSize,TBool aZLP,TRequestStatus& aStatus)
+ {
+ if (iInState)
+ return iInState;
+
+ iClient->WriteData(iBufferNum, ((TUint)aBuffer - (TUint)iBaseAddr),aSize,aZLP,aStatus);
+ return KErrNone;
+ }
+
+
+EXPORT_C TInt TEndpointBuffer::WriteBuffer(TUint aOffset,TUint aSize,TBool aZLP,TRequestStatus& aStatus)
+ {
+ if (iInState)
+ return iInState;
+
+ iClient->WriteData(iBufferNum,aOffset,aSize,aZLP,aStatus);
+ return KErrNone;
+ }
+
+
+/**
+Closes the endpoint buffer
+@return KErrNone if close is successfull
+*/
+EXPORT_C TInt TEndpointBuffer::Close()
+ {
+ if ((iInState == ENotValid) && (iOutState == ENotValid))
+ return KErrNotFound;
+ if (iOutState != ENotValid)
+ {
+ TUsbcScTransferHeader* currentTransfer = (TUsbcScTransferHeader*) (iBaseAddr + iEndpointHdr->iTail);
+ //Incase of AlternateSetting changes and using TEndpointBuffer::GetBuffer, iTail is always one 'transfer' behind iBilTail
+ //Incase of AlternateSetting changes and using TEndpointBuffer::TakeBuffer, this shuold force the user to update iTail & only then closes the endpoint buffer
+ if (((TInt) currentTransfer->iNext != iEndpointHdr->iBilTail) && (iEndpointHdr->iTail != iEndpointHdr->iBilTail))
+ return KErrNotReady;
+ }
+ iClient->iEndpointStatus &= ~(1 << iEndpointNumber); //reset the bit corresponding to endpoint
+ iInState = ENotValid;
+ iOutState = ENotValid;
+ return KErrNone;
+ }
+
+
+
+EXPORT_C TUsbcScChunkHeader::TUsbcScChunkHeader(RChunk aChunk)
+ {
+ iChunk = aChunk;
+ iBuffers = (TUsbcScChunkBuffersHeader*) (aChunk.Base()+((TUsbcScChunkHdrOffs*)iChunk.Base())->iBuffers);
+ iAltSettings = (TUsbcScChunkAltSettingHeader*) (aChunk.Base()+((TUsbcScChunkHdrOffs*)iChunk.Base())->iAltSettings);
+ }
+
+EXPORT_C TInt TUsbcScChunkHeader::GetNumberOfEndpoints(TInt aAltSetting)
+ {
+ if ((aAltSetting<0) || (aAltSetting>=iAltSettings->iNumOfAltSettings))
+ return KErrArgument;
+ return *((TInt*) (iAltSettings->iAltTableOffset[aAltSetting] + (TInt) iChunk.Base()));
+ }
+
+
+EXPORT_C TUsbcScBufferRecord* TUsbcScChunkHeader::GetBuffer(TInt aAltSetting, TInt aEndpoint, TUsbcScHdrEndpointRecord*& aEndpointInf)
+ {
+ if ((aAltSetting<0) || (aAltSetting>=iAltSettings->iNumOfAltSettings))
+ return NULL;
+ TInt8* iEndpoint = (TInt8*) (iAltSettings->iAltTableOffset[aAltSetting] + (TInt) iChunk.Base());
+ if ((aEndpoint<=0) || (aEndpoint>*iEndpoint))
+ return NULL;
+ aEndpointInf = (TUsbcScHdrEndpointRecord*) &(iEndpoint[aEndpoint*iAltSettings->iEpRecordSize]);
+ return iBuffers->Buffers(aEndpointInf->iBufferNo);
+ }
+
+
+/* Debug functions */
+
+EXPORT_C void TEndpointBuffer::Dump()
+ {
+ RDebug::Printf("TEndpointBuffer::Dump iBufferStart: 0x%x, iSize: 0x%x, iEndpointNumber: 0x%x, iBufferNum: %d, iInState: 0x%x iOutState: 0x%x\n",
+ iBufferStartAddr,iSize,iEndpointNumber,iBufferNum,iInState,iOutState);
+ }
+