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