diff -r d3e8e7d462dd -r f92a4f87e424 usbmgmt/usbmgr/device/classdrivers/ncm/classcontroller/src/ncmconnectionmanager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usbmgmt/usbmgr/device/classdrivers/ncm/classcontroller/src/ncmconnectionmanager.cpp Tue Aug 31 17:01:47 2010 +0300 @@ -0,0 +1,479 @@ +/* +* 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 +#include +#endif // OVERDUMMY_NCMCC + +#include +#include +#include +#include + +#include "ncmconnectionmanager.h" +#include "ncmiapprogresswatcher.h" +#include "ncmiapreader.h" +#include "ncmdhcpnotifwatcher.h" + +#ifdef OVERDUMMY_NCMCC +#include +#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 interfaceInfo; + TPckgBuf 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 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) + 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 ); + }