os/kernelhwsrv/kernel/eka/drivers/usbcsc/usbcsc_bil.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32\drivers\usbcsc\usbcsc_bil.cpp
    15 // 
    16 //
    17 
    18 #include <e32std.h>
    19 #include <e32std_private.h>
    20 #include <d32usbcsc.h>
    21 #include <e32debug.h>
    22 
    23 /** @file usbcsc_bil.cpp
    24 
    25 	Buffer Interface Layer for USB Client Device driver stack, using shared chunks.
    26 
    27 	@internalTechnology
    28 */
    29 
    30 EXPORT_C TInt RDevUsbcScClient::FinalizeInterface()
    31 	{
    32 	TInt errorOrhandle = DoControl(EControlRealizeInterface); //returns a error value or chunk handle
    33 	TInt r = iSharedChunk.SetReturnedHandle(errorOrhandle);
    34 	iEndpointStatus = 0x00; //all endpoints are closed at the moment
    35 	iAlternateSetting = 0;
    36 	iNewAltSetting = 0;
    37 	iAltSettingSeq = 0;
    38 	return r;
    39 	}
    40 
    41 
    42 EXPORT_C TInt RDevUsbcScClient::FinalizeInterface(RChunk*& aChunk)
    43 	{
    44 	TInt errorOrhandle = DoControl(EControlRealizeInterface);
    45 	iSharedChunk.SetReturnedHandle(errorOrhandle);
    46 	iEndpointStatus = 0x00; //all endpoints are closed at the moment
    47 	iAlternateSetting = 0;
    48 	return aChunk->SetReturnedHandle(errorOrhandle);
    49 	}
    50 
    51 
    52 EXPORT_C TInt RDevUsbcScClient::OpenEndpoint(TEndpointBuffer& aEpB, TInt aEpI)
    53 	{
    54 	TUsbcScHdrEndpointRecord* endpointInf = NULL;
    55 	TBuf8<KUsbDescSize_Endpoint> descriptor;
    56 	TUsbcScChunkHeader chunkHeader(iSharedChunk);
    57 	//Do some validity checks
    58 	if((aEpB.iInState != TEndpointBuffer::ENotValid) && (aEpB.iOutState != TEndpointBuffer::ENotValid))
    59 		return KErrArgument;
    60 
    61 	TInt nEndpoints = chunkHeader.GetNumberOfEndpoints(iAlternateSetting);	
    62 	if ((aEpI < KEp0Number) && (aEpI > nEndpoints)) // Check endpoint number range 
    63 		return KErrNotFound;
    64 
    65 	if(iEndpointStatus & (1 << aEpI)) // Check that endpoint isn't already opene
    66 		return KErrInUse;
    67 
    68 	if(aEpI == KEp0Number) //endpoint 0
    69 		{
    70 		TUsbcScHdrEndpointRecord ep0=  TUsbcScHdrEndpointRecord(KUsbcScEndpointZero, KUsbScHdrEpDirectionBiDir | KUsbScHdrEpTypeControl);
    71 		aEpB.Construct(this,iSharedChunk.Base(), &ep0 ,aEpI, 
    72 		(SUsbcScBufferHeader*) ((TUint)iSharedChunk.Base() + (chunkHeader.iBuffers)->Ep0Out()->Offset()));
    73 
    74 		aEpB.iBufferStartAddr = (TUint8*) ((TUint)iSharedChunk.Base() + (chunkHeader.iBuffers)->Ep0In()->Offset());
    75 		aEpB.iSize = chunkHeader.iBuffers->Ep0In()->Size();
    76 		}
    77 	else  // If normal endpoint (!ep0)
    78 		{
    79 		TUsbcScBufferRecord* buf = 	chunkHeader.GetBuffer(iAlternateSetting,aEpI,endpointInf);
    80 		if (!buf)
    81 			return KErrGeneral;
    82 		// Set up endpoint members
    83 		aEpB.iBufferStartAddr = (TUint8*)  (buf->Offset() + (TUint)iSharedChunk.Base());
    84 		aEpB.iSize = buf->Size();
    85 		TInt r = GetEndpointDescriptor(iAlternateSetting, aEpI, descriptor);
    86 		if(r != KErrNone) // We need this to be able to calculate alignment
    87 			{
    88 			return r;
    89 			}
    90 
    91 		if (endpointInf->Direction()&KUsbScHdrEpDirectionIn)
    92 			{  							//in case of IN endpoints, first endpoint buffer location points to end offset
    93 			aEpB.Construct(this,iSharedChunk.Base(),endpointInf,aEpI);
    94 			if (iInAltSetting==KErrEof)
    95 			aEpB.iInState=TEndpointBuffer::EEOF;
    96 
    97 			}
    98 		else
    99 			{
   100 			SUsbcScBufferHeader *endpointHdr = (SUsbcScBufferHeader *) aEpB.iBufferStartAddr;
   101 			//In this case,SUsbcScBufferHeader points to full OUT endpoint header 
   102 			aEpB.Construct(this,iSharedChunk.Base(),endpointInf,aEpI, endpointHdr);
   103 			}
   104 		}
   105 	iEndpointStatus |= (1 << aEpI);	
   106 
   107 #ifdef _DEBUG
   108 	aEpB.Dump();
   109 	RDebug::Printf("iEndpointStatus: %x \n",iEndpointStatus);
   110 #endif
   111 	return KErrNone;
   112 	}
   113 
   114 
   115 //Internal, used by RDevUsbcScClient::StartNextOutAlternateSetting(...)
   116 //This drains any old data from an OUT buffer, and gets it ready for reading an ep.
   117 //aBufferOffset - The offset, into the chunk, that the buffer in question, may be found.
   118  
   119 TInt RDevUsbcScClient::Drain(TUint aBufferOffset)
   120 {
   121 	TUint8* base = iSharedChunk.Base();
   122 	SUsbcScBufferHeader* endpointHdr = (SUsbcScBufferHeader*) (aBufferOffset+base);
   123 	TUint localTail = endpointHdr->iBilTail;
   124 	TUsbcScTransferHeader* currentTransfer;
   125 	TUint16 next = (iAltSettingSeq+1)&0xFFFF;
   126 	TInt err=KErrNone;
   127 
   128 	while (ETrue)
   129 		{
   130 		if (localTail == (TUint) endpointHdr->iHead)
   131 			{
   132 			err = KErrNotReady;
   133 			break;
   134 			}
   135 		currentTransfer = (TUsbcScTransferHeader*) (base + localTail);
   136 
   137 		if (currentTransfer->iAltSettingSeq == next)
   138 			{
   139 			iNewAltSetting=currentTransfer->iAltSetting; // record new alt setting
   140 			break;
   141 			}
   142 		else
   143 			{
   144 			localTail = currentTransfer->iNext;
   145 			}
   146 		} // end while
   147 	endpointHdr->iBilTail = localTail;
   148 	endpointHdr->iTail = localTail;
   149 	return err;
   150 }
   151 
   152 //Internal, used by RDevUsbcScClient::StartNextOutAlternateSetting(...)
   153 //This method checks that the OUT buffer is ready for reading an ep.
   154 //aBufferOffset - The offset, into the chunk, that the buffer in question, may be found.
   155 
   156 TInt RDevUsbcScClient::Peek(TUint aBufferOffset)
   157 {
   158 	TUint8* base = iSharedChunk.Base();
   159 	SUsbcScBufferHeader* endpointHdr = (SUsbcScBufferHeader*) (aBufferOffset+base);
   160 	TUint localTail = endpointHdr->iBilTail;
   161 	TUsbcScTransferHeader* currentTransfer = (TUsbcScTransferHeader*) (base + localTail);
   162 
   163 	if ((localTail == (TUint)endpointHdr->iHead) || (currentTransfer->iAltSettingSeq != (iAltSettingSeq+1)&0xFFFF))
   164 		// if alternate setting has not changed
   165 		return KErrNotReady;
   166 	else
   167 		{
   168 		iNewAltSetting=currentTransfer->iAltSetting;
   169 		return KErrNone;
   170 		}
   171 }
   172 
   173 //Internal, used by RDevUsbcScClient::StartNextOutAlternateSetting(...)
   174 //This method is called if an alternate setting change happens from a set of ONLY IN endpoints.
   175 //Used to find the least possible alternate setting it can return to the user, stored in iNewAltSetting
   176 //Returns the sequence number of the 'latest' alternate setting it can switch to
   177 
   178 TInt RDevUsbcScClient::FindNextAlternateSetting()
   179 	{
   180 	TUsbcScChunkHeader chunkHeader(iSharedChunk);
   181 	TUsbcScHdrEndpointRecord* endpointInf = NULL;
   182 	TUint bufOff;
   183 	TInt altSet;
   184 	TInt ep;
   185 	TInt bufNum;
   186 
   187 	RArray <TInt> bufferOffset;	// Array to contain all OUT enpoint buffer offsets
   188 	// Populate array
   189 	for (altSet = 0; altSet < chunkHeader.iAltSettings->iNumOfAltSettings ; altSet++)
   190 		{
   191 		TInt numEndpoints = chunkHeader.GetNumberOfEndpoints(altSet);
   192 		for (ep =  1; ep  <= numEndpoints ; ep ++)
   193 			{
   194 			bufOff = chunkHeader.GetBuffer(altSet, ep, endpointInf)->Offset();	
   195 			if ((endpointInf->Direction() & KUsbScHdrEpDirectionOut) && (bufferOffset.Find(bufOff) == KErrNotFound))
   196 				{
   197 				bufferOffset.Append(bufOff);
   198 				}
   199 			}
   200 		}
   201 
   202 	TInt err = KErrNotFound;
   203 	TUint16 altSetSeqDelta = 0;
   204 	TUint16 currentaltSetSeqDelta = 0;
   205 	TBool noNewSettingFound = ETrue;
   206 	TInt altSetSeq = iAltSettingSeq;
   207 	TUint8* base = iSharedChunk.Base();
   208 
   209 	for (bufNum = 0; bufNum < bufferOffset.Count(); bufNum++) // Scan all OUT buffers
   210 		{	
   211 		SUsbcScBufferHeader* endpointHdr = (SUsbcScBufferHeader*) (bufferOffset[bufNum] + base);
   212 		TUint localTail = endpointHdr->iBilTail;
   213 		TUsbcScTransferHeader* currentTransfer;
   214 		TUint16 next = (iAltSettingSeq+1)&0xFFFF;
   215 		
   216 		while (ETrue)
   217 			{
   218 			if (localTail == (TUint) endpointHdr->iHead)
   219 				{
   220 				break;	// This OUT endpoint buffer has no data, proceed checking with other OUT endpoint buffers
   221 				}
   222 			currentTransfer = (TUsbcScTransferHeader*) (base + localTail);
   223 
   224 			if (currentTransfer->iAltSettingSeq != iAltSettingSeq) 
   225 				{
   226 				if (currentTransfer->iAltSettingSeq == next)
   227 					{
   228 					altSetSeq = currentTransfer->iAltSettingSeq;
   229 					iNewAltSetting = currentTransfer->iAltSetting; // record new alt setting
   230 					err = KErrNone;
   231 					break;
   232 					}
   233 
   234 				if (noNewSettingFound)
   235 					{
   236 					altSetSeqDelta = Abs(iAltSettingSeq - currentTransfer->iAltSettingSeq);
   237 					altSetSeq = currentTransfer->iAltSettingSeq;
   238 					iNewAltSetting = currentTransfer->iAltSetting; // record new alt setting
   239 					noNewSettingFound = EFalse;
   240 					}
   241 				else
   242 					{
   243 					currentaltSetSeqDelta = Abs(iAltSettingSeq - currentTransfer->iAltSettingSeq);
   244 					if (currentaltSetSeqDelta < altSetSeqDelta)
   245 						{
   246 						altSetSeqDelta = currentaltSetSeqDelta;
   247 						altSetSeq = currentTransfer->iAltSettingSeq;
   248 						iNewAltSetting = currentTransfer->iAltSetting;
   249 						}
   250 					}
   251 				break;
   252 				}
   253 			
   254 			localTail = currentTransfer->iNext;
   255 			} // end while
   256 
   257 		if (!err) // Found an alt set sequence one after iAltSettingSeq
   258 			{
   259 			break; // found 'the next' alternate setting, exit for loop
   260 			}
   261 		
   262 		}// for loop
   263 
   264 	return altSetSeq;
   265 	}
   266 
   267 EXPORT_C TInt RDevUsbcScClient::StartNextOutAlternateSetting(TBool aFlush)
   268 	{
   269 	TUsbcScChunkHeader chunkHeader(iSharedChunk);
   270 	
   271 	//if endpoints are still open, return KErrInUse 
   272 	if((iEndpointStatus&~1) != 0)
   273 		{
   274 		return KErrInUse;
   275 		}
   276 
   277 	TInt r;
   278 	TInt ep;
   279 	TInt noEp;
   280 	TUint bufOff;
   281 	TBool inEndpointSet = ETrue;
   282 	TUsbcScHdrEndpointRecord* endpointInf = NULL;
   283 
   284 	// check if alternate setting contains all IN endpoints
   285 	noEp = chunkHeader.GetNumberOfEndpoints(iAlternateSetting);
   286 
   287 	// for each used buffer. 
   288 	for (ep=1;ep<=noEp;ep++)
   289 		{
   290 		bufOff = chunkHeader.GetBuffer(iAlternateSetting,ep,endpointInf)->Offset();	
   291 	
   292 		if (endpointInf->Direction() & KUsbScHdrEpDirectionOut) 
   293 			{
   294 			inEndpointSet = EFalse;
   295 			if (aFlush)
   296 				r = Drain(bufOff); // we need to remove anythng in the way, and get it ready for reading.
   297 			else
   298 				r = Peek(bufOff); // we need to check it is ready for reading!
   299 			if (r) 
   300 				return r;
   301 			}
   302 		}
   303 
   304 
   305 	TInt altSeq = 0;
   306 	if (inEndpointSet)	// If all endpoints in the current alternate setting are IN endpoints
   307 		{	// go through all OUT buffers for alternate setting change
   308 		altSeq = FindNextAlternateSetting();
   309 		}
   310 
   311 	if((iNewAltSetting == iAlternateSetting) && (!inEndpointSet))
   312 			{
   313 			return KErrNotReady;
   314 			}
   315 
   316 	// Find/Set IN alternate setting
   317 	TInt ret = StartNextInAlternateSetting();
   318 	SUsbcScAlternateSetting* altrec = ((SUsbcScAlternateSetting*) (&ret));
   319 
   320 	if (altrec->iSequence==iAltSettingSeq+1)
   321 		{
   322 		if (altrec->iSetting!=iNewAltSetting)
   323 			return KErrGeneral;
   324 		iInAltSetting=iNewAltSetting;
   325 		}
   326 	else
   327 		{
   328 		if (inEndpointSet)
   329 			{
   330 			if ((altSeq == iAltSettingSeq) || (iAltSettingSeq == altrec->iSequence))
   331 				{
   332 				return KErrNotReady;
   333 				}
   334 			else if (altSeq != altrec->iSequence)
   335 				{
   336 				iInAltSetting=KErrEof;
   337 				}
   338 			}
   339 		iInAltSetting=KErrEof;
   340 		}
   341 
   342 	iAlternateSetting = iNewAltSetting;
   343 	iAltSettingSeq += 1;
   344 
   345 	return iAlternateSetting;
   346 	}
   347 
   348 
   349 EXPORT_C TInt RDevUsbcScClient::GetDataTransferChunk(RChunk* & aChunk)
   350 	{
   351 	aChunk = &iSharedChunk;
   352 	return KErrNone;
   353 	}
   354 
   355 // Constructor
   356 
   357 EXPORT_C TEndpointBuffer::TEndpointBuffer()
   358 		:iInState(ENotValid),
   359 		iOutState(ENotValid),
   360 		iEndpointNumber(-1),
   361 		iBufferNum(-1),
   362 		iBufferStartAddr(0),
   363 		iSize(0)
   364 	{
   365 	}
   366 
   367 // Internal, called by RDevUsbcScClient::OpenEndpoint.
   368 void TEndpointBuffer::Construct(RDevUsbcScClient* aClient, TUint8* aBaseAddr, const TUsbcScHdrEndpointRecord* aEpType , TInt aEndpointNumber,SUsbcScBufferHeader* aEndpointHdr)
   369 	{
   370 	iClient		= aClient;
   371 	iBaseAddr	= (TUint) aBaseAddr;
   372 	iInState 	= (((aEpType->Direction())&KUsbScHdrEpDirectionIn) ? EValid :  ENotValid);
   373 	iOutState	= (((aEpType->Direction())&KUsbScHdrEpDirectionOut) ? EValid :  ENotValid);
   374 	iBufferNum	= (aEpType->iBufferNo==(KUsbcScEndpointZero&0xFF))?KUsbcScEndpointZero:aEpType->iBufferNo;
   375 	iEndpointNumber = aEndpointNumber;
   376 
   377 	iEndpointHdr = aEndpointHdr;
   378 	};
   379 
   380 EXPORT_C TInt TEndpointBuffer::GetInBufferRange(TAny*& aStart, TUint& aSize)
   381 	{
   382 	if ((iInState))
   383 		{
   384 		return iInState;
   385 		}
   386 	aStart= iBufferStartAddr;
   387 	aSize= iSize;
   388 	return KErrNone;
   389 	};
   390 
   391 EXPORT_C TInt TEndpointBuffer::GetInBufferRange(TUint& aStart, TUint& aSize)
   392 	{
   393 	if ((iInState))
   394 		return iInState;
   395 	aStart=	(TUint) iBufferStartAddr - iBaseAddr;
   396 	aSize= iSize;
   397 	return KErrNone;
   398 	}
   399 
   400 
   401 EXPORT_C TInt TEndpointBuffer::GetBuffer(TAny*& aBuffer,TUint& aSize,TBool& aZLP,TRequestStatus& aStatus,TUint aLength)
   402 	{
   403 	if (iOutState)
   404 		return iOutState;
   405 
   406 	TUsbcScTransferHeader* currentTransfer;
   407 	TInt r;
   408 	do // until we have a transfer with data.
   409 		{
   410 		iEndpointHdr->iTail = iEndpointHdr->iBilTail; 
   411 		if(iEndpointHdr->iBilTail == iEndpointHdr->iHead)  //If no new data, create request
   412 			{
   413 			r = iClient->ReadDataNotify(iBufferNum,aStatus);
   414 			if (r!=KErrCompletion)  // Data could arrive since we checked.
   415 				return r;
   416 			}
   417 		currentTransfer = (TUsbcScTransferHeader*) (iBaseAddr + iEndpointHdr->iBilTail);
   418 
   419 		iEndpointHdr->iBilTail = currentTransfer->iNext;
   420 		aZLP = (currentTransfer->iFlags & KUsbcScShortPacket)!=EFalse;
   421 
   422 		if(currentTransfer->iAltSettingSeq != (iClient->iAltSettingSeq))  // if alternate setting has changed
   423 			{
   424 			if (currentTransfer->iAltSettingSeq == (iClient->iAltSettingSeq+1))	   //Note- KIS ATM, if multiple alternate setting changes happen
   425 				iClient->iNewAltSetting = currentTransfer->iAltSetting; //before StartNextOutAlternateSetting is called, 		   
   426 																	   //this variable will reflect the latest requested AlternateSetting
   427 
   428 
   429 			if (iEndpointNumber != KEp0Number)
   430 				{
   431 //				iOutState =  EEOF;	
   432 				return KErrEof;
   433 				}
   434 			else if ((currentTransfer->iBytes==0) && (!aZLP)) 
   435 				{
   436 				return KErrAlternateSettingChanged;
   437 				}
   438 			}						
   439 
   440 		}
   441 	while ((currentTransfer->iBytes==0) && (!aZLP)); // ignore empty transfers
   442 
   443 	aBuffer = currentTransfer->iData.i;
   444 	aSize = currentTransfer->iBytes;	
   445 	return (currentTransfer->iFlags & KUsbcScStateChange)?KStateChange:KErrCompletion;	
   446 	}
   447 
   448 EXPORT_C TInt TEndpointBuffer::TakeBuffer(TAny*& aBuffer,TUint& aSize,TBool& aZLP,TRequestStatus& aStatus,TUint aLength)
   449 	{
   450 	if (iOutState)
   451 		return iOutState;
   452 
   453 	TUsbcScTransferHeader* currentTransfer;
   454 	TInt r;
   455 	do // until we have a transfer with data.
   456 		{
   457 		if(iEndpointHdr->iBilTail == iEndpointHdr->iHead)  //If no new data, create request
   458 			{
   459 			r = iClient->ReadDataNotify(iBufferNum,aStatus);
   460 			if (r!=KErrCompletion)  // Data could arrive since we checked.
   461 				{
   462 				return r;
   463 				}
   464 			}
   465 
   466 		currentTransfer = (TUsbcScTransferHeader*) (iBaseAddr + iEndpointHdr->iBilTail);
   467 		iEndpointHdr->iBilTail = currentTransfer->iNext;
   468 		aZLP = (currentTransfer->iFlags & KUsbcScShortPacket)!=EFalse; // True if short packet else false 
   469 
   470 		if(currentTransfer->iAltSettingSeq != (iClient->iAltSettingSeq))  // if alternate setting has changed
   471 			{
   472 			if (currentTransfer->iAltSettingSeq == (iClient->iAltSettingSeq+1))	   //Note- KIS ATM, if multiple alternate setting changes happen
   473 				iClient->iNewAltSetting = currentTransfer->iAltSetting; //before StartNextOutAlternateSetting is called, 		   
   474 																	   //this variable will reflect the latest requested AlternateSetting
   475 			Expire(currentTransfer->iData.i);
   476 			if (iEndpointNumber != KEp0Number)
   477 				{
   478 //				iOutState = EEOF;
   479 				return KErrEof;
   480 				}
   481 			else if ((currentTransfer->iBytes==0) && (!aZLP)) 
   482 				{
   483 				return KErrAlternateSettingChanged;
   484 				}
   485 
   486 			}	
   487 
   488 		if ((currentTransfer->iBytes==0) && (!aZLP)) // here , if empty transfer with alt setting information, Call expire 
   489 			{
   490 			Expire(currentTransfer->iData.i);
   491 			}
   492 		}
   493 	while ((currentTransfer->iBytes==0) && (!aZLP)); // ignore empty transfers
   494 
   495 	aBuffer = currentTransfer->iData.i;
   496 	aSize = currentTransfer->iBytes;
   497 	return (currentTransfer->iFlags & KUsbcScStateChange)?KStateChange:KErrCompletion;	
   498 	}
   499 
   500 EXPORT_C TInt TEndpointBuffer::Expire()
   501 	{
   502 	if (!(iOutState != ENotValid))
   503 		return iOutState;
   504 
   505 	if (iEndpointHdr->iTail != iEndpointHdr->iBilTail)
   506 		{
   507 		TUsbcScTransferHeader* currentTransfer = (TUsbcScTransferHeader*) (iBaseAddr + iEndpointHdr->iTail);
   508 		iEndpointHdr->iTail = currentTransfer->iNext;
   509 		}
   510 	return KErrNone;
   511 	}
   512 
   513 EXPORT_C TInt TEndpointBuffer::Expire(TAny* aAddress)
   514 	{
   515 	if (!(iOutState != ENotValid))
   516 		return iOutState;
   517 
   518 	TUint headerSize = sizeof(TUsbcScTransferHeader)-4; // TransferHeader includes 4 bytes of data.
   519 	TInt transferToExpire = ((TUint) aAddress - headerSize);
   520 	TInt offsetToExpire = transferToExpire - iBaseAddr; 
   521 
   522 	TInt currentTail = iEndpointHdr->iTail;
   523 
   524 	TInt prevTail = NULL;
   525 	TBool found = EFalse;
   526 	while (currentTail != iEndpointHdr->iBilTail)
   527 		{
   528 		TUsbcScTransferHeader* currentTransfer = (TUsbcScTransferHeader*) (iBaseAddr + currentTail);
   529 		if (currentTail == offsetToExpire)		// found which to expire
   530 			{
   531 			found = ETrue;
   532 			// This offset is to be expired
   533 			if (prevTail == NULL)
   534 				{
   535 				// The offset is at the list head
   536 				iEndpointHdr->iTail = currentTransfer->iNext;	
   537 				}
   538 			else
   539 				{
   540 				// The offset is NOT at the list head
   541 				// This leaves a GAP in the buffer which will not be filled unless the 'transfers' before 'currentTail' are expired
   542 				currentTail = currentTransfer->iNext;
   543 				TUsbcScTransferHeader* prevTransfer = (TUsbcScTransferHeader*) (iBaseAddr + prevTail);
   544 				prevTransfer->iNext = currentTail;
   545 				}
   546 			break;
   547 			}
   548 		prevTail = currentTail;
   549 		currentTail = currentTransfer->iNext;
   550 		}
   551 	return found ? KErrNone : KErrNotFound;
   552 	}
   553 
   554 	
   555 EXPORT_C TInt TEndpointBuffer::WriteBuffer(TAny* aBuffer,TUint aSize,TBool aZLP,TRequestStatus& aStatus)
   556 	{
   557 	if (iInState)
   558 		return iInState;
   559 
   560 	iClient->WriteData(iBufferNum, ((TUint)aBuffer - (TUint)iBaseAddr),aSize,aZLP,aStatus);
   561 	return KErrNone;
   562 	}
   563 
   564 
   565 EXPORT_C TInt TEndpointBuffer::WriteBuffer(TUint aOffset,TUint aSize,TBool aZLP,TRequestStatus& aStatus)
   566 	{
   567 	if (iInState)
   568 		return iInState;
   569 
   570 	iClient->WriteData(iBufferNum,aOffset,aSize,aZLP,aStatus);
   571 	return KErrNone;
   572 	}
   573 
   574 
   575 /**
   576 Closes the endpoint buffer
   577 @return			KErrNone if close is successfull
   578 */	
   579 EXPORT_C TInt TEndpointBuffer::Close()
   580 	{
   581 	if ((iInState == ENotValid) && (iOutState == ENotValid))
   582 		return KErrNotFound;
   583 	if (iOutState != ENotValid)
   584 		{
   585 		TUsbcScTransferHeader* currentTransfer = (TUsbcScTransferHeader*) (iBaseAddr + iEndpointHdr->iTail);
   586 		//Incase of AlternateSetting changes and using TEndpointBuffer::GetBuffer, iTail is always one 'transfer' behind iBilTail
   587 		//Incase of AlternateSetting changes and using TEndpointBuffer::TakeBuffer, this shuold force the user to update iTail & only then closes the endpoint buffer
   588 		if (((TInt) currentTransfer->iNext != iEndpointHdr->iBilTail) && (iEndpointHdr->iTail != iEndpointHdr->iBilTail))
   589 			return KErrNotReady;
   590 		}
   591 	iClient->iEndpointStatus &= ~(1 << iEndpointNumber); //reset the bit corresponding to endpoint
   592 	iInState = ENotValid;
   593 	iOutState = ENotValid;
   594 	return KErrNone;
   595 	}
   596 
   597 
   598   
   599 EXPORT_C TUsbcScChunkHeader::TUsbcScChunkHeader(RChunk aChunk)
   600 	{
   601 	iChunk = aChunk;
   602 	iBuffers     = (TUsbcScChunkBuffersHeader*)    (aChunk.Base()+((TUsbcScChunkHdrOffs*)iChunk.Base())->iBuffers);
   603 	iAltSettings = (TUsbcScChunkAltSettingHeader*) (aChunk.Base()+((TUsbcScChunkHdrOffs*)iChunk.Base())->iAltSettings);
   604 	}
   605 
   606 EXPORT_C TInt TUsbcScChunkHeader::GetNumberOfEndpoints(TInt aAltSetting)
   607 	{
   608 	if ((aAltSetting<0) || (aAltSetting>=iAltSettings->iNumOfAltSettings))
   609 		return KErrArgument;
   610 	return  *((TInt*) (iAltSettings->iAltTableOffset[aAltSetting] + (TInt) iChunk.Base()));
   611 	}
   612 
   613 
   614 EXPORT_C TUsbcScBufferRecord* TUsbcScChunkHeader::GetBuffer(TInt aAltSetting, TInt aEndpoint, TUsbcScHdrEndpointRecord*& aEndpointInf)
   615 	{
   616 	if ((aAltSetting<0) || (aAltSetting>=iAltSettings->iNumOfAltSettings))
   617 		return NULL;
   618 	TInt8* iEndpoint = (TInt8*) (iAltSettings->iAltTableOffset[aAltSetting] + (TInt) iChunk.Base());
   619 	if ((aEndpoint<=0) || (aEndpoint>*iEndpoint))
   620 		return NULL;
   621 	aEndpointInf = (TUsbcScHdrEndpointRecord*) &(iEndpoint[aEndpoint*iAltSettings->iEpRecordSize]);
   622 	return iBuffers->Buffers(aEndpointInf->iBufferNo);
   623 	}
   624 
   625 
   626 /* Debug functions */
   627 
   628 EXPORT_C void TEndpointBuffer::Dump()
   629 	{
   630 	RDebug::Printf("TEndpointBuffer::Dump iBufferStart: 0x%x, iSize: 0x%x, iEndpointNumber: 0x%x, iBufferNum: %d, iInState: 0x%x iOutState: 0x%x\n",
   631 							iBufferStartAddr,iSize,iEndpointNumber,iBufferNum,iInState,iOutState);
   632 	}
   633