usbdrv/peripheral/ldd/perilddsc/appifwrapper/src/usbcsc_bil.cpp
branchRCL_3
changeset 15 f92a4f87e424
equal deleted inserted replaced
14:d3e8e7d462dd 15:f92a4f87e424
       
     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 <usb/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