usbmgmt/usbmgr/device/classdrivers/ncm/classimplementation/ncmpktdrv/pktdrv/src/ncmdatasender.cpp
branchRCL_3
changeset 16 012cc2ee6408
parent 15 f92a4f87e424
equal deleted inserted replaced
15:f92a4f87e424 16:012cc2ee6408
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 /**
       
    21 @file
       
    22 @internalComponent
       
    23 */
       
    24 
       
    25 
       
    26 #include <e32base.h>
       
    27 
       
    28 #ifndef __OVER_DUMMYUSBSCLDD__
       
    29 #include <d32usbc.h>
       
    30 #else
       
    31 #include <dummyusbsclddapi.h>
       
    32 #endif
       
    33 
       
    34 #include "ncmdatasender.h"
       
    35 #include "ncmntb16builder.h"
       
    36 #include "ncmdatainterface.h"
       
    37 #include "ncmbuffermanager.h"
       
    38 #include "ncmntbbuildsimplepolicy.h"
       
    39 #include "OstTraceDefinitions.h"
       
    40 #ifdef OST_TRACE_COMPILER_IN_USE
       
    41 #include "ncmdatasenderTraces.h"
       
    42 #endif
       
    43 
       
    44 
       
    45 //
       
    46 //write buffer alignment value should get from share chunk LDD, current LDD has no API for this
       
    47 //use a pagesize here instead
       
    48 //
       
    49 const TInt KAlignSize = 1024;
       
    50 
       
    51 
       
    52 // ======== MEMBER FUNCTIONS ========
       
    53 //
       
    54 
       
    55 CNcmDataSender::CNcmDataSender(RDevUsbcScClient& aPort, CNcmDataInterface& aParent) : CActive(EPriorityStandard),
       
    56                                             iPort(aPort),
       
    57                                             iParent(aParent)
       
    58     {
       
    59     CActiveScheduler::Add(this);
       
    60     }
       
    61 
       
    62 CNcmDataSender* CNcmDataSender::NewL(RDevUsbcScClient& aPort, CNcmDataInterface& aParent)
       
    63     {
       
    64     OstTraceFunctionEntry0( CNCMDATASENDER_NEWL_ENTRY );
       
    65     CNcmDataSender *self = new (ELeave) CNcmDataSender(aPort, aParent);
       
    66     CleanupStack::PushL(self);
       
    67     self->ConstructL();
       
    68     CleanupStack::Pop(self);
       
    69     OstTraceFunctionExit0( CNCMDATASENDER_NEWL_EXIT );
       
    70     return self;
       
    71     }
       
    72 
       
    73 void CNcmDataSender::ConstructL()
       
    74     {
       
    75 
       
    76     iNtbBuilder = CNcmNtb16Builder::NewL(*this);
       
    77     iBufferManager = CNcmBufferManager::NewL();
       
    78     iBufferManager->SetAlignSize(KAlignSize);
       
    79     iBuildPolicy = CNcmNtbBuildSimplePolicy::NewL(*iNtbBuilder);
       
    80     iBuildPolicy->NtbBuilder().SetBuildPolicy(*iBuildPolicy);
       
    81     iStarted = EFalse;
       
    82     iStopSending = EFalse;
       
    83     iIsSending = EFalse;
       
    84     }
       
    85 
       
    86 CNcmDataSender::~CNcmDataSender()
       
    87     {
       
    88     Cancel();
       
    89     delete iNtbBuilder;
       
    90     delete iBufferManager;
       
    91     delete iBuildPolicy;
       
    92     }
       
    93 
       
    94 //
       
    95 // Start the sender
       
    96 //
       
    97 void CNcmDataSender::Start()
       
    98     {
       
    99     OstTraceFunctionEntry1( CNCMDATASENDER_START_ENTRY, this );
       
   100     if (iStarted)
       
   101         {
       
   102         OstTrace0( TRACE_ERROR, CNCMDATASENDER_START, "Alrealy start, return directly." );
       
   103         OstTraceFunctionExit1( CNCMDATASENDER_START_EXIT, this );
       
   104         return;
       
   105         }
       
   106 
       
   107     if (iStopSending)
       
   108         {
       
   109         iParent.ResumeSending();
       
   110         iStopSending = EFalse;
       
   111         }
       
   112 
       
   113     TInt ret = iPort.OpenEndpoint(iEpOut, EEndpoint1);
       
   114     if (ret != KErrNone)
       
   115         {
       
   116         OstTrace1( TRACE_FATAL, CNCMDATASENDER_START1, "OpenEndpoint error %d", ret );
       
   117         iParent.DataError(ret);
       
   118         OstTraceFunctionExit1( CNCMDATASENDER_START_EXIT_DUP1, this );
       
   119         return;
       
   120         }
       
   121 
       
   122     TAny* buf = NULL;
       
   123     TUint size;
       
   124     ret = iEpOut.GetInBufferRange(buf, size);
       
   125     if (ret != KErrNone)
       
   126         {
       
   127         OstTrace1( TRACE_FATAL, CNCMDATASENDER_START2, "iEpOut.GetInBufferRange failed ret=%d", ret );
       
   128         iParent.DataError(ret);
       
   129         OstTraceFunctionExit1( CNCMDATASENDER_START_EXIT_DUP2, this );
       
   130         return;
       
   131         }
       
   132     else if (size < NtbInMaxSize())
       
   133         {
       
   134         OstTrace0( TRACE_FATAL, CNCMDATASENDER_START3, "LDD buffer size is small than NTB size" );
       
   135         iParent.DataError(KErrArgument);
       
   136         OstTraceFunctionExit1( CNCMDATASENDER_START_EXIT_DUP3, this );
       
   137         return;
       
   138         }
       
   139     OstTraceExt2( TRACE_NORMAL, CNCMDATASENDER_START4, "GetInBufferRange at 0x%x size %d", (TUint)buf, size);
       
   140 
       
   141 
       
   142     iBufferManager->InitBufferArea(buf, size);
       
   143     ret = iBufferManager->SetBufferCellSize(NtbInMaxSize());
       
   144     if (ret != KErrNone)
       
   145         {
       
   146         OstTrace1( TRACE_FATAL, CNCMDATASENDER_START5, "iBufferManager->SetBufferCellSize failed ret=%d", ret );
       
   147         iParent.DataError(KErrArgument);
       
   148         OstTraceFunctionExit1( CNCMDATASENDER_START_EXIT_DUP4, this );
       
   149         return;
       
   150         }
       
   151     iBuildPolicy->UpdateBufferSize(NtbInMaxSize());
       
   152     iBuildPolicy->UpdateTotalBufferCount(iBufferManager->FreeBufferCount());
       
   153     iStarted = ETrue;
       
   154     OstTraceFunctionExit1( CNCMDATASENDER_START_EXIT_DUP5, this );
       
   155     }
       
   156 
       
   157 
       
   158 void CNcmDataSender::RunL()
       
   159     {
       
   160     OstTraceFunctionEntry1( CNCMDATASENDER_RUNL_ENTRY, this );
       
   161     OstTrace1( TRACE_NORMAL, CNCMDATASENDER_RUNL, "CNcmDataSender::RunL:Status=%d", iStatus.Int());
       
   162 
       
   163     if(iStatus.Int() != KErrNone)
       
   164         {
       
   165         if (KErrCancel == iStatus.Int() )
       
   166             {
       
   167             }
       
   168         else
       
   169             {
       
   170             iParent.DataError(iStatus.Int());
       
   171             }
       
   172         OstTraceFunctionExit1( CNCMDATASENDER_RUNL_EXIT, this );
       
   173         return;
       
   174         }
       
   175     SendNtbComplete();
       
   176     OstTraceFunctionExit1( CNCMDATASENDER_RUNL_EXIT_DUP1, this );
       
   177     }
       
   178 
       
   179 //
       
   180 //Start a New Ntb in Builder
       
   181 //
       
   182 
       
   183 TInt CNcmDataSender::StartNewNtb()
       
   184     {
       
   185     OstTraceFunctionEntry1( CNCMDATASENDER_STARTNEWNTB_ENTRY, this );
       
   186     TNcmBuffer ncmBuffer;
       
   187     TInt ret = iBufferManager->GetBuffer(ncmBuffer);
       
   188 	if (ret == KErrNone || ret == KErrCongestion)
       
   189         {
       
   190         iNtbBuilder->StartNewNtb(ncmBuffer);
       
   191         }
       
   192     else
       
   193         {
       
   194         OstTrace1( TRACE_FATAL, CNCMDATASENDER_STARTNEWNTB, "iBufferManager->GetBuffer failed ret=%d", ret);
       
   195         }
       
   196     OstTraceFunctionExit1( CNCMDATASENDER_STARTNEWNTB_EXIT, this );
       
   197     return ret;
       
   198     }
       
   199 
       
   200 
       
   201 //add a Ethernet packet to current NTB
       
   202 //
       
   203 
       
   204 TInt CNcmDataSender::Send(RMBufChain& aPacket)
       
   205     {
       
   206     OstTraceFunctionEntry1( CNCMDATASENDER_SEND_ENTRY, this );
       
   207 
       
   208     if (!iStarted)
       
   209         {
       
   210         OstTrace0( TRACE_WARNING, CNCMDATASENDER_SEND1, "Sender is not started" );
       
   211         iStopSending = ETrue;
       
   212         OstTraceFunctionExit1( CNCMDATASENDER_SEND_EXIT, this );
       
   213         return KErrNotReady;
       
   214         }
       
   215 
       
   216     TInt ret = KErrNone;
       
   217     if (!iNtbBuilder->IsNtbStarted())
       
   218         {
       
   219         ret = StartNewNtb();
       
   220         if (ret != KErrNone && ret != KErrCongestion)
       
   221             {
       
   222             OstTraceFunctionExit1( CNCMDATASENDER_SEND_EXIT_DUP1, this );
       
   223             return ret;
       
   224             }
       
   225         }
       
   226 
       
   227     TBool isCongestion = (ret == KErrCongestion)?ETrue:EFalse;
       
   228 
       
   229     ret = iNtbBuilder->AppendPacket(aPacket);
       
   230 
       
   231     if (ret == KErrBufferFull)
       
   232         {
       
   233     //current NTB is full and can't add new packet, start a new NTB and insert packet to it
       
   234         ret = StartNewNtb();
       
   235         if (ret == KErrNone)
       
   236             {
       
   237             ret = iNtbBuilder->AppendPacket(aPacket);
       
   238             }
       
   239         else if (ret == KErrCongestion)
       
   240             {
       
   241             isCongestion = ETrue;
       
   242             ret = iNtbBuilder->AppendPacket(aPacket);
       
   243             }
       
   244         }
       
   245 
       
   246     if (isCongestion && ret == KErrNone)
       
   247         {
       
   248         OstTrace0( TRACE_NORMAL, CNCMDATASENDER_SEND2, "CNcmDataSender::Send congestion" );
       
   249         iStopSending = ETrue;
       
   250         OstTraceFunctionExit1( CNCMDATASENDER_SEND_EXIT_DUP2, this );
       
   251         return KErrCongestion;
       
   252         }
       
   253     OstTraceFunctionExit1( CNCMDATASENDER_SEND_EXIT_DUP3, this );
       
   254     return ret;
       
   255     }
       
   256 
       
   257 //
       
   258 //Cancel the outgoing request of sending
       
   259 //
       
   260 
       
   261 void CNcmDataSender::DoCancel()
       
   262     {
       
   263     OstTraceFunctionEntry1( CNCMDATASENDER_DOCANCEL_ENTRY, this );
       
   264     iPort.WriteCancel(iEpOut.BufferNumber());
       
   265     OstTraceFunctionExit1( CNCMDATASENDER_DOCANCEL_EXIT, this );
       
   266     }
       
   267 
       
   268 void CNcmDataSender::SendNtbPayload(TNcmBuffer& aBuf)
       
   269     {
       
   270     OstTraceFunctionEntry1( CNCMDATASENDER_SENDNTBPAYLOAD_ENTRY, this );
       
   271     OstTraceExt2( TRACE_NORMAL, CNCMDATASENDER_SENDNTBPAYLOAD, "SendNtbPayload:%08x, len=%d", (TUint)aBuf.iPtr, aBuf.iLen);
       
   272 
       
   273     if (iIsSending)
       
   274         {
       
   275         OstTrace0( TRACE_NORMAL, CNCMDATASENDER_SENDNTBPAYLOAD1, "SendNtbPayload: there is NTB on sending, store the buffer" );
       
   276         iTxArray.Append(aBuf);
       
   277         OstTraceFunctionExit1( CNCMDATASENDER_SENDNTBPAYLOAD_EXIT, this );
       
   278         return;
       
   279         }
       
   280 
       
   281     iSendingBuffer = aBuf;
       
   282     iIsSending = ETrue;
       
   283 
       
   284     iStatus = KRequestPending;
       
   285     TInt ret;
       
   286     //
       
   287     //   compliant to NCM spec with Zlp case
       
   288     //
       
   289     if (aBuf.iLen == NtbInMaxSize())
       
   290         {
       
   291         OstTrace0( TRACE_NORMAL, CNCMDATASENDER_SENDNTBPAYLOAD2, "iEpOut.WriteBuffer without zlp" );
       
   292         ret = iEpOut.WriteBuffer((TAny*)aBuf.iPtr, aBuf.iLen, EFalse, iStatus);
       
   293         }
       
   294     else
       
   295         {
       
   296         OstTrace0( TRACE_NORMAL, CNCMDATASENDER_SENDNTBPAYLOAD3, "iEpOut.WriteBuffer with zlp" );
       
   297         ret = iEpOut.WriteBuffer((TAny*)aBuf.iPtr, aBuf.iLen, ETrue, iStatus);
       
   298         }
       
   299     if (ret == KErrNone && !IsActive())
       
   300         {
       
   301         SetActive();
       
   302         }
       
   303     else
       
   304         {
       
   305         OstTrace1( TRACE_FATAL, CNCMDATASENDER_SENDNTBPAYLOAD4, "iEpOut.WriteBuffer failed ret = %d", ret);
       
   306         iParent.DataError(ret);
       
   307         }
       
   308     OstTraceFunctionExit1( CNCMDATASENDER_SENDNTBPAYLOAD_EXIT_DUP1, this );
       
   309     return;
       
   310     }
       
   311 
       
   312 //
       
   313 // called when a sender request is completed by LDD
       
   314 //
       
   315 
       
   316 void CNcmDataSender::SendNtbComplete()
       
   317     {
       
   318     OstTraceFunctionEntry1( CNCMDATASENDER_SENDNTBCOMPLETE_ENTRY, this );
       
   319 
       
   320     iIsSending = EFalse;
       
   321     iBufferManager->FreeBuffer(iSendingBuffer);
       
   322     iBuildPolicy->UpdateFreeBufferCount(iBufferManager->FreeBufferCount());
       
   323 
       
   324     // when buffer manage has enough buffers, notify networking to stop flow control
       
   325     if (!iBufferManager->IsCongestion() && iStopSending)
       
   326         {
       
   327         iStopSending = EFalse;
       
   328         iParent.ResumeSending();
       
   329         }
       
   330     if (iTxArray.Count())
       
   331         {
       
   332         OstTrace0( TRACE_NORMAL, CNCMDATASENDER_SENDNTBCOMPLETE3, "send NTB in sending queue" );
       
   333         SendNtbPayload(iTxArray[0]);
       
   334         iTxArray.Remove(0);
       
   335         }
       
   336     OstTraceFunctionExit1( CNCMDATASENDER_SENDNTBCOMPLETE_EXIT, this );
       
   337     }
       
   338 
       
   339 void CNcmDataSender::GetNtbParam(TNcmNtbInParam& aParam)
       
   340     {
       
   341     iNtbBuilder->GetNtbParam(aParam);
       
   342     }
       
   343 
       
   344 TInt CNcmDataSender::SetNtbInMaxSize(TInt aSize, TBool aIsAltZero)
       
   345     {
       
   346     OstTraceFunctionEntry1( CNCMDATASENDER_SETNTBINMAXSIZE_ENTRY, this );
       
   347     OstTrace1( TRACE_NORMAL, CNCMDATASENDER_SETNTBINMAXSIZE, "SetNtbInMaxSize %d", aSize);
       
   348 
       
   349     TInt ret = iNtbBuilder->SetNtbInMaxSize(aSize);
       
   350     if (ret != KErrNone)
       
   351         {
       
   352         OstTrace1( TRACE_FATAL, CNCMDATASENDER_SETNTBINMAXSIZE1, "iNtbBuilder->SetNtbInMaxSize failed %d", ret);
       
   353         OstTraceFunctionExit1( CNCMDATASENDER_SETNTBINMAXSIZE_EXIT, this );
       
   354         return ret;
       
   355         }
       
   356 
       
   357 //
       
   358 //if sender is not started, endpoint buffer is not setup, so does not call SetBufferCellSize
       
   359 //
       
   360     if (!iStarted)
       
   361         {
       
   362         OstTraceFunctionExit1( CNCMDATASENDER_SETNTBINMAXSIZE_EXIT_DUP1, this );
       
   363         return KErrNone;
       
   364         }
       
   365 
       
   366 //    if not in alternate setting 0, there may be data in buffer, so doesn't reset buffers.
       
   367     if (!aIsAltZero)
       
   368         {
       
   369         OstTraceFunctionExit1( CNCMDATASENDER_SETNTBINMAXSIZE_EXIT_DUP2, this );
       
   370         return KErrNone;
       
   371         }
       
   372 
       
   373     OstTraceFunctionExit1( CNCMDATASENDER_SETNTBINMAXSIZE_EXIT_DUP4, this );
       
   374     return KErrNone;
       
   375     }
       
   376 
       
   377 
       
   378 void CNcmDataSender::Stop()
       
   379     {
       
   380     OstTraceFunctionEntry1( CNCMDATASENDER_STOP_ENTRY, this );
       
   381     Cancel();
       
   382     iBuildPolicy->Cancel();
       
   383     iNtbBuilder->Reset();
       
   384     iTxArray.Reset();
       
   385     iEpOut.Close();
       
   386     iStopSending = EFalse;
       
   387     iStarted = EFalse;
       
   388     iIsSending = EFalse;
       
   389     OstTraceFunctionExit1( CNCMDATASENDER_STOP_EXIT, this );
       
   390     }
       
   391 
       
   392 // call this function to notify the buffer size of In endpoint buffer size of LDD and adjust the MaxInNtbSize supported
       
   393 // report to host
       
   394 
       
   395 TInt CNcmDataSender::SetInEpBufferSize(TUint aSize)
       
   396     {
       
   397     OstTraceFunctionEntry1( CNCMDATASENDER_SETINEPBUFFERSIZE_ENTRY, this );
       
   398     TInt ret = KErrNone;
       
   399     TUint size = aSize;
       
   400 
       
   401 	OstTrace1( TRACE_NORMAL, CNCMDATASENDER_SETINEPBUFFERSIZE, "SetInEpBufferSize aSize=%d", aSize);
       
   402 
       
   403 
       
   404 // the buffer may not aligned, so decrease max possible offset due to aligment
       
   405     size -= KAlignSize-1;
       
   406     TInt ntbSize = iNtbBuilder->NtbInMaxSize();
       
   407     TInt cellSize = KAlignSize;
       
   408     TInt minNtbInMaxSize = iNtbBuilder->MinNtbInMaxSize();
       
   409     TInt count;
       
   410     TBool find = EFalse;
       
   411     while (ntbSize >= minNtbInMaxSize)
       
   412         {
       
   413         cellSize = (ntbSize+KAlignSize-1)&~(KAlignSize-1);
       
   414         count = size / cellSize;
       
   415         if (count < iBufferManager->RequiredBufferCount())
       
   416             {
       
   417             ntbSize /= 2;
       
   418             continue;
       
   419             }
       
   420         find = ETrue;
       
   421         break;
       
   422         }
       
   423 
       
   424     if (ntbSize == iNtbBuilder->NtbInMaxSize())
       
   425         {
       
   426         ret = KErrNone;
       
   427         }
       
   428     else if (find)
       
   429         {
       
   430         ret = iNtbBuilder->SetNtbInMaxSize(cellSize);
       
   431         }
       
   432     else
       
   433         {
       
   434         ret = KErrGeneral;
       
   435         }
       
   436     OstTraceFunctionExit1( CNCMDATASENDER_SETINEPBUFFERSIZE_EXIT, this );
       
   437     return ret;
       
   438     }
       
   439