usbmgmt/usbmgr/device/classdrivers/ncm/classimplementation/ncmpktdrv/pktdrv/src/ncmengine.cpp
branchRCL_3
changeset 15 f92a4f87e424
equal deleted inserted replaced
14:d3e8e7d462dd 15:f92a4f87e424
       
     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 #include "ncmengine.h"
       
    19 #include "ncmpktdrv.h"
       
    20 #include "OstTraceDefinitions.h"
       
    21 #ifdef OST_TRACE_COMPILER_IN_USE
       
    22 #include "ncmengineTraces.h"
       
    23 #endif
       
    24 
       
    25 
       
    26 
       
    27 const TUint8 KDataIFAltSet1 = 1;
       
    28 
       
    29 /**
       
    30 Create a new CNcmControlEngine object.
       
    31 */
       
    32 CNcmEngine *CNcmEngine::NewL(CNcmPktDrv& aPktDrv)
       
    33     {
       
    34     OstTraceFunctionEntry0( CNCMENGINE_NEWL );
       
    35 
       
    36     CNcmEngine *self=new (ELeave) CNcmEngine(aPktDrv);
       
    37     CleanupStack::PushL(self);
       
    38     self->ConstructL();
       
    39     CleanupStack::Pop(self);
       
    40 
       
    41     OstTraceFunctionExit1( CNCMENGINE_NEWL_DUP01, self );
       
    42     return self;
       
    43     }
       
    44 
       
    45 /**
       
    46 Create the CNcmEngine object.
       
    47 */
       
    48 void CNcmEngine::ConstructL()
       
    49     {
       
    50     OstTraceFunctionEntry0( CNCMENGINE_CONSTRUCTL );
       
    51 
       
    52     RandomMacAddressL(iSymbianMacAddress);
       
    53 
       
    54     iSharedStateManager = CNcmSharedStateManager::NewL(*this);
       
    55     iDataInterface = CNcmDataInterface::NewL(*this, iDataLdd);
       
    56     iCommInterface = CNcmCommunicationInterface::NewL(*this, iCommLdd);
       
    57 
       
    58     OstTraceFunctionExit0( CNCMENGINE_CONSTRUCTL_DUP01 );
       
    59     }
       
    60 
       
    61 /**
       
    62 Constructor.
       
    63 @param aPktDrv Pointer to NCM Packet Driver.
       
    64 */
       
    65 CNcmEngine::CNcmEngine(CNcmPktDrv& aPktDrv) : CActive(CActive::EPriorityStandard),
       
    66                                     iPktDrv(aPktDrv)
       
    67     {
       
    68     CActiveScheduler::Add(this);
       
    69     }
       
    70 
       
    71 /**
       
    72 Destructor.
       
    73 */
       
    74 CNcmEngine::~CNcmEngine()
       
    75     {
       
    76     OstTraceFunctionEntry0( CNCMENGINE_CNCMENGINE_DUP10 );
       
    77 
       
    78     //double check for possibly missed by PktDrvBase's StopInterface;
       
    79     Stop();
       
    80 
       
    81     delete iCommInterface;
       
    82     delete iDataInterface;
       
    83     delete iSharedStateManager;
       
    84 
       
    85     OstTraceFunctionExit0( CNCMENGINE_CNCMENGINE_DUP11 );
       
    86     }
       
    87 
       
    88 /**
       
    89  * Initialize the DataInterface's and CommInterface's LDD instances with transferred handle.
       
    90  */
       
    91 void CNcmEngine::InitLddL(const RMessagePtr2& aMsg)
       
    92     {
       
    93     OstTraceFunctionEntry0( CNCMENGINE_INITLDDL );
       
    94 
       
    95     const TUint KCommLddOffset = 0;                     //0
       
    96     const TUint KCommChunkOffset = KCommLddOffset + 1;  //1
       
    97     const TUint KDataLddOffset = KCommChunkOffset + 1;  //2
       
    98     const TUint KDataChunkOffset = KDataLddOffset + 1;  //3
       
    99     const TUint KHandlesInStackCount = 3;
       
   100 
       
   101     User::LeaveIfError(iCommLdd.Open(aMsg, KCommLddOffset, EOwnerProcess));
       
   102     CleanupClosePushL(iCommLdd);
       
   103 
       
   104     RChunk* chunk;
       
   105     //Get the Ldd's RChunk, but don't own it.
       
   106     User::LeaveIfError(iCommLdd.GetDataTransferChunk(chunk));
       
   107 
       
   108     User::LeaveIfError(chunk->Open(aMsg, KCommChunkOffset, FALSE, EOwnerProcess));
       
   109     CleanupClosePushL(*chunk);
       
   110 
       
   111     User::LeaveIfError(iDataLdd.Open(aMsg, KDataLddOffset, EOwnerProcess));
       
   112     CleanupClosePushL(iDataLdd);
       
   113 
       
   114     User::LeaveIfError(iDataLdd.GetDataTransferChunk(chunk));
       
   115     User::LeaveIfError(chunk->Open(aMsg, KDataChunkOffset, FALSE, EOwnerProcess));
       
   116 
       
   117     CleanupStack::Pop(KHandlesInStackCount);
       
   118 
       
   119     OstTraceFunctionExit0( CNCMENGINE_INITLDDL_DUP01 );
       
   120     }
       
   121 
       
   122 /**
       
   123  * Start Engine to initialize LDD, and start monitor LDD device status changes.
       
   124  */
       
   125 TInt CNcmEngine::Start(RMessagePtr2& aMsg)
       
   126     {
       
   127     OstTraceFunctionEntry0( CNCMENGINE_START );
       
   128 
       
   129     __ASSERT_DEBUG(iEngineState == ENcmStateUninitialized, User::Panic(KEnginePanic, __LINE__));
       
   130     if (ENcmStateUninitialized != iEngineState)
       
   131         {
       
   132         OstTraceFunctionExitExt( CNCMENGINE_START_DUP10, this, KErrNotSupported );
       
   133         return KErrNotSupported;
       
   134         }
       
   135 
       
   136     TRAPD(err, InitLddL(aMsg));
       
   137     if (KErrNone != err)
       
   138         {
       
   139         OstTrace1( TRACE_ERROR, CNCMENGINE_START_DUP01, "InitLdd return error=%d;", err );
       
   140         return err;
       
   141         }
       
   142 
       
   143     if (KErrNone != iCommLdd.DeviceStatus(reinterpret_cast<TUsbcDeviceState&>(iDeviceState)))
       
   144         {
       
   145         RChunk* commChunk = NULL;
       
   146         RChunk* dataChunk = NULL;
       
   147         iCommLdd.GetDataTransferChunk(commChunk);
       
   148         iDataLdd.GetDataTransferChunk(dataChunk);
       
   149         commChunk->Close();
       
   150         dataChunk->Close();
       
   151         iDataLdd.Close();
       
   152         iCommLdd.Close();
       
   153         OstTraceFunctionExitExt( CNCMENGINE_START_DUP11, this, KErrNotReady );
       
   154         return KErrNotReady;
       
   155         }
       
   156     OstTrace1( TRACE_NORMAL, CNCMENGINE_START_DUP02, "CommLdd DeviceStatus=%d", iDeviceState);
       
   157 
       
   158     if (EUsbcDeviceStateConfigured == iDeviceState)
       
   159         {
       
   160         iStatus = KRequestPending;
       
   161         TRequestStatus* reportStatus = &iStatus;
       
   162         SetActive();
       
   163 
       
   164         User::RequestComplete(reportStatus, KErrNone);
       
   165         }
       
   166     else
       
   167         {
       
   168         iCommLdd.AlternateDeviceStatusNotify(iStatus, iDeviceState);
       
   169         SetActive();
       
   170         }
       
   171 
       
   172     iDataInterface->ActivateLdd();
       
   173 
       
   174     iEngineState = ENcmStateStarting;
       
   175 
       
   176     OstTraceFunctionExitExt( CNCMENGINE_START_DUP12, this, KErrNone );
       
   177     return KErrNone;
       
   178     }
       
   179 
       
   180 /**
       
   181  * Monitor the USB device State, Start/Stop Communication/Data Interface
       
   182  */
       
   183 void CNcmEngine::RunL()
       
   184     {
       
   185     OstTraceExt2( TRACE_NORMAL, CNCMENGINE_RUNL, "iDeviceState=%d;iStatus.Int()=%d", iDeviceState, iStatus.Int() );
       
   186 
       
   187     if (KErrNone == iStatus.Int())
       
   188         {
       
   189         iCommLdd.AlternateDeviceStatusNotify(iStatus, iDeviceState);
       
   190         SetActive();
       
   191         }
       
   192     else
       
   193         {
       
   194         iPktDrv.FatalErrorNotification(iStatus.Int());
       
   195         Stop();
       
   196         return;
       
   197         }
       
   198 
       
   199     switch(iDeviceState)
       
   200         {
       
   201         case EUsbcDeviceStateConfigured:
       
   202             if (!iCommInterface->IsStarted())
       
   203                 {
       
   204                 iCommInterface->Start();
       
   205 
       
   206                 StartDataLayer();
       
   207                 }
       
   208             break;
       
   209 
       
   210         case EUsbcDeviceStateSuspended:
       
   211             StopDataLayer();
       
   212             break;
       
   213 
       
   214         case EUsbcDeviceStateUndefined:
       
   215 
       
   216 			iDataLdd.ResetAltSetting();
       
   217             StopDataLayer();
       
   218             if (iCommInterface->IsStarted())
       
   219                 {
       
   220                 iCommInterface->Stop();
       
   221                 }
       
   222             break;
       
   223 
       
   224         default:
       
   225             //do nothing here.
       
   226             break;
       
   227         }
       
   228     }
       
   229 
       
   230 /**
       
   231 AO cancel
       
   232 */
       
   233 void CNcmEngine::DoCancel()
       
   234     {
       
   235     OstTraceFunctionEntry0( CNCMENGINE_DOCANCEL );
       
   236     iCommLdd.AlternateDeviceStatusNotifyCancel();
       
   237     }
       
   238 
       
   239 /**
       
   240  * Fatal error report from Control Channel
       
   241  */
       
   242 void CNcmEngine::ControlError(TInt aError)
       
   243     {
       
   244     OstTrace1( TRACE_NORMAL, CNCMENGINE_CONTROLERROR, "aError=%d", aError );
       
   245 
       
   246     iPktDrv.FatalErrorNotification(aError);
       
   247     Stop();
       
   248     }
       
   249 
       
   250 /**
       
   251  *Enter the started state.
       
   252  */
       
   253 void CNcmEngine::DoNcmStarted()
       
   254     {
       
   255     OstTraceFunctionEntry0( CNCMENGINE_DONCMSTARTED );
       
   256 
       
   257     iDataInterface->Start();
       
   258     TInt speed = 0;
       
   259     iDataInterface->GetSpeed(speed);
       
   260 
       
   261     iCommInterface->SendSpeedNotification(speed, speed);
       
   262     iCommInterface->SendConnectionNotification(ETrue);
       
   263 
       
   264     __ASSERT_DEBUG(((iEngineState==ENcmStateStarting) || (iEngineState==ENcmStatePaused)), User::Panic(KEnginePanic, __LINE__));
       
   265     iEngineState = ENcmStateStarted;
       
   266     iSharedStateManager->NotifyNcmConnected();
       
   267     }
       
   268 
       
   269 /**
       
   270  *Start the data channel
       
   271  */
       
   272 void CNcmEngine::StartDataLayer()
       
   273     {
       
   274     OstTraceFunctionEntry0( CNCMENGINE_STARTDATALAYER );
       
   275 
       
   276     if (iDataInterface->IsStarted())
       
   277         {
       
   278         OstTrace0( TRACE_WARNING, CNCMENGINE_STARTDATALAYER_DUP01, "The DataIf has already been started!" );
       
   279 
       
   280         __ASSERT_DEBUG(0, User::Panic(KEnginePanic, __LINE__));
       
   281         return;
       
   282         }
       
   283 
       
   284     if (KDataIFAltSet1 != iDataInterface->AltSetting())
       
   285         {
       
   286         OstTrace0( TRACE_NORMAL, CNCMENGINE_STARTDATALAYER_DUP02, "Data Interface is not ready to start; it's fine!!" );
       
   287         return;
       
   288         }
       
   289 
       
   290     TInt ret = iSharedStateManager->NotifyDhcpProvisionRequested();
       
   291     if (KErrAlreadyExists == ret)
       
   292         {
       
   293         DoNcmStarted();
       
   294         }
       
   295     else
       
   296         {
       
   297         if (KErrNone != ret)
       
   298             {
       
   299             //minus error when try to set IPBearerCoexistence P&S key. just continue...
       
   300             OstTrace1( TRACE_WARNING, CNCMENGINE_STARTDATALAYER_DUP03, "SharedStateManager issued dhcp request return error:;ret=%d", ret );
       
   301             }
       
   302 
       
   303         iCommInterface->SendConnectionNotification(EFalse);
       
   304 
       
   305         if (ENcmStatePaused == iEngineState)
       
   306             {
       
   307             iEngineState = ENcmStateStarting;
       
   308             }
       
   309         }
       
   310     }
       
   311 
       
   312 /**
       
   313  *Stop the data channel
       
   314  */
       
   315 void CNcmEngine::StopDataLayer()
       
   316     {
       
   317     OstTraceFunctionEntry0( CNCMENGINE_STOPDATALAYER );
       
   318 
       
   319     if (iDataInterface->IsStarted())
       
   320         {
       
   321         __ASSERT_DEBUG((iEngineState==ENcmStateStarted), User::Panic(KEnginePanic, __LINE__));
       
   322         iEngineState = ENcmStatePaused;
       
   323         iSharedStateManager->NotifyNcmDisconnected(KErrNone);
       
   324 
       
   325         iDataInterface->Stop();
       
   326         }
       
   327     }
       
   328 
       
   329 /**
       
   330  *Stop NCM
       
   331  */
       
   332 void CNcmEngine::Stop()
       
   333     {
       
   334     OstTraceFunctionEntry0( CNCMENGINE_STOP );
       
   335 
       
   336     if (ENcmStateStarted == iEngineState ||
       
   337         ENcmStatePaused == iEngineState ||
       
   338         ENcmStateStarting == iEngineState)
       
   339         {
       
   340         Cancel();
       
   341         iDataInterface->Cancel();
       
   342 
       
   343         if (iDataInterface->IsStarted())
       
   344             {
       
   345             iDataInterface->Stop();
       
   346             }
       
   347 
       
   348         if (iCommInterface->IsStarted())
       
   349             {
       
   350             iCommInterface->Stop();
       
   351             }
       
   352 
       
   353         RChunk* commChunk = NULL;
       
   354         RChunk* dataChunk = NULL;
       
   355 
       
   356         iCommLdd.GetDataTransferChunk(commChunk);
       
   357         iDataLdd.GetDataTransferChunk(dataChunk);
       
   358         commChunk->Close();
       
   359         dataChunk->Close();
       
   360         iDataLdd.Close();
       
   361         iCommLdd.Close();
       
   362         }
       
   363 
       
   364     if (ENcmStateStarted == iEngineState ||
       
   365         ENcmStateStarting == iEngineState)
       
   366         {
       
   367         iSharedStateManager->NotifyNcmDisconnected(KErrNone);
       
   368         }
       
   369     iEngineState = ENcmStateStopped;
       
   370     }
       
   371 
       
   372 /**
       
   373  * Send the ethernet frame to USB Host.
       
   374 */
       
   375 TInt CNcmEngine::Send(RMBufChain &aPacket)
       
   376     {
       
   377     OstTraceExt2( TRACE_NORMAL, CNCMENGINE_SEND, "aPacket=%x;aPacket.Length()=%d", ( TUint )&( aPacket ), aPacket.Length() );
       
   378 
       
   379     return iDataInterface->Send(aPacket);
       
   380     }
       
   381 
       
   382 /**
       
   383 Get the Hardware address of the LAN Device
       
   384 @return MAC address of the Symbian device
       
   385 */
       
   386 TUint8* CNcmEngine::InterfaceAddress()
       
   387     {
       
   388     OstTraceExt3( TRACE_NORMAL, CNCMENGINE_INTERFACEADDRESS, "Local MAC is 02:00:00:%02X:%02X:%02X.", iSymbianMacAddress[3], iSymbianMacAddress[4], iSymbianMacAddress[5]);
       
   389     return static_cast<TUint8*>(&iSymbianMacAddress[0]);
       
   390     }
       
   391 
       
   392 void CNcmEngine::RandomMacAddressL(TNcmMacAddress& aMacAddress)
       
   393     {
       
   394     OstTrace1( TRACE_NORMAL, CNCMENGINE_RANDOMMACADDRESSL, "aMacAddress=%x", ( TUint )&( aMacAddress ) );
       
   395     //random the MAC address
       
   396     aMacAddress.SetLength(KEthernetAddressLength);
       
   397     const TUint KOUILength = 3;
       
   398     const TInt len = KEthernetAddressLength - KOUILength;
       
   399 
       
   400     TPtr8 ptr(&aMacAddress[0] + KOUILength,  len, len);
       
   401     TRandom::RandomL(ptr);
       
   402 
       
   403     //mark it as locally managed address
       
   404     aMacAddress[0] = 0x02;
       
   405     aMacAddress[1] = 0x00;
       
   406     aMacAddress[2] = 0x00;
       
   407     }
       
   408 
       
   409 /** MControlInterfaceObserver
       
   410  * Set Ntb Input Size. See NCM1.0 spec.
       
   411  */
       
   412 TInt CNcmEngine::HandleSetNtbInputSize(TDes8& aSize)
       
   413     {
       
   414     OstTraceFunctionEntry1( CNCMENGINE_HANDLESETNTBINPUTSIZE, ( TUint )&( aSize ) );
       
   415 
       
   416     return iDataInterface->SetNtbInputSize(aSize);
       
   417     }
       
   418 
       
   419 /**
       
   420  * Set Ntb Parameters. See NCM1.0 spec.
       
   421  */
       
   422 TInt CNcmEngine::HandleGetNtbParam(TDes8& aReturnBuf)
       
   423     {
       
   424     OstTraceFunctionEntry1( CNCMENGINE_HANDLEGETNTBPARAM, ( TUint )&( aReturnBuf ) );
       
   425 
       
   426     return iDataInterface->GetNtbParam(aReturnBuf);
       
   427     }
       
   428 
       
   429 /**
       
   430  * Get Ntb Input Size. See NCM1.0 spec.
       
   431  */
       
   432 TInt CNcmEngine::HandleGetNtbInputSize(TDes8& aSize)
       
   433     {
       
   434     OstTraceFunctionEntry1( CNCMENGINE_HANDLEGETNTBINPUTSIZE, ( TUint )&( aSize ) );
       
   435 
       
   436     return iDataInterface->GetNtbInputSize(aSize);
       
   437     }
       
   438 
       
   439 /**
       
   440  * Enable NCM connection by setting NCM speed & connection, when notified that DHCP Provison done successfully.
       
   441  */
       
   442 void CNcmEngine::NotifyDhcpStarted()
       
   443     {
       
   444     OstTraceFunctionEntry0( CNCMENGINE_NOTIFYDHCPSTARTED );
       
   445     __ASSERT_DEBUG(!iDataInterface->IsStarted(), User::Panic(KEnginePanic, __LINE__));
       
   446     if (iDeviceState != EUsbcDeviceStateConfigured || KDataIFAltSet1 != iDataInterface->AltSetting())
       
   447         {
       
   448         OstTraceExt2( TRACE_WARNING, CNCMENGINE_NOTIFYDHCPSTARTED_DUP01, "NotifyDhcpStarted comes so later;iDeviceState=%d;iDataInterface->AltSetting()=%d", iDeviceState, iDataInterface->AltSetting() );
       
   449         return;
       
   450         }
       
   451 
       
   452     DoNcmStarted();
       
   453     }
       
   454 
       
   455 /**
       
   456  *Upwards notify
       
   457  * @param aPacket A Reference to a buffer holding data.
       
   458  */
       
   459 void CNcmEngine::ProcessReceivedDatagram(RMBufPacket& aPacket)
       
   460     {
       
   461     OstTraceExt2( TRACE_NORMAL, CNCMENGINE_PROCESSRECEIVEDDATAGRAM, "aPacket=%x;aPacket.Length()=%d", ( TUint )&( aPacket ), aPacket.Length() );
       
   462     iPktDrv.ReceiveEthFrame(aPacket);
       
   463     }
       
   464 
       
   465 /**
       
   466  * Resume Sending is a notification call into NIF from the lower layer telling the NIF that a
       
   467  * previous sending congestion situation has been cleared and it can accept more downstack data.
       
   468  */
       
   469 void CNcmEngine::ResumeSending()
       
   470     {
       
   471     OstTraceFunctionEntry0( CNCMENGINE_RESUMESENDING );
       
   472     iPktDrv.ResumeSending();
       
   473     }
       
   474 
       
   475 /**
       
   476  * Error report from Data Channel
       
   477  */
       
   478 void CNcmEngine::DataError(TInt aError)
       
   479     {
       
   480     OstTrace1( TRACE_ERROR, CNCMENGINE_DATAERROR, "CNcmEngine::DataError;aError=%d", aError );
       
   481 
       
   482     iPktDrv.FatalErrorNotification(aError);
       
   483     }
       
   484 /**
       
   485  * Handle the data interface alt setting changes.
       
   486  */
       
   487 void CNcmEngine::HandleAltSetting(TInt aIfAltSet)
       
   488     {
       
   489     OstTraceExt3( TRACE_NORMAL, CNCMENGINE_HANDLEALTSETTING, "CNcmEngine::HandleAltSetting;aIfAltSet=%d;iDataInterface->AltSetting()=%d;iDeviceState=%d", aIfAltSet, iDataInterface->AltSetting(), (TInt) iDeviceState );
       
   490 
       
   491     if (KDataIFAltSet1 == aIfAltSet)
       
   492         {
       
   493         StartDataLayer();
       
   494         }
       
   495     else
       
   496         {
       
   497         StopDataLayer();
       
   498         }
       
   499     }
       
   500 
       
   501 TInt CNcmEngine::SetInEpBufferSize(TUint aSize)
       
   502     {
       
   503     OstTrace1( TRACE_NORMAL, CNCMENGINE_SETINEPBUFFERSIZE, "aSize=%u", aSize );
       
   504     return iDataInterface->SetInEpBufferSize(aSize);
       
   505     }
       
   506