bluetooth/btcomm/src/reader.cpp
changeset 0 29b1cd4cb562
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2005-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 "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 // reader.cpp - all the active reader code
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <cs_port.h>
       
    19 #include "btcomm.h"
       
    20 #include "btcommactive.h"
       
    21 #include "btcommutil.h"
       
    22 
       
    23 CBTPortReader *CBTPortReader::NewL(CBTPortProxy *aParent)
       
    24 /**
       
    25 	Create new CBTPortReader.
       
    26 	This function creates a new CBTPortReader active object.
       
    27 **/
       
    28 	{
       
    29 	CBTPortReader *cc;
       
    30 	cc=new (ELeave) CBTPortReader();
       
    31 	CleanupStack::PushL(cc);
       
    32 	cc->InitL(aParent);
       
    33 	CleanupStack::Pop();
       
    34 	CActiveScheduler::Add(cc);
       
    35 	return cc;
       
    36 	}
       
    37 
       
    38 void CBTPortReader::InitL(CBTPortProxy *aParent)
       
    39 /**
       
    40 	CBTPortReader InitL.
       
    41 	This function sets up the local read buffer
       
    42 	that is the first port of call for data read
       
    43 	from the socket.  The size of the local read 
       
    44 	buffer should be the max size available for
       
    45 	socket datagrams.
       
    46 **/
       
    47 	{
       
    48 	iPortProxy=aParent;
       
    49 	iLocalReadBuffer=HBufC8::NewMaxL(KBTCOMMRecvBufferLength);
       
    50 	iLocalReadBufferPtr.Set(iLocalReadBuffer->Des());
       
    51 	}
       
    52 
       
    53 CBTPortReader::~CBTPortReader()
       
    54 /**
       
    55 	CBTPortReader destructor.	
       
    56 **/
       
    57 	{
       
    58 	delete iLocalReadBuffer;
       
    59 	Cancel();
       
    60 	}
       
    61 
       
    62 void CBTPortReader::RunL()
       
    63 /**
       
    64 	CBTPortReader RunL.
       
    65 	Active status cleared.  Put the read data into the circular
       
    66 	buffer.  After that we can call the DoReadCompleted 
       
    67 	function on the corresponding port proxy object.
       
    68 **/
       
    69 	{
       
    70 	CBTPortBuffer& circBuf=*(iPortProxy->iCircularReadBuf);
       
    71 
       
    72 	TInt ret=iStatus.Int();
       
    73 	if (ret==KErrNone)
       
    74 		{
       
    75 			TUint8 *ptr=CONST_CAST(TUint8*,iLocalReadBufferPtr.Ptr());
       
    76 			TInt receivedBytes=iLocalReadBufferPtr.Length();
       
    77 
       
    78 			// add newly arrived data in the circular buffer
       
    79 #ifdef _DEBUG
       
    80 			TInt consumed=
       
    81 #endif
       
    82 				circBuf.Add(ptr,receivedBytes);
       
    83 			
       
    84 			__ASSERT_DEBUG(consumed==receivedBytes,BTCommUtil:: \
       
    85 				Panic(EBTCommPortReaderPotentialLossOfIncomingData));
       
    86 		}
       
    87 
       
    88 	iPortProxy->DoReadCompleted(ret);
       
    89 	}
       
    90 
       
    91 void CBTPortReader::QueueRead()
       
    92 /**
       
    93 	CBTPortReader QueueRead.
       
    94 	This function is invoked to queue a read on the socket.
       
    95 	We just keep queueing reads on the socket here with the 
       
    96 	resulting data being fed into the circular read buffer.
       
    97 **/
       
    98 	{
       
    99 	if (IsActive())
       
   100 		{
       
   101 		//__DEBUGGER(); //FIXME
       
   102 		return;
       
   103 		}
       
   104 	else
       
   105 		{	
       
   106 		// queue read to socket
       
   107 		iLocalReadBufferPtr.SetLength(0);
       
   108 		iPortProxy->iSocket.RecvOneOrMore(iLocalReadBufferPtr,0,iStatus,iPlen);
       
   109 		SetActive();
       
   110 		}
       
   111 	}
       
   112 
       
   113 void CBTPortReader::StartReading()
       
   114 	{
       
   115 	iKeepReading=ETrue;
       
   116 	QueueRead();
       
   117 	}
       
   118 
       
   119 void CBTPortReader::StopReading()
       
   120 	{
       
   121 	iKeepReading=EFalse;
       
   122 	}
       
   123 
       
   124 TBool CBTPortReader::IsReading()
       
   125 	{ 
       
   126 	return iKeepReading;
       
   127 	}
       
   128 
       
   129 void CBTPortReader::DoCancel()
       
   130 /**
       
   131 	CBTPortReader DoCancel.
       
   132 **/
       
   133 	{ 
       
   134 	if ( iPortProxy->iSocket.SubSessionHandle())
       
   135 		{
       
   136 		iPortProxy->iSocket.CancelRead();
       
   137 		}
       
   138 	}
       
   139 
       
   140 CBTPortReader::CBTPortReader() 
       
   141 	: CActive (EPriorityHigh), 
       
   142 	  iLocalReadBufferPtr(NULL,0,0)
       
   143 	{
       
   144 	}
       
   145 
       
   146 //********************* READ CIRCULAR BUFFER CODE **********************
       
   147 
       
   148 CBTPortBuffer *CBTPortBuffer::NewL(CBTPortProxy* aParent,TInt aBufSize)
       
   149 	{
       
   150 	CBTPortBuffer *buf;
       
   151 	buf=new (ELeave) CBTPortBuffer(aBufSize);
       
   152 	CleanupStack::PushL(buf);
       
   153 	buf->ConstructL(aParent);
       
   154 	CleanupStack::Pop();
       
   155 	return buf;
       
   156 	}
       
   157 
       
   158 void CBTPortBuffer::ConstructL(CBTPortProxy* aParent)
       
   159 /**
       
   160 	Sets up the circular buffer.
       
   161 **/
       
   162 	{
       
   163 	iPortProxy=aParent;
       
   164 	SetLengthL(iCircBufSize);
       
   165 	}
       
   166 
       
   167 CBTPortBuffer::CBTPortBuffer(TInt aBufSize) 
       
   168 	: CCirBufBase(sizeof(TUint8)), 
       
   169 	  iCircBufSize(aBufSize)
       
   170 	{
       
   171 	iCircBufSize=aBufSize;
       
   172 	}
       
   173 
       
   174 CBTPortBuffer::~CBTPortBuffer()
       
   175 	{
       
   176 	}
       
   177 
       
   178 TInt CBTPortBuffer::Add(const TUint8* aPtr,TInt aCount)
       
   179 	{
       
   180 	return DoAdd(aPtr,aCount);
       
   181 	}
       
   182 
       
   183 TInt CBTPortBuffer::Remove(TUint8* aPtr,TInt aCount)
       
   184 	{
       
   185 	return DoRemove(aPtr,aCount);
       
   186 	}
       
   187 
       
   188 TInt CBTPortBuffer::ScanForTerminator(TReadTerminator& aTerminator)
       
   189 /**
       
   190 	This function returns the number of bytes to be read of the circ buffer or KErrNotFound.
       
   191 	If the terminator sequence was not found then KErrNotFound is returned to 
       
   192 	indicate this, the  returned number of bytes does include the terminator 
       
   193 	sequence held in aTerminator.
       
   194 */
       
   195 	{
       
   196 	// go through the circbuf trying to find a terminator char.
       
   197 	TInt byteCount=1;
       
   198 	TInt charsFound=KErrNotFound; //ret val from the sequence scan
       
   199 	
       
   200 	TUint8* ptr=iTail; //somehow inefficient for now
       
   201 	TText8 nextChar;
       
   202 
       
   203 	// init scanning
       
   204 	aTerminator.iNextCharToFindIdx=0; //point to the first char to be scanned
       
   205 
       
   206 	FOREVER
       
   207 		{	
       
   208 		if(ptr>=iPtrE) 
       
   209 			{// roll over
       
   210 			ptr=iPtr;
       
   211 			}
       
   212 		
       
   213 		nextChar=*ptr;
       
   214 		
       
   215 		charsFound=ScanForTerminatorSequence(aTerminator,nextChar);
       
   216 		if(charsFound>KErrNone)
       
   217 			{// charsFound will only be positive once			
       
   218 			__ASSERT_DEBUG(charsFound==aTerminator.iTerminatorCount, \
       
   219 		BTCommUtil::Panic(EBTCommPortBufferTerminatorCharNoOtherThanExpected));
       
   220 			
       
   221 			break;
       
   222 			}
       
   223 		ptr++; // go for the next one
       
   224 		if(byteCount==iCount)
       
   225 			{
       
   226 			break; //we scanned the whole buf
       
   227 			}
       
   228 		byteCount++; // record one more char that will definately be searched
       
   229 		}
       
   230 	
       
   231 	 // either returns the no of bytes read or KErrNotFound
       
   232 	if(charsFound>=KErrNone)
       
   233 		{
       
   234 		__ASSERT_DEBUG(byteCount<=iCount,BTCommUtil::Panic(EBTCommPortBufferTerminatedCharsFoundBogus));
       
   235 		return byteCount;
       
   236 		}
       
   237 	return KErrNotFound;
       
   238 	}
       
   239 
       
   240 
       
   241 TInt CBTPortBuffer::ScanForTerminatorSequence(TReadTerminator& aTerminator,
       
   242 											  TText8 aChar)
       
   243 /**
       
   244 	Will return the number of terminator chars found or KErrNotFound.
       
   245 	The invariant is that the number of chars returned should be equal to
       
   246 	the TReadTerminator::iTerminatorCount.
       
   247 	The control and drive of the 'find the terminator sequence' state machine
       
   248 	is kept in this method.
       
   249 
       
   250 	To drive this state machine, a client must keep feeding it with aChar until
       
   251 	it returns a positive int or the client's buffer has been exhausted.
       
   252 */
       
   253 	{
       
   254 	//check for the expected character
       
   255 	if(aChar==aTerminator.iTerminatorChars[aTerminator.iNextCharToFindIdx])
       
   256 		{// the expected character was found
       
   257 		// check to see if we found the whole sequence
       
   258 		if(aTerminator.iNextCharToFindIdx==(aTerminator.iTerminatorCount-1))
       
   259 			{// yes this was the last expected char in the sequence
       
   260 			TInt ret=aTerminator.iNextCharToFindIdx; 
       
   261 			aTerminator.iNextCharToFindIdx=0; //set it back to the first char in the seq
       
   262 			return ret+1; // found so many, return with success
       
   263 			}
       
   264 		// we didn't but still we're doing ok, so prepare for the next one
       
   265 		aTerminator.iNextCharToFindIdx++;
       
   266 		return KErrNotFound; //yet
       
   267 		}
       
   268 
       
   269 	// the current char wasn't in the terminator sequence or it was 
       
   270 	// in an irrelevant position so reset the state machine in order to start again
       
   271 	aTerminator.iNextCharToFindIdx=0;		
       
   272 	return KErrNotFound; 
       
   273 	}