--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usbmgmt/usbmgr/device/classdrivers/ncm/classcontroller/src/ncmconnectionmanager.cpp Wed Jul 07 14:16:40 2010 +0800
@@ -0,0 +1,480 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+/**
+ * @file
+ * @internalComponent
+ */
+
+#ifndef OVERDUMMY_NCMCC
+#include <commdbconnpref.h>
+#include <es_enum.h>
+#endif // OVERDUMMY_NCMCC
+
+#include <usb/usbncm.h>
+#include <nifvar.h>
+#include <cdbcols.h>
+#include <commdb.h>
+
+#include "ncmconnectionmanager.h"
+#include "ncmiapprogresswatcher.h"
+#include "ncmiapreader.h"
+#include "ncmdhcpnotifwatcher.h"
+
+#ifdef OVERDUMMY_NCMCC
+#include <usb/testncmcc/dummy_ncminternalsrv.h>
+#else
+#include "ncminternalsrv.h"
+#endif // OVERDUMMY_NCMCC
+
+#include "ncmclasscontroller.h"
+#include "ncmconnectionmanagerobserver.h"
+#include "ncmconnectionmanagerhelper.h"
+
+// For OST tracing
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "ncmconnectionmanagerTraces.h"
+#endif
+
+using namespace UsbNcm;
+
+#if defined(_DEBUG)
+_LIT(KNcmConnManagerPanic, "UsbNcmCM"); // must be <=16 chars
+#endif
+
+extern const TUint KEthernetFrameSize;
+
+// Panic codes
+enum TNcmCMPanicCode
+ {
+ ENcmCMPanicOutstandingRequestFromDevice = 1,
+ ENcmCMPanicNoRegisteredWatcher = 2,
+ ENcmCMEndMark
+ };
+
+/**
+ * Constructs a CNcmConnectionManager object.
+ * @param[in] aObserver, NCM connection observer
+ * @param[in] aHostMacAddress, the NCM interface MAC address
+ * @param[in] aDataBufferSize, the EndPoint buffer size
+ * @param[in] aNcmInternalSvr, the NCM internal server
+ * @return Ownership of a new CNcmConnectionManager object
+ */
+CNcmConnectionManager* CNcmConnectionManager::NewL(
+ MNcmConnectionManagerObserver& aObserver,
+ const TNcmMacAddress& aMacAddress, TUint aDataBufferSize,
+ RNcmInternalSrv& aNcmInternalSvr)
+ {
+ OstTraceFunctionEntry0(CNCMCONNECTIONMANAGER_NEWL_ENTRY);
+
+ CNcmConnectionManager* self = new (ELeave) CNcmConnectionManager(aObserver,
+ aMacAddress, aDataBufferSize, aNcmInternalSvr);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+
+ OstTraceFunctionExit0(CNCMCONNECTIONMANAGER_NEWL_EXIT);
+ return self;
+ }
+
+/**
+ * Method to perform second phase construction.
+ */
+void CNcmConnectionManager::ConstructL()
+ {
+ OstTraceFunctionEntry0(CNCMCONNECTIONMANAGER_CONSTRUCTL_ENTRY);
+
+ TInt err = RProperty::Define(KUsbmanSvrUid, KKeyNcmSharedState, RProperty::EInt,
+ KAllowAllPolicy, KCommDDPolicy);
+
+ if (KErrNone != err)
+ {
+ OstTrace1( TRACE_ERROR, CNCMCONNECTIONMANAGER_CONSTRUCTL, "Define NCM shared state P&S key fail: err=%d", err );
+ User::Leave(err);
+ }
+
+ User::LeaveIfError(iProperty.Attach(KUsbmanSvrUid, KKeyNcmSharedState));
+ User::LeaveIfError(iProperty.Set(ENcmStateIntial));
+
+ User::LeaveIfError(iSocketServ.Connect());
+ User::LeaveIfError(iConnection.Open(iSocketServ));
+
+ iIapPrgrsWatcher = new (ELeave) CNcmIapProgressWatcher(*this, iConnection);
+ iConnManHelper = new (ELeave) CNcmConnectionManHelper(*this, iConnection);
+ iDhcpNotifWatcher = new (ELeave) CNcmDhcpNotifWatcher(*this, iNcmInternalSvr);
+ iIapReader = new (ELeave) CNcmIapReader(*this, iConnPref);
+
+ OstTraceFunctionExit0(CNCMCONNECTIONMANAGER_CONSTRUCTL_EXIT);
+ }
+
+/**
+ * Called when NCM connection starting attempt completed
+ */
+void CNcmConnectionManager::HandleConnectionCompleteL()
+ {
+ OstTraceFunctionEntry0( CNCMCONNECTIONMANAGER_HANDLECONNECTIONCOMPLETEL_ENTRY );
+ OstTrace0(TRACE_NORMAL, CNCMCONNECTIONMANAGER_HANDLECONNECTIONCOMPLETEL_CHANGE_MTU, "About to change default MTU size!");
+ // Change default MTU size
+ SetCustomMtuL();
+
+ OstTrace0(TRACE_NORMAL, CNCMCONNECTIONMANAGER_HANDLECONNECTIONCOMPLETEL_CONN_NCM_INTERNAL_SVR, "About to connect to internal NCM server!");
+
+ // Connect to internal server in packet driver
+ User::LeaveIfError(iNcmInternalSvr.Connect());
+
+ iNcmInternalSvr.TransferBufferSize(iDataBufferSize);
+ iNcmInternalSvr.SetIapId(iConnPref.IapId());
+ iDhcpNotifWatcher->StartL();
+ OstTraceFunctionExit0( CNCMCONNECTIONMANAGER_HANDLECONNECTIONCOMPLETEL_EXIT );
+ }
+
+/**
+ * Destructor.
+ */
+CNcmConnectionManager::~CNcmConnectionManager()
+ {
+ OstTraceFunctionEntry0(CNCMCONNECTIONMANAGER_CNCMCONNECTIONMANAGER_DESTRUCTOR_ENTRY);
+
+ delete iIapReader;
+ delete iDhcpNotifWatcher;
+ delete iConnManHelper;
+ delete iIapPrgrsWatcher;
+
+ iConnection.Close();
+ iSocketServ.Close();
+ iProperty.Close();
+
+ RProperty::Delete(KKeyNcmSharedState);
+
+ OstTraceFunctionExit0(CNCMCONNECTIONMANAGER_CNCMCONNECTIONMANAGER_DESTRUCTOR_EXIT);
+ }
+
+/**
+ * Constructor.
+ * @param[in] aObserver, NCM connection observer
+ * @param[in] aHostMacAddress, the NCM interface MAC address
+ * @param[in] aDataBufferSize, the EndPoint buffer size
+ * @param[in] aNcmInternalSvr, the NCM internal server
+ */
+CNcmConnectionManager::CNcmConnectionManager(MNcmConnectionManagerObserver& aObserver,
+ const TNcmMacAddress& aHostMacAddress, TUint aDataBufferSize,
+ RNcmInternalSrv& aNcmInternalSvr):
+ iConnMgrObserver(aObserver),
+ iHostMacAddress(aHostMacAddress), iDataBufferSize(aDataBufferSize),
+ iNcmInternalSvr(aNcmInternalSvr)
+ {
+ // No implementation needed.
+ }
+
+/**
+ *Called by class controller to start the connection building process.
+ *@param aStatus, reference to ncm class controller's iStatus
+ */
+void CNcmConnectionManager::Start(TRequestStatus& aStatus)
+ {
+ OstTraceFunctionEntry0(CNCMCONNECTIONMANAGER_START_ENTRY);
+
+ __ASSERT_DEBUG(!iReportStatus,
+ User::Panic(KNcmConnManagerPanic, ENcmCMPanicOutstandingRequestFromDevice));
+
+ aStatus = KRequestPending;
+ iReportStatus = &aStatus;
+
+ Reset();
+
+ // Preparing IAP information
+ iIapReader->Start();
+ OstTraceFunctionExit0(CNCMCONNECTIONMANAGER_START_EXIT);
+ }
+
+/**
+ * Cancel ongoing starting attempt
+ */
+void CNcmConnectionManager::StartCancel()
+ {
+ OstTraceFunctionEntry0(CNCMCONNECTIONMANAGER_STARTCANCEL_ENTRY);
+
+ __ASSERT_DEBUG(iReportStatus,
+ User::Panic(KNcmConnManagerPanic, ENcmCMPanicNoRegisteredWatcher));
+
+ Stop();
+
+ User::RequestComplete(iReportStatus, KErrCancel);
+
+ OstTraceFunctionExit0(CNCMCONNECTIONMANAGER_STARTCANCEL_EXIT);
+ }
+
+/**
+ * Called by class controller to stop the connection.
+ */
+void CNcmConnectionManager::Stop()
+ {
+ OstTraceFunctionEntry0(CNCMCONNECTIONMANAGER_STOP_ENTRY);
+
+ // Cancel any current ongoing operations
+ Reset();
+
+ // Reset shared state
+ iProperty.Set(ENcmStateIntial);
+
+ iConnManHelper->Stop();
+ OstTraceFunctionExit0(CNCMCONNECTIONMANAGER_STOP_EXIT);
+ }
+
+/**
+ * Reset conneciton manager itself
+ */
+void CNcmConnectionManager::Reset()
+ {
+ OstTraceFunctionEntry0(CNCMCONNECTIONMANAGER_RESET_ENTRY);
+
+ iConnComplete = EFalse;
+
+ iIapReader->Cancel();
+ iDhcpNotifWatcher->Cancel();
+ iIapPrgrsWatcher->Cancel();
+ iConnManHelper->Cancel();
+
+ OstTraceFunctionExit0(CNCMCONNECTIONMANAGER_RESET_EXIT);
+ }
+/**
+ * Change the default MTU size on NCM networking connection
+ */
+void CNcmConnectionManager::SetCustomMtuL()
+ {
+ OstTraceFunctionEntry0(CNCMCONNECTIONMANAGER_SETCUSTOMMTUL_ENTRY);
+
+ RSocket socket;
+ User::LeaveIfError(socket.Open(iSocketServ, KAfInet, KSockStream, KProtocolInetTcp,
+ iConnection));
+
+ TPckgBuf<TSoInet6InterfaceInfo> interfaceInfo;
+ TPckgBuf<TConnInterfaceName> interfaceName;
+
+ TUint cnt = 0;
+ iConnection.EnumerateConnections(cnt); // Count all underlying interfaces
+
+ TUint iap = iConnPref.IapId();
+ TInt index = 1;
+ for (index = 1; index <= cnt; index++)
+ {
+ TConnectionInfoBuf info;
+ iConnection.GetConnectionInfo(index, info);
+ if (info().iIapId == iap)
+ {
+ break;
+ }
+ }
+
+ if (index > cnt)
+ {
+ OstTrace0( TRACE_NORMAL, CNCMCONNECTIONMANAGER_SETCUSTOMMTUL, "Can not find an interface based on NCM!" );
+ User::Leave(KErrNotFound);
+ }
+
+ interfaceName().iIndex = index;
+ OstTraceExt2( TRACE_NORMAL, CNCMCONNECTIONMANAGER_SETCUSTOMMTUL_INTER_INFO, ";cnt=%d;interfaceName().iIndex=%u", cnt, interfaceName().iIndex );
+ User::LeaveIfError(iConnection.Control(KCOLProvider, KConnGetInterfaceName, interfaceName));
+ OstTraceExt3( TRACE_NORMAL, CNCMCONNECTIONMANAGER_SETCUSTOMMTUL_NEW_MTU_SIZE, ";Interface Name=%S, ;current MTU=%d. MTU size will be changed to %d!", interfaceName().iName, interfaceInfo().iMtu, KEthernetFrameSize);
+
+ TInt err = socket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl);
+ if (err != KErrNone)
+ {
+ OstTrace1(TRACE_NORMAL, CNCMCONNECTIONMANAGER_SETCUSTOMMTUL_START_INTER_ENUM, "Failed to set KSoInetEnumInterfaces option [%d]", err);
+ User::LeaveIfError(err);
+ }
+
+ err = KErrNotFound;
+ while (socket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, interfaceInfo) == KErrNone)
+ {
+ OstTraceExt1(TRACE_NORMAL, CNCMCONNECTIONMANAGER_SETCUSTOMMTUL_INTER_NAME, "InterfaceInfo().iName = %S", interfaceInfo().iName);
+ OstTrace1(TRACE_NORMAL, CNCMCONNECTIONMANAGER_SETCUSTOMMTUL_INTER_MTU, "InterfaceInfo().iMtu = %d", interfaceInfo().iMtu);
+ if (interfaceInfo().iName == interfaceName().iName)
+ {
+ // found the interface
+ err = KErrNone;
+ break;
+ }
+ }
+ if (KErrNone != err)
+ {
+ OstTrace1(TRACE_ERROR, CNCMCONNECTIONMANAGER_SETCUSTOMMTUL_SEARCH_FAIL, "Can not find NCM connection: err=%x", err);
+ User::LeaveIfError(err);
+ }
+
+ // Set new MTU size
+ TPckgBuf<TSoInet6InterfaceInfo> newinterfaceInfo;
+ newinterfaceInfo().iMtu = KEthernetFrameSize;
+ newinterfaceInfo().iDoPrefix = 0;
+ newinterfaceInfo().iDoId = 0;
+ newinterfaceInfo().iDoState = 0;
+ newinterfaceInfo().iDoAnycast = 0;
+ newinterfaceInfo().iDoProxy = 0;
+ newinterfaceInfo().iAlias = interfaceInfo().iAlias;
+ newinterfaceInfo().iDelete = interfaceInfo().iDelete;
+ newinterfaceInfo().iState = interfaceInfo().iState;
+ newinterfaceInfo().iSpeedMetric = interfaceInfo().iSpeedMetric;
+ newinterfaceInfo().iFeatures = interfaceInfo().iFeatures;
+ newinterfaceInfo().iTag = interfaceInfo().iTag;
+ newinterfaceInfo().iName = interfaceInfo().iName;
+ newinterfaceInfo().iSpeedMetric = interfaceInfo().iSpeedMetric;
+ newinterfaceInfo().iFeatures = interfaceInfo().iFeatures;
+ newinterfaceInfo().iHwAddr = interfaceInfo().iHwAddr;
+ newinterfaceInfo().iAddress = interfaceInfo().iAddress;
+ newinterfaceInfo().iNetMask = interfaceInfo().iNetMask;
+ newinterfaceInfo().iDefGate = interfaceInfo().iDefGate;
+ newinterfaceInfo().iNameSer2 = interfaceInfo().iNameSer2;
+ newinterfaceInfo().iNameSer1 = interfaceInfo().iNameSer1;
+
+ OstTrace0( TRACE_NORMAL, CNCMCONNECTIONMANAGER_SETCUSTOMMTUL_PRE_SETMTU, "About to change the default MTU size." );
+ User::LeaveIfError(socket.SetOpt(KSoInetConfigInterface, KSolInetIfCtrl, newinterfaceInfo));
+
+ socket.Close();
+
+ OstTraceFunctionExit0(CNCMCONNECTIONMANAGER_SETCUSTOMMTUL_EXIT);
+ }
+
+/**
+ * Called by connection watcher when it detects the class fatal error.
+ */
+void CNcmConnectionManager::MipsoHandleClassFatalError(TInt aError)
+ {
+ OstTraceFunctionEntryExt( CNCMCONNECTIONMANAGER_MIPSOHANDLECLASSFATALERROR_ENTRY, this );
+
+ Reset();
+
+ __ASSERT_DEBUG(!iReportStatus, User::Panic(KNcmConnManagerPanic, ENcmCMPanicOutstandingRequestFromDevice));
+
+ OstTrace1(TRACE_ERROR, CNCMCONNECTIONMANAGER_MIPSOHANDLECLASSFATALERROR, "NCM connection fatal error occurs: %d", aError);
+
+ iConnMgrObserver.McmoErrorIndication(aError);
+
+ OstTraceFunctionExit1( CNCMCONNECTIONMANAGER_MIPSOHANDLECLASSFATALERROR_EXIT, this );
+ }
+
+/**
+ * Called by connection help when it get notification the
+ * connection over NCM has been established.
+ */
+void CNcmConnectionManager::MicoHandleConnectionComplete(TInt aError)
+ {
+ OstTraceFunctionEntryExt( CNCMCONNECTIONMANAGER_MICOHANDLECONNECTIONCOMPLETE_ENTRY, this );
+
+ // Reset shared state
+ iProperty.Set(ENcmStateIntial);
+
+ if (KErrNone == aError)
+ {
+ TRAPD(err, HandleConnectionCompleteL());
+ User::RequestComplete(iReportStatus, err);
+ }
+ else
+ {
+ // Leave if connection build failed
+ User::RequestComplete(iReportStatus, aError);
+ }
+
+ OstTraceFunctionExit1( CNCMCONNECTIONMANAGER_MICOHANDLECONNECTIONCOMPLETE_EXIT, this );
+ }
+
+/**
+ * Called by DHCP notification watcher.
+ * When the NCM internal server send DHCP request notification to
+ * the watcher, watcher call this function to do DHCP provisioning
+ * for NCM connection.
+ */
+void CNcmConnectionManager::MdnoHandleDhcpNotification(TInt aError)
+ {
+ OstTraceFunctionEntryExt( CNCMCONNECTIONMANAGER_MDNOHANDLEDHCPNOTIFICATION_ENTRY, this );
+ if (KErrNone != aError)
+ {
+ // Report this failure to the observer
+ // Finally this will report to usbman and NCM class will be stopped.
+ iConnMgrObserver.McmoErrorIndication(aError);
+ OstTraceFunctionExit1( CNCMCONNECTIONMANAGER_MDNOHANDLEDHCPNOTIFICATION_EXIT, this );
+ return;
+ }
+
+ // Doing DHCP for NCM
+ aError = KErrNone;
+
+ // Configuring DHCP server to assign the IP address to PC(host)
+ // Using static IP temporarily and will swithch to use DHCP server to do provision.
+// TRequestStatus stat;
+// OstTrace0(TRACE_NORMAL, CNCMCONNECTIONMANAGER_MDNOHANDLEDHCPNOTIFICATION_CALL_IOCTL, "About to call to Ioctl()");
+//
+// TNcmMacAddress macAddr = iHostMacAddress;
+// iConnection.Ioctl(KCOLConfiguration, KConnDhcpSetHwAddressParams, stat,
+// &macAddr);
+// User::WaitForRequest(stat);
+// aError = stat.Int();
+// OstTrace1( TRACE_NORMAL, CNCMCONNECTIONMANAGER_MDNOHANDLEDHCPNOTIFICATION_RETURN_IOCTL, "Return from Ioctl:;aError=%d", aError );
+
+ if (KErrNone == aError)
+ {
+ // Disable timer on interface and wont let interface coming down due to timer expiry.
+ iConnection.SetOpt(KCOLProvider, KConnDisableTimers, ETrue);
+ iIapPrgrsWatcher->Start();
+ }
+ else
+ {
+ // Silent stop the NCM connection.
+ iConnManHelper->Stop();
+
+ // Report this failure to the observer
+ // Finally this will report to usbman and NCM class will be stopped.
+ iConnMgrObserver.McmoErrorIndication(aError);
+ }
+
+ // Set DHCP result to NCM internal server
+ iNcmInternalSvr.SetDhcpResult(aError);
+ OstTraceFunctionExit1( CNCMCONNECTIONMANAGER_MDNOHANDLEDHCPNOTIFICATION_EXIT_DUP1, this );
+ }
+
+/**
+ * Called by IAP reader.
+ * When IAP reader finished reading NCM IAP preference from CentRep,
+ * it will call this function to start building ethernet connection
+ * using NCM IAP configuration.
+ */
+void CNcmConnectionManager::MicoHandleIAPReadingComplete(TInt aError)
+ {
+ OstTraceFunctionEntryExt( CNCMCONNECTIONMANAGER_MICOHANDLEIAPREADINGCOMPLETE_ENTRY, this );
+ if (KErrNone != aError)
+ {
+ OstTrace1( TRACE_ERROR, CNCMCONNECTIONMANAGER_MICOHANDLEIAPREADINGCOMPLETE_IAP_RESULT, "IAP reading failed with error;aError=%d", aError );
+ User::RequestComplete(iReportStatus, aError);
+
+ OstTraceFunctionExit1( CNCMCONNECTIONMANAGER_MICOHANDLEIAPREADINGCOMPLETE_EXIT, this );
+ return;
+ }
+
+ aError = iProperty.Set(ENcmStartRequested);
+
+ if (KErrNone != aError)
+ {
+ OstTrace1( TRACE_ERROR, CNCMCONNECTIONMANAGER_MICOHANDLEIAPREADINGCOMPLETE_SET_SHARED_STATE, "Property set failed with error:;aError=%d", aError );
+ User::RequestComplete(iReportStatus, aError);
+
+ OstTraceFunctionExit1( CNCMCONNECTIONMANAGER_MICOHANDLEIAPREADINGCOMPLETE_EXIT_DUP1, this );
+ return;
+ }
+
+ iConnManHelper->Start(iConnPref);
+ OstTraceFunctionExit1( CNCMCONNECTIONMANAGER_MICOHANDLEIAPREADINGCOMPLETE_EXIT_DUP2, this );
+ }