linklayerprotocols/ethernetnif/EtherPkt/CardIo.cpp
branchRCL_3
changeset 12 e9cc36e353d4
equal deleted inserted replaced
11:db85996de7c4 12:e9cc36e353d4
       
     1 // Copyright (c) 1997-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 // 
       
    15 //
       
    16 
       
    17 /**
       
    18  @file
       
    19 */
       
    20 
       
    21 #include <nifman.h>
       
    22 #include <nifvar.h>
       
    23 #include <nifutl.h>
       
    24 #include <es_mbuf.h>
       
    25 #include "PKTDRV.H"
       
    26 #include "ETHINTER.H"
       
    27 #include "Cardctl.h"
       
    28 
       
    29 //#define __DebugCardLo__ 1
       
    30 #if defined(__DebugCardLo__)
       
    31 #include <e32svr.h>
       
    32  #define DPRINT(x) RDebug::Print x
       
    33  #pragma message ("Warning: this code contains RDebug::Print statements!  Do not submit to the mainline with __DebugCardCtl__ defined.")
       
    34 #else
       
    35  #define DPRINT(x)
       
    36 #endif
       
    37  
       
    38 #ifdef __DebugCardLo__
       
    39 // TCP packet tracing debug
       
    40 const TUint8 ETHER2_TYPE_IP_MSB = 0x08;
       
    41 const TUint8 ETHER2_TYPE_IP_LSB = 0x00;
       
    42 const TUint8 IP_TYPE_TCP        = 0x06;
       
    43 static inline TBool IsTcp(TDesC8 &aFrame)
       
    44 {
       
    45 	return (aFrame[12] == ETHER2_TYPE_IP_MSB && aFrame[13] == ETHER2_TYPE_IP_LSB && aFrame[23] == IP_TYPE_TCP);
       
    46 }
       
    47 static TInt GetTcpSeqNumber(TDesC8 &aFrame)
       
    48 	{
       
    49 	TInt seqNum = 0;
       
    50 	if (IsTcp(aFrame))
       
    51 		seqNum = aFrame[38] << 24 | aFrame[39] << 16 | aFrame[40] << 8| aFrame[41];
       
    52 	return seqNum;
       
    53 	}
       
    54 static TInt GetTcpAckNumber(TDesC8 &aFrame)
       
    55 	{
       
    56 	TInt ackNum = 0;
       
    57 	if (IsTcp(aFrame))
       
    58 		ackNum = aFrame[42] << 24 | aFrame[43] << 16 | aFrame[44] << 8| aFrame[45];
       
    59 	return ackNum;
       
    60 	}
       
    61 #endif
       
    62 
       
    63 
       
    64 /**
       
    65 Send active object class
       
    66 When CIOBuffer's are passed to SendL() the class takes ownership and is
       
    67 therefore resposible for freeing them in the RunL()
       
    68 @internalComponent
       
    69 */
       
    70 const TInt KTxQueueThreshold = 40;
       
    71 
       
    72 /**
       
    73 Constructor.
       
    74 */
       
    75 CPcCardSender::CPcCardSender() : CActive(EPriorityStandard)
       
    76 {
       
    77 	
       
    78 }
       
    79 
       
    80 /**
       
    81 Destructor.
       
    82 Could be buffers on the transmit queue, free them as this class should be sole owner.
       
    83 */
       
    84 CPcCardSender::~CPcCardSender()
       
    85 {
       
    86 	EmptyQueue();
       
    87 	Cancel();
       
    88 }
       
    89 
       
    90 /**
       
    91 Standard CActive construction.
       
    92 @param aParent Pointer to the parent CPcCardControlEngine class.
       
    93 @return A pointer to CPcCardSender object.
       
    94 */
       
    95 CPcCardSender* CPcCardSender::NewL(CPcCardControlEngine* aParent)
       
    96 {
       
    97 	CPcCardSender *sd=new (ELeave) CPcCardSender;
       
    98 	CleanupStack::PushL(sd);
       
    99 	sd->InitL(aParent);
       
   100 	CActiveScheduler::Add(sd);
       
   101 	CleanupStack::Pop();
       
   102 	return sd;
       
   103 }
       
   104 
       
   105 /**
       
   106 Add the newly created object to an object container.
       
   107 @param aParent Pointer to the parent CPcCardControlEngine class.
       
   108 */
       
   109 void CPcCardSender::InitL(CPcCardControlEngine* aParent)
       
   110 {
       
   111 	iParent=aParent;
       
   112 	iTxQueue.SetOffset(CIOBuffer::LinkOffset());
       
   113 	iQueueLength = 0;
       
   114 	iStopSending = EFalse;
       
   115 }
       
   116 
       
   117 /** 
       
   118 Protocol inspects return
       
   119 It blocks sending if it receives a return <= 0
       
   120 This value should be propogated up through the stack
       
   121 @internalComponent
       
   122 */
       
   123 const TInt KStopSending		= 0;
       
   124 
       
   125 /**
       
   126 Protocol inspects return to indicate Keep sending the data.
       
   127 @internalComponent
       
   128 */
       
   129 const TInt KContinueSending	= 1;
       
   130 
       
   131 /**
       
   132 Writes the data to buffer.
       
   133 
       
   134 @param aBuffer The data to be send.
       
   135 @return 0 Tells the higher layer to stop sending the data.
       
   136 		1 Tells higher layer that it can continue sending more data.
       
   137 */
       
   138 TInt CPcCardSender::Send(CIOBuffer *aBuffer)
       
   139 {
       
   140 	DPRINT((_L(">pkt tx: requested write - tcp seq=%u ack=%u iQueueLength=%d threadId=%d"), 
       
   141 			GetTcpSeqNumber(aBuffer->Ptr()), GetTcpAckNumber(aBuffer->Ptr()), iQueueLength, (TInt)RThread().Id() ));
       
   142 	
       
   143 	// Check to see if we need to start transmission
       
   144 	// Pseudo interrupt queue
       
   145 	TBool startTx = iTxQueue.IsEmpty();
       
   146 
       
   147 	iTxQueue.AddLast(*aBuffer);
       
   148 	iQueueLength++;
       
   149 	if(startTx)
       
   150 		{
       
   151 		// Transmitter was idle start next transmit
       
   152 		DPRINT((_L(">pkt tx: PRE write - tcp seq=%u ack=%u iQueueLength=%d threadId=%d"), 
       
   153 				GetTcpSeqNumber(aBuffer->Ptr()), GetTcpAckNumber(aBuffer->Ptr()), iQueueLength, (TInt)RThread().Id() ));
       
   154 		iParent->iCard.Write(iStatus,aBuffer->Ptr());
       
   155 		SetActive();
       
   156 		//DPRINT((_L(">pkt tx: PST write - tcp seq=%u ack=%u iQueueLength=%d threadId=%d"), GetTcpSeqNumber(aBuffer->Ptr()), GetTcpAckNumber(aBuffer->Ptr()), iQueueLength, RThread().Id() ));
       
   157 		}
       
   158 	else
       
   159 	{
       
   160 		DPRINT((_L(">pkt tx: PST skipped write queuing (leave for runl) - tcp seq=%u ack=%u iQueueLength=%d threadId=%d"), 
       
   161 				GetTcpSeqNumber(aBuffer->Ptr()), GetTcpAckNumber(aBuffer->Ptr()), iQueueLength, (TInt)RThread().Id() ));
       
   162 	}	
       
   163 	// The stack could saturate us with data
       
   164 	// Tell the stack to send no more
       
   165 	// We will unblock the stack when the queue size drops below
       
   166 	// the the threshold
       
   167 	if(iQueueLength >= KTxQueueThreshold)
       
   168 		{
       
   169 		iStopSending = ETrue;
       
   170 		return KStopSending;
       
   171 		}
       
   172 	else
       
   173 		{
       
   174 		return KContinueSending;
       
   175 		}
       
   176 }
       
   177 
       
   178 /**
       
   179 Free all queued buffers. Should be safe as this class owns them
       
   180 */
       
   181 void CPcCardSender::EmptyQueue()
       
   182 {
       
   183 	DPRINT((_L(">pkt tx: emptying driver...")));	
       
   184 	while(!iTxQueue.IsEmpty())
       
   185 		{
       
   186 		CIOBuffer* buf = iTxQueue.First();
       
   187 		iTxQueue.Remove(*buf);
       
   188 		delete buf;
       
   189 		}
       
   190 	iQueueLength = 0;
       
   191 	iStopSending = EFalse;
       
   192 }
       
   193 
       
   194 /**
       
   195 Write completion from the LDD. Pseudo transmit interrupt handler
       
   196 */
       
   197 void CPcCardSender::RunL()
       
   198 {
       
   199 	DPRINT((_L(">pkt tx runl: completion - tcp seq=%u ack=%u iQueueLength=%d threadId=%d"), 
       
   200 			GetTcpSeqNumber(iTxQueue.First()->Ptr()), GetTcpAckNumber(iTxQueue.First()->Ptr()), iQueueLength, (TInt)RThread().Id() ));
       
   201 	// Check for error, all we can do is free the buffers
       
   202 	if(iStatus.Int()!=KErrNone)
       
   203 		{
       
   204 		DPRINT((_L(">pkt tx runl error... emptying queue: - tcp seq=%u ack=%u iQueueLength=%d threadId=%d"), 
       
   205 				GetTcpSeqNumber(iTxQueue.First()->Ptr()), GetTcpAckNumber(iTxQueue.First()->Ptr()), iQueueLength, (TInt)RThread().Id() ));
       
   206 		EmptyQueue();
       
   207 		return;
       
   208 		}
       
   209 
       
   210 	if(!iTxQueue.IsEmpty())
       
   211 		{
       
   212 		// Head of the queue has been transmitted
       
   213 		// Remove it and free it
       
   214 		CIOBuffer* buf = iTxQueue.First();
       
   215 		iTxQueue.Remove(*buf);
       
   216 		iQueueLength--;
       
   217 		delete buf;
       
   218 		
       
   219 
       
   220 		// Check to see if there are still buffers queued.
       
   221 		// Start next transmit if there are
       
   222 		TBool startTx;
       
   223 		(iTxQueue.IsEmpty()) ? (startTx = EFalse) : (startTx = ETrue);
       
   224 		if(startTx)
       
   225 			{
       
   226 			buf = iTxQueue.First();
       
   227 			DPRINT((_L(">pkt tx runl PRE write...: - tcp seq=%u ack=%u iQueueLength=%d threadId=%d"), 
       
   228 					GetTcpSeqNumber(buf->Ptr()), GetTcpAckNumber(buf->Ptr()), iQueueLength, (TInt)RThread().Id() ));
       
   229 			iParent->iCard.Write(iStatus,buf->Ptr());
       
   230 			SetActive();
       
   231 			}
       
   232 		else
       
   233 		{
       
   234 			DPRINT((_L(">pkt tx runl skipped writing (queue empty)...:")));
       
   235 		}
       
   236 		// Resume sending if the protocol was previously blocked
       
   237 		if(iStopSending && iQueueLength < KTxQueueThreshold)
       
   238 			{
       
   239 			DPRINT((_L(">pkt tx runl resume sending notification...: - tcp seq=%u ack=%u iQueueLength=%d threadId=%d"), 
       
   240 					GetTcpSeqNumber(iTxQueue.First()->Ptr()), GetTcpAckNumber(iTxQueue.First()->Ptr()), iQueueLength, (TInt)RThread().Id() ));
       
   241 
       
   242 			iStopSending = EFalse;
       
   243 			iParent->ResumeSending();
       
   244 			}
       
   245 		}
       
   246 }
       
   247 
       
   248 /**
       
   249 cancellation of an outstanding request.
       
   250 */
       
   251 void CPcCardSender::DoCancel()
       
   252 {
       
   253 	iParent->iCard.WriteCancel();
       
   254 }
       
   255 
       
   256 /**
       
   257 Read active object class.
       
   258 Read kept permanently on the LDD
       
   259 Read completion is notified immediately up through the stack
       
   260 with the one receive buffer therefore no Q.
       
   261 */
       
   262 CPcCardReceiver::CPcCardReceiver() : CActive(EPriorityMore)  , iRecvBufPtr(NULL,0) 
       
   263 {
       
   264 	
       
   265 }
       
   266 
       
   267 /**
       
   268 Constructor.
       
   269 */
       
   270 CPcCardReceiver::~CPcCardReceiver()
       
   271 {
       
   272 	Cancel();
       
   273 	// One buffer only
       
   274 	delete iRecvBuffer;
       
   275 }
       
   276 
       
   277 /**
       
   278 Standard CActive construction.
       
   279 @param aParent Pointer to the parent CPcCardControlEngine class.
       
   280 @return A pointer to CPcCardReceiver object.
       
   281 */
       
   282 CPcCardReceiver* CPcCardReceiver::NewL(CPcCardControlEngine* aParent)
       
   283 {
       
   284 	CPcCardReceiver *rv=new (ELeave) CPcCardReceiver;
       
   285 	CleanupStack::PushL(rv);
       
   286 	rv->InitL(aParent);
       
   287 	CActiveScheduler::Add(rv);
       
   288 	CleanupStack::Pop();
       
   289 	return rv;
       
   290 }
       
   291 
       
   292 /**
       
   293 Allocate the one and only read buffer.
       
   294 @param aParent Pointer to the parent CPcCardControlEngine class.
       
   295 */
       
   296 void CPcCardReceiver::InitL(CPcCardControlEngine* aParent)
       
   297 {
       
   298 	iParent=aParent;
       
   299 	iRecvBufLength=KEtherBufSize;
       
   300 	iRecvBuffer=HBufC8::NewMaxL(iRecvBufLength);
       
   301 	TPtr8 temp=iRecvBuffer->Des();
       
   302 	iRecvBufPtr.Set(temp);
       
   303 }
       
   304 
       
   305 /**
       
   306 Pass the receive buffer to the Card.
       
   307 */
       
   308 void CPcCardReceiver::QueueRead()
       
   309 {
       
   310 	iRecvBufPtr.SetMax();
       
   311 	DPRINT((_L(">pkt queuing read...")));
       
   312 	iParent->iCard.Read(iStatus,iRecvBufPtr);
       
   313 	SetActive();
       
   314 }
       
   315 
       
   316 /**
       
   317 Pseudo read interrupt handler.
       
   318 */
       
   319 void CPcCardReceiver::RunL()
       
   320 {
       
   321 	if (iParent->CardOpen())
       
   322 		{
       
   323 		if (iStatus.Int()!=KErrNone)
       
   324 			{
       
   325 			DPRINT((_L(">pkt tx runl: bad status=%d tcp seq=%u ack=%u threadId=%d"), 
       
   326 					iStatus.Int(), GetTcpSeqNumber(iRecvBufPtr), GetTcpAckNumber(iRecvBufPtr), (TInt)RThread().Id() ));
       
   327 			QueueRead();
       
   328 			return;
       
   329 			}
       
   330 		// Pass the buffer up the stack
       
   331 		// and queue the next read, safe to reuse the buffer.
       
   332 		if(iRecvBufPtr.Length())
       
   333 			{
       
   334 			DPRINT((_L(">pkt rx runl: tcp seq=%u ack=%u threadId=%d"), 
       
   335 					GetTcpSeqNumber(iRecvBufPtr), GetTcpAckNumber(iRecvBufPtr), (TInt)RThread().Id() ));
       
   336 			iParent->ProcessReceivedPacket(iRecvBufPtr);
       
   337 			}
       
   338 		QueueRead();
       
   339 		}
       
   340 	else
       
   341 	{
       
   342 		DPRINT((_L(">CPcCardReceiver::RunL Card NOT open")));
       
   343 	}
       
   344 }
       
   345 
       
   346 /**
       
   347 Cancellation of an outstanding request.
       
   348 */
       
   349 void CPcCardReceiver::DoCancel()
       
   350 {
       
   351 	iParent->iCard.ReadCancel();
       
   352 }
       
   353 
       
   354 /**
       
   355 Constructor.
       
   356 */
       
   357 CPcCardEventHandler::CPcCardEventHandler() : CActive(EPriorityStandard) 
       
   358 {
       
   359 	
       
   360 }
       
   361 
       
   362 /**
       
   363 Destructor.
       
   364 */
       
   365 CPcCardEventHandler::~CPcCardEventHandler()
       
   366 {
       
   367 	Cancel();
       
   368 }
       
   369 
       
   370 /**
       
   371 Allocate the one and only read buffer.
       
   372 @param aParent Pointer to the parent CPcCardControlEngine class.
       
   373 */
       
   374 void CPcCardEventHandler::InitL(CPcCardControlEngine* aParent)
       
   375 {
       
   376 	iParent = aParent;
       
   377 }
       
   378 
       
   379 /**
       
   380 Standard CActive construction
       
   381 @param aParent Pointer to the parent CPcCardControlEngine class.
       
   382 @return A pointer to the CPcCardEventHandler object.
       
   383 */
       
   384 CPcCardEventHandler* CPcCardEventHandler::NewL(CPcCardControlEngine* aParent)
       
   385 {
       
   386 	CPcCardEventHandler *p=new (ELeave) CPcCardEventHandler;
       
   387 	CleanupStack::PushL(p);
       
   388 	p->InitL(aParent);
       
   389 	CActiveScheduler::Add(p);
       
   390 	CleanupStack::Pop();
       
   391 	return p;
       
   392 }
       
   393 
       
   394 /**
       
   395 Handles an active object’s request completion event.
       
   396 */
       
   397 void CPcCardEventHandler::RunL()
       
   398 {
       
   399 	// TODO Parse code in iStatus for type of event
       
   400 }
       
   401 
       
   402 /**
       
   403 Cancellation of an outstanding request.
       
   404 */
       
   405 void CPcCardEventHandler::DoCancel()
       
   406 {
       
   407 }
       
   408 
       
   409 /**
       
   410 Gets the Event generated by the device drivers.
       
   411 */
       
   412 void CPcCardEventHandler::GetEvent()
       
   413 {
       
   414 	// Tell the device driver we want ALL Events
       
   415 	iEventBuffer.SetLength(1);
       
   416 	iEventBuffer[0] = 0xFF;
       
   417 	SetActive();
       
   418 }
       
   419 
       
   420 /**
       
   421 Constructor.
       
   422 */
       
   423 CPcCardIOCTL::CPcCardIOCTL() : CActive(EPriorityStandard) 
       
   424 {
       
   425 	
       
   426 }
       
   427 
       
   428 /**
       
   429 Destructor.
       
   430 */
       
   431 CPcCardIOCTL::~CPcCardIOCTL()
       
   432 {
       
   433 	Cancel();
       
   434 }
       
   435 
       
   436 /**
       
   437 Add the newly created object to an object container.
       
   438 @param aParent Pointer to the parent CPcCardControlEngine class.
       
   439 */
       
   440 void CPcCardIOCTL::InitL(CPcCardControlEngine* aParent)
       
   441 {
       
   442 	iParent = aParent;
       
   443 }
       
   444 
       
   445 TInt CPcCardIOCTL::Ioctl(const TUint8 aIOCTLCode)
       
   446 {
       
   447 	if(IsActive())
       
   448 		return KErrNotReady;
       
   449 	iIOCTLBuffer.SetLength(1);
       
   450 	iIOCTLBuffer[0] = aIOCTLCode;
       
   451 	iCurrentIOCTL = aIOCTLCode;
       
   452 	SetActive();
       
   453 	return KErrNone;
       
   454 }
       
   455 
       
   456 
       
   457 /**
       
   458 Standard CActive construction.
       
   459 @param aParent Pointer to the parent CPcCardControlEngine class.
       
   460 @return A pointer to CPcCardIOCTL object.
       
   461 */
       
   462 CPcCardIOCTL* CPcCardIOCTL::NewL(CPcCardControlEngine* aParent)
       
   463 {
       
   464 	CPcCardIOCTL *p=new (ELeave) CPcCardIOCTL;
       
   465 	CleanupStack::PushL(p);
       
   466 	p->InitL(aParent);
       
   467 	CActiveScheduler::Add(p);
       
   468 	CleanupStack::Pop();
       
   469 	return p;
       
   470 }
       
   471 
       
   472 /**
       
   473 Handles an active object’s request completion event.
       
   474 */
       
   475 void CPcCardIOCTL::RunL()
       
   476 {
       
   477 			{
       
   478 			iParent->iReceiver->QueueRead();
       
   479 			iParent->LinkLayerUp();
       
   480 			}
       
   481 }
       
   482 
       
   483 /**
       
   484 Cancellation of an outstanding request.
       
   485 */
       
   486 void CPcCardIOCTL::DoCancel()
       
   487 {
       
   488 }