localconnectivityservice/dun/plugins/src/usb/DunUsbPlugin.cpp
branchRCL_3
changeset 19 0aa8cc770c8a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/localconnectivityservice/dun/plugins/src/usb/DunUsbPlugin.cpp	Tue Aug 31 16:03:15 2010 +0300
@@ -0,0 +1,781 @@
+/*
+* Copyright (c) 2006-2007 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:  DUN USB plugin
+*
+*/
+
+
+#include <c32comm.h>
+#include <d32usbc.h>
+#include "DunPlugin.h"
+#include "DunUtils.h"
+#include "DunUsbPlugin.h"
+#include "DunDebug.h"
+
+_LIT( KUsbCsyName,     "ECACM"    );
+_LIT( KUsbPortName,    "ACM"      );
+_LIT( KUsbPortPort,    "::"       );
+_LIT( KUsbLddName,     "EUSBC"    );
+_LIT( KUsbChannelName, "DUNUSB::" );
+
+const TInt   KCharactersInTInt      = 10;    // For "2147483648"
+const TUint8 KDefaultAcmProtocolNum = 0x01;  // Hayes compatible modem
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// CDunUsbPlugin::CDunUsbPlugin
+// ---------------------------------------------------------------------------
+//
+CDunUsbPlugin::CDunUsbPlugin() :
+    iServer( NULL ),
+    iUsbListen( NULL ),
+    iUsbConfig( NULL ),
+    iTransporter( NULL )
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CDunUsbPlugin::~CDunUsbPlugin()
+    {
+    FTRACE(FPrint( _L( "CDunUsbPlugin::~CDunUsbPlugin()" ) ));
+    Uninitialize();
+    FTRACE(FPrint( _L( "CDunUsbPlugin::~CDunUsbPlugin() complete" ) ));
+    }
+
+// ---------------------------------------------------------------------------
+// State of this plugin
+// ---------------------------------------------------------------------------
+//
+TDunPluginState CDunUsbPlugin::PluginState()
+    {
+    return iServer->GetPluginStateByUid( KDunUsbPluginUid );
+    }
+
+// ---------------------------------------------------------------------------
+// Constructs a listener object for this plugin
+// ---------------------------------------------------------------------------
+//
+void CDunUsbPlugin::ConstructListenerL()
+    {
+    FTRACE(FPrint(_L("CDunUsbPlugin::ConstructListenerL()")));
+    if ( PluginState() != EDunStateLoaded )
+        {
+        FTRACE(FPrint(_L("CDunUsbPlugin::ConstructListenerL() (not ready) complete")));
+        User::Leave( KErrNotReady );
+        }
+    ReportStateChangeUp( EDunStateTryListen );
+    if ( iUsbListen )
+        {
+        FTRACE(FPrint(_L("CDunUsbPlugin::ConstructListenerL() (already exists) complete")));
+        User::Leave( KErrAlreadyExists );
+        }
+    InitUsbL();
+    CDunUsbListen* listen = CDunUsbListen::NewL( iServer, this, iUsbServer );
+    CleanupStack::PushL( listen );
+    TInt retTemp = listen->IssueRequestL();
+    CleanupStack::Pop( listen );
+    iUsbListen = listen;
+    // Here return value of KErrAlreadyExists means the device is already
+    // configured
+    // In this case we have to switch directly to channeled mode
+    ReportStateChangeUp( EDunStateListening );
+    if ( retTemp == KErrAlreadyExists )
+        {
+        TBool noFreeChans = EFalse;
+        // noFreeChans will be omitted (not needed to set to RComm)
+        NotifyChannelAllocate( noFreeChans );  // Create channel and change state
+        }
+    FTRACE(FPrint(_L("CDunUsbPlugin::ConstructListenerL() complete")));
+    }
+
+// ---------------------------------------------------------------------------
+// Initializes USB by loading LDD
+// ---------------------------------------------------------------------------
+//
+void CDunUsbPlugin::InitUsbL()
+    {
+    FTRACE(FPrint( _L( "CDunUsbPlugin::InitUsbL()") ));
+    // Load Logical device driver for USB
+    FTRACE(FPrint( _L( "CDunUsbPlugin::InitUsbL() LoadLogicalDevice") ));
+    TInt retTemp = User::LoadLogicalDevice( KUsbLddName );
+    if ( retTemp!=KErrAlreadyExists && retTemp!=KErrNone )
+        {
+        User::Leave( retTemp );
+        }
+    // Connect to the USB Manager server
+    FTRACE(FPrint( _L( "CDunUsbPlugin::InitUsbL() Connect()") ));
+    User::LeaveIfError( iUsbServer.Connect() );
+    // Create USB configuration accessor and listener
+    iUsbConfig = CDunUsbConfig::NewL( iServer, this, KDefaultAcmProtocolNum );
+    FTRACE(FPrint( _L( "CDunUsbPlugin::InitUsbL() complete") ));
+    }
+
+// ---------------------------------------------------------------------------
+// Initializes all usable USB ports for DUN
+// ---------------------------------------------------------------------------
+//
+TInt CDunUsbPlugin::InitPorts()
+    {
+    FTRACE(FPrint( _L( "CDunUsbPlugin::InitPorts() (num=%d)" ), iUsbPorts.Count()));
+    TInt i;
+    TInt retTemp = CreateAllPorts();
+    if ( retTemp != KErrNone )
+        {
+        FTRACE(FPrint( _L( "CDunUsbPlugin::InitPorts() (ERROR) complete" )));
+        return retTemp;
+        }
+    TInt count = iUsbPorts.Count();
+    for ( i=0; i<count; i++ )
+        {
+        retTemp = InitOnePort( &iUsbPorts[i] );
+        if ( retTemp != KErrNone )
+            {
+            FTRACE(FPrint( _L( "CDunUsbPlugin::InitPorts() (not ready) complete" )));
+            return KErrGeneral;
+            }
+        }
+    FTRACE(FPrint( _L( "CDunUsbPlugin::InitPorts() complete" )));
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Creates empty usable USB ports that can be used by DUN
+// ---------------------------------------------------------------------------
+//
+TInt CDunUsbPlugin::CreateAllPorts()
+    {
+    FTRACE(FPrint( _L( "CDunUsbPlugin::CreateAllPorts()" ) ));
+    // Connect to comms server
+    TInt retTemp = CDunUtils::ConnectCommsServer( iCommServer );
+    if ( retTemp != KErrNone )
+        {
+        FTRACE(FPrint( _L( "CDunUsbPlugin::CreateAllPorts() (ERROR) complete" )));
+        return retTemp;
+        }
+    // Load communications module
+    retTemp = iCommServer.LoadCommModule( KUsbCsyName );
+    if ( retTemp!=KErrNone && retTemp!=KErrAlreadyExists )
+        {
+        FTRACE(FPrint( _L( "CDunUsbPlugin::CreateAllPorts() (LoadCommModule failed) complete" ) ));
+        return retTemp;
+        }
+    // Stop waiter now (just to be sure) before explicitly fetching port data
+    iUsbConfig->Stop();
+    // Find out what ports can be supported and append them to array
+    TBool validConfig;
+    TUsbPortEntity entity;
+    for ( TInt i=0;; i++ )
+        {
+        retTemp = iUsbConfig->GetConfigValidityByIndex( i, validConfig );
+        if ( retTemp != KErrNone )
+            {
+            break;
+            }
+        if ( !validConfig )
+            {
+            continue;
+            }
+        // Valid config found, append it to array
+        entity.iPortNum = i;
+        retTemp = iUsbPorts.Append( entity );
+        if ( retTemp != KErrNone )
+            {
+            FTRACE(FPrint( _L( "CDunUsbPlugin::CreateAllPorts() (append failed!) complete" ) ));
+            return retTemp;
+            }
+        }
+    FTRACE(FPrint( _L( "CDunUsbPlugin::CreateAllPorts() complete" ) ));
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Initializes one USB port for DUN
+// ---------------------------------------------------------------------------
+//
+TInt CDunUsbPlugin::InitOnePort( TUsbPortEntity* aEntity )
+    {
+    FTRACE(FPrint( _L( "CDunUsbPlugin::InitOnePort()" )));
+    if ( !aEntity )
+        {
+        FTRACE(FPrint( _L( "CDunUsbPlugin::InitOnePort() (not initialized!) complete" )));
+        return KErrGeneral;
+        }
+    TInt retTemp;
+    TName portName;
+    portName.Copy( KUsbPortName );
+    portName.Append( KUsbPortPort );
+    portName.AppendNum( aEntity->iPortNum );
+    retTemp = aEntity->iUsbPort.Open( iCommServer,
+                                      portName,
+                                      ECommExclusive,
+                                      ECommRoleDCE );
+    if ( retTemp != KErrNone )
+        {
+        FTRACE(FPrint( _L( "CDunUsbPlugin::InitOnePort() Open failed (%d)" ), retTemp));
+        return retTemp;
+        }
+    TRAPD( retTrap, SetChannelL(aEntity) );
+    if ( retTrap != KErrNone )
+        {
+        iTransporter->FreeChannel( &aEntity->iUsbPort );
+        FTRACE(FPrint( _L( "CDunUsbPlugin::InitOnePort() (trapped!) complete" )));
+        return retTrap;
+        }
+    FTRACE(FPrint( _L( "CDunUsbPlugin::InitOnePort() complete" )));
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Sets channel for one USB port
+// ---------------------------------------------------------------------------
+//
+void CDunUsbPlugin::SetChannelL( TUsbPortEntity* aEntity )
+    {
+    FTRACE(FPrint( _L( "CDunUsbPlugin::SetChannelL()" )));
+    if ( !aEntity )
+        {
+        FTRACE(FPrint( _L( "CDunUsbPlugin::SetChannelL() (not initialized!) complete" )));
+        User::Leave( KErrGeneral );
+        }
+    HBufC8* channelName = HBufC8::NewMaxLC( KUsbChannelName().Length() +
+                          KCharactersInTInt );
+    TPtr8 channelNamePtr = channelName->Des();
+    channelNamePtr.Copy( KUsbChannelName );
+    channelNamePtr.AppendNum( aEntity->iPortNum );
+    iTransporter->AllocateChannelL( &aEntity->iUsbPort,
+                                    KDunUsbPluginUid,
+                                    channelNamePtr,
+                                    ETrue,
+                                    this );
+    AddSkippedErrorL( KErrUsbInterfaceChange, &aEntity->iUsbPort );
+    iTransporter->AddConnMonCallbackL( &aEntity->iUsbPort,
+                                       this,
+                                       EDunReaderUpstream,
+                                       EFalse );
+    iTransporter->AddConnMonCallbackL( &aEntity->iUsbPort,
+                                       this,
+                                       EDunWriterUpstream,
+                                       EFalse );
+    iTransporter->AddConnMonCallbackL( &aEntity->iUsbPort,
+                                       this,
+                                       EDunReaderDownstream,
+                                       EFalse );
+    iTransporter->AddConnMonCallbackL( &aEntity->iUsbPort,
+                                       this,
+                                       EDunWriterDownstream,
+                                       EFalse );
+    iTransporter->IssueTransferRequestsL( &aEntity->iUsbPort );
+    CleanupStack::PopAndDestroy( channelName );
+    FTRACE(FPrint( _L( "CDunUsbPlugin::SetChannelL() complete" )));
+    }
+
+// ---------------------------------------------------------------------------
+// Adds skipped error code to Transporter
+// The skipped error is added to local media's read and write operations
+// ---------------------------------------------------------------------------
+//
+void CDunUsbPlugin::AddSkippedErrorL( TInt aError, RComm* aComm )
+    {
+    iTransporter->AddSkippedErrorL( aError, aComm, EDunReaderUpstream );
+    iTransporter->AddSkippedErrorL( aError, aComm, EDunWriterDownstream );
+    }
+
+// ---------------------------------------------------------------------------
+// Sets new state
+// New state must be one more than the old state
+// ---------------------------------------------------------------------------
+//
+TInt CDunUsbPlugin::ReportStateChangeUp( TDunPluginState aPluginState )
+    {
+    FTRACE(FPrint(_L("CDunUsbPlugin::ReportStateChangeUp()")));
+    TInt retTemp = iServer->NotifyPluginStateChangeUp( aPluginState,
+                                                       KDunUsbPluginUid );
+    if ( retTemp != KErrNone )
+        {
+        FTRACE(FPrint(_L("CDunUsbPlugin::ReportStateChangeUp() (ERROR) complete")));
+        return retTemp;
+        }
+    FTRACE(FPrint(_L("CDunUsbPlugin::ReportStateChangeUp() complete")));
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Sets new state
+// New state must be one less than the old state
+// ---------------------------------------------------------------------------
+//
+TInt CDunUsbPlugin::ReportStateChangeDown( TDunPluginState aPluginState )
+    {
+    FTRACE(FPrint(_L("CDunUsbPlugin::ReportStateChangeDown()")));
+    TInt retTemp = iServer->NotifyPluginStateChangeDown( aPluginState,
+                                                         KDunUsbPluginUid );
+    if ( retTemp != KErrNone )
+        {
+        FTRACE(FPrint(_L("CDunUsbPlugin::ReportStateChangeDown() (ERROR) complete")));
+        return retTemp;
+        }
+    FTRACE(FPrint(_L("CDunUsbPlugin::ReportStateChangeDown() complete")));
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Frees existing channels
+// ---------------------------------------------------------------------------
+//
+TInt CDunUsbPlugin::FreeChannels()
+    {
+    FTRACE(FPrint(_L("CDunUsbPlugin::FreeChannels()")));
+    if ( PluginState() != EDunStateTryUninitialize )
+        {
+        FTRACE(FPrint( _L( "CDunUsbPlugin::FreeChannels() (not ready) complete" ) ));
+        return KErrNotReady;
+        }
+    TInt i;
+    TInt count = iUsbPorts.Count();
+    for ( i=0; i<count; i++ )
+        {
+        FTRACE(FPrint( _L( "CDunUsbPlugin::FreeChannels() i=%d" ), i));
+        if ( iUsbPorts[i].iUsbPort.SubSessionHandle() )
+            {
+            iTransporter->FreeChannel( &iUsbPorts[i].iUsbPort );
+            iUsbPorts[i].iUsbPort.SetSignals( 0, KSignalDCEOutputs );
+            iUsbPorts[i].iUsbPort.Close();
+            }
+        }
+    iUsbPorts.Close();
+    if ( iCommServer.Handle() != KNullHandle )
+        {
+        iCommServer.UnloadCommModule( KUsbCsyName );
+        iCommServer.Close();
+        }
+    FTRACE(FPrint(_L("CDunUsbPlugin::FreeChannels() complete")));
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Uninitializes this plugin
+// ---------------------------------------------------------------------------
+//
+TInt CDunUsbPlugin::Uninitialize()
+    {
+    FTRACE(FPrint( _L( "CDunUsbPlugin::Uninitialize()" ) ));
+    ReportStateChangeDown( EDunStateTryUninitialize );
+    // Free channel(s), ignore errors
+    FreeChannels();
+    delete iUsbListen;  // delete before iUsbServer close
+    iUsbListen = NULL;
+    delete iUsbConfig;
+    iUsbConfig = NULL;
+    if ( iUsbServer.Handle() != KNullHandle )
+        {
+        iUsbServer.Close();
+        }
+    User::FreeLogicalDevice( KUsbLddName );
+    ReportStateChangeUp( EDunStateUninitialized );
+    ReportStateChangeUp( EDunStateTryLoad );
+    ReportStateChangeUp( EDunStateLoaded );
+    FTRACE(FPrint( _L( "CDunUsbPlugin::Uninitialize() complete" ) ));
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Gets port's index and entity by connection ID
+// ---------------------------------------------------------------------------
+//
+TInt CDunUsbPlugin::GetEntityByConnId( TConnId aConnId,
+                                       TUsbPortEntity*& aEntity )
+    {
+    FTRACE(FPrint( _L( "CDunUsbPlugin::GetEntityByConnId()")) );
+    TInt i;
+    TInt count = iUsbPorts.Count();
+    for ( i=0; i<count; i++ )
+        {
+        if ( &iUsbPorts[i].iUsbPort == aConnId )
+            {
+            aEntity = &iUsbPorts[i];
+            FTRACE(FPrint( _L( "CDunUsbPlugin::GetEntityByConnId() complete")) );
+            return i;
+            }
+        }
+    aEntity = NULL;
+    FTRACE(FPrint( _L( "CDunUsbPlugin::GetEntityByConnId() (not found) complete")) );
+    return KErrNotFound;
+    }
+
+// ---------------------------------------------------------------------------
+// Gets port's entity by port number
+// ---------------------------------------------------------------------------
+//
+TInt CDunUsbPlugin::GetEntityByPortNumber( TInt aPortNum,
+                                           TUsbPortEntity*& aEntity )
+    {
+    FTRACE(FPrint( _L( "CDunUsbPlugin::GetEntityByPortNumber()")) );
+    TInt i;
+    TInt count = iUsbPorts.Count();
+    for ( i=0; i<count; i++ )
+        {
+        if ( iUsbPorts[i].iPortNum == aPortNum )
+            {
+            aEntity = &iUsbPorts[i];
+            FTRACE(FPrint( _L( "CDunUsbPlugin::GetEntityByPortNumber() complete")) );
+            return i;
+            }
+        }
+    aEntity = NULL;
+    FTRACE(FPrint( _L( "CDunUsbPlugin::GetEntityByPortNumber() (not found) complete")) );
+    return KErrNotFound;
+    }
+
+// ---------------------------------------------------------------------------
+// Gets first free port's index and entity
+// ---------------------------------------------------------------------------
+//
+TInt CDunUsbPlugin::GetFirstFreeEntity( TUsbPortEntity*& aEntity )
+    {
+    FTRACE(FPrint( _L( "CDunUsbPlugin::GetFirstFreeEntity()")) );
+    TInt i;
+    TInt count = iUsbPorts.Count();
+    for ( i=0; i<count; i++ )
+        {
+        if ( iUsbPorts[i].iPortNum == KErrNotFound &&
+             !iUsbPorts[i].iUsbPort.SubSessionHandle() )
+            {
+            aEntity = &iUsbPorts[i];
+            FTRACE(FPrint( _L( "CDunUsbPlugin::GetFirstFreeEntity() complete")) );
+            return i;
+            }
+        }
+    aEntity = NULL;
+    FTRACE(FPrint( _L( "CDunUsbPlugin::GetFirstFreeEntity() (not found) complete")) );
+    return KErrNotFound;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MDunLocalMediaPlugin.
+// CDunUsbPlugin::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CDunUsbPlugin::ConstructL( MDunServerCallback* aServer,
+                                CDunTransporter* aTransporter )
+    {
+    FTRACE(FPrint( _L( "CDunUsbPlugin::ConstructL()" ) ));
+    if ( !aServer || !aTransporter )
+        {
+        FTRACE(FPrint( _L( "CDunUsbPlugin::ConstructL() not initialized!" ) ));
+        User::Leave( KErrGeneral );
+        }
+    iServer = aServer;
+    iTransporter = aTransporter;
+    FTRACE(FPrint( _L( "CDunUsbPlugin::ConstructL() complete" ) ));
+    }
+
+// ---------------------------------------------------------------------------
+// From class MDunLocalMediaPlugin.
+// Gets called when server changes a plugin's state
+// ---------------------------------------------------------------------------
+//
+TInt CDunUsbPlugin::NotifyServerStateChange( TDunPluginState aPluginState )
+    {
+    FTRACE(FPrint(_L("CDunUsbPlugin::NotifyServerStateChange()")));
+    TInt retTemp;
+    switch ( aPluginState )
+        {
+        case EDunStateTryListen:
+            if ( PluginState() != EDunStateLoaded )
+                {
+                FTRACE(FPrint(_L("CDunUsbPlugin::NotifyServerStateChange() (not ready) complete")));
+                return KErrNotReady;
+                }
+            // Change to listening mode
+            TRAPD( retTrap, ConstructListenerL() );
+            if ( retTrap != KErrNone )
+                {
+                FTRACE(FPrint(_L("CDunUsbPlugin::NotifyServerStateChange() (ERROR) complete (%d)"), retTrap));
+                return retTrap;
+                }
+            break;
+        case EDunStateTryUninitialize:
+            if ( PluginState() == EDunStateUninitialized )
+                {
+                FTRACE(FPrint(_L("CDunUsbPlugin::NotifyServerStateChange() (not ready) complete")));
+                return KErrNotReady;
+                }
+            // Uninitialize
+            retTemp = Uninitialize();
+            if ( retTemp != KErrNone )
+                {
+                FTRACE(FPrint(_L("CDunUsbPlugin::NotifyServerStateChange() (not ready) complete (%d)"), retTemp));
+                return retTemp;
+                }
+            break;
+        default:
+            FTRACE(FPrint(_L("CDunUsbPlugin::NotifyServerStateChange() (unknown state) complete")));
+            return KErrNotSupported;
+        }
+    FTRACE(FPrint(_L("CDunUsbPlugin::NotifyServerStateChange() complete")));
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MDunLocalMediaPlugin.
+// Gets called when server needs to know the active connection
+// ---------------------------------------------------------------------------
+//
+TConnId CDunUsbPlugin::ActiveConnection()
+    {
+    FTRACE(FPrint(_L("CDunUsbPlugin::ActiveConnection()")));
+    FTRACE(FPrint(_L("CDunUsbPlugin::ActiveConnection() (not found) complete")));
+    return NULL;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MDunListenCallback.
+// Gets called when new channel must be created
+// ---------------------------------------------------------------------------
+//
+TInt CDunUsbPlugin::NotifyChannelAllocate( TBool& /*aNoFreeChans*/ )
+    {
+    FTRACE(FPrint(_L("CDunUsbPlugin::NotifyChannelAllocate()")));
+    if ( PluginState() != EDunStateListening )
+        {
+        FTRACE(FPrint(_L("CDunUsbPlugin::NotifyChannelAllocate() (not ready) complete")));
+        return KErrNotReady;
+        }
+    ReportStateChangeUp( EDunStateTryChannel );
+    TInt retTemp = InitPorts();
+    if ( retTemp != KErrNone )
+        {
+        FTRACE(FPrint(_L("CDunUsbPlugin::NotifyChannelAllocate() (ERROR) complete")));
+        return retTemp;
+        }
+    // Channels allocated so start to wait for possible port config change
+    retTemp = iUsbConfig->IssueRequest();
+    if ( retTemp != KErrNone )
+        {
+        FTRACE(FPrint(_L("CDunUsbPlugin::NotifyChannelAllocate() (ERROR) complete")));
+        return retTemp;
+        }
+    iShutdown = EFalse;
+    ReportStateChangeUp( EDunStateChanneled );
+    FTRACE(FPrint(_L("CDunUsbPlugin::NotifyChannelAllocate() complete")));
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MDunListenCallback.
+// Gets called when an existing channel must be freed
+// ---------------------------------------------------------------------------
+//
+TInt CDunUsbPlugin::NotifyChannelFree()
+    {
+    FTRACE(FPrint(_L("CDunUsbPlugin::NotifyChannelFree()")));
+    if ( PluginState() != EDunStateChanneled )
+        {
+        FTRACE(FPrint(_L("CDunUsbPlugin::NotifyChannelFree() (not ready) complete")));
+        return KErrNotReady;
+        }
+    // Cable removed or PC sleep, hibernate or reset.
+    // Just remove channels.
+    ReportStateChangeDown( EDunStateTryUninitialize );
+    TInt retTemp = FreeChannels();
+    if ( retTemp != KErrNone )
+        {
+        FTRACE(FPrint(_L("CDunUsbPlugin::NotifyChannelFree() (ERROR) complete")));
+        return retTemp;
+        }
+    ReportStateChangeUp( EDunStateUninitialized );
+    ReportStateChangeUp( EDunStateTryLoad );
+    ReportStateChangeUp( EDunStateLoaded );
+    ReportStateChangeUp( EDunStateTryListen );
+    ReportStateChangeUp( EDunStateListening );
+    FTRACE(FPrint(_L("CDunUsbPlugin::NotifyChannelFree() complete")));
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MDunConnMon.
+// Gets called when line status changes or when any type of error is detected
+// ---------------------------------------------------------------------------
+//
+void CDunUsbPlugin::NotifyProgressChangeL(
+    TConnId aConnId,
+    TDunConnectionReason aConnReason )
+    {
+    FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyProgressChangeL()")) );
+    // Find matching failed ID
+    TUsbPortEntity* foundEntity = NULL;
+    TInt foundIndex = GetEntityByConnId( aConnId, foundEntity );
+    if ( !foundEntity )
+        {
+        FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyProgressChangeL() (not found) complete")) );
+        User::Leave( KErrNotFound );
+        }
+    if ( aConnReason.iReasonType == EDunReasonTypeRW ||
+         aConnReason.iReasonType == EDunReasonTypeRunL )
+        {
+        // The following check will make it possible for CDunUsbListen to react
+        // to cable removal (<KErrUsbDriverBase) or to the case when personality
+        // is changed from USBUI and LOCOD/USBWatcher is too slow to notify the
+        // change (KErrAccessDenied).
+        if ( aConnReason.iErrorCode < KErrUsbDriverBase ||
+             aConnReason.iErrorCode == KErrAccessDenied )
+            {
+            FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyProgressChangeL() (shutdown now) complete")) );
+            iShutdown = ETrue;
+            return;
+            }
+        }
+    if ( iShutdown )
+        {
+        FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyProgressChangeL() (shutdown) complete")) );
+        return;
+        }
+    // Now indications are down indications from local media side
+    if ( foundEntity->iUsbPort.SubSessionHandle() )
+        {
+        iTransporter->FreeChannel( &foundEntity->iUsbPort );
+        foundEntity->iUsbPort.SetSignals( 0, KSignalDCEOutputs );
+        foundEntity->iUsbPort.Close();
+        }
+    TInt retTemp = InitOnePort( foundEntity );
+    if ( retTemp != KErrNone )
+        {
+        FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyProgressChangeL() (ERROR) complete")) );
+        User::Leave( KErrGeneral );
+        }
+    // Now this plugin was basically "restarted", but only for one
+    // channel. Because transporter has channels with waiters, notify
+    // server to reopen queued plugin(s)
+    iServer->NotifyPluginReopenRequest();
+    FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyProgressChangeL() complete")) );
+    }
+
+// ---------------------------------------------------------------------------
+// From class MDunBufferCorrection.
+// Gets called when request to change local media's buffer size
+// ---------------------------------------------------------------------------
+//
+TInt CDunUsbPlugin::NotifyBufferCorrection( TInt aLength )
+    {
+    FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyBufferCorrection()")) );
+    /*
+     * This method modifies the default buffer length to match the maximum value
+     * used by "CanHandleZLP=0" configuration option. This length is nearest length
+     * divisible by 64 - 1. With slow USB compared to high speed HSDPA some products
+     * can start to collect data to Dataport which results in full packet writes to
+     * USB. However, the default full packet must not be divisible by 64, which results
+     * in the ACM to send the full packet to LDD plus one extra packet with one byte
+     * (disabling interrupts for a long time with current non-DMA USB driver).
+     */
+    TInt newLength = aLength;
+    if ( newLength % 64 == 0 )
+        {
+        newLength = ((aLength >> 6) << 6) - 1;
+        }
+    FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyBufferCorrection() complete")) );
+    return newLength;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MDunUsbConfig.
+// Gets called when one or more ACM configurations are added
+// ---------------------------------------------------------------------------
+//
+TInt CDunUsbPlugin::NotifyConfigAddition( TInt aIndex )
+    {
+    FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyConfigAddition()")) );
+    // Configuration added so aIndex is the port number to be added to array.
+    // This port number must not already exist in the array.
+    TUsbPortEntity* foundEntity = NULL;
+    TInt foundIndex = GetEntityByPortNumber( aIndex, foundEntity );
+    if ( foundEntity )
+        {
+        FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyConfigAddition() (already exists) complete")) );
+        return KErrAlreadyExists;
+        }
+    // Now either find port with KErrNotFound set as port number or if that is
+    // not found then try to append to array
+    foundIndex = GetFirstFreeEntity( foundEntity );
+    if ( !foundEntity )  // free not found so add new
+        {
+        // Now append the new port to array
+        TUsbPortEntity newEntity;
+        newEntity.iPortNum = aIndex;
+        TInt retTemp = iUsbPorts.Append( newEntity );
+        if ( retTemp != KErrNone )
+            {
+            FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyConfigAddition() (append failed!) complete")) );
+            return KErrGeneral;
+            }
+        // entity not valid here so set now
+        foundEntity = &iUsbPorts[iUsbPorts.Count()-1];
+        }
+    else  // free found so change array
+        {
+        foundEntity->iPortNum = aIndex;
+        }
+    // Open port and create channel for it
+    TInt retTemp = InitOnePort( foundEntity );
+    if ( retTemp != KErrNone )
+        {
+        FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyConfigAddition() (ERROR) complete" )));
+        return KErrGeneral;
+        }
+    FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyConfigAddition() complete")) );
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MDunUsbConfig.
+// Gets called when one or more ACM configurations are removed
+// ---------------------------------------------------------------------------
+//
+TInt CDunUsbPlugin::NotifyConfigRemoval( TInt aIndex )
+    {
+    FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyConfigRemoval()")) );
+    // Configuration removed so aIndex is the port number to be added to array.
+    // This port number must already exist in the array.
+    TUsbPortEntity* foundEntity = NULL;
+    TInt foundIndex = GetEntityByPortNumber( aIndex, foundEntity );
+    if ( !foundEntity )
+        {
+        FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyConfigRemoval() (not found) complete")) );
+        return KErrNotFound;
+        }
+    // Now free channel and mark as unused
+    iTransporter->FreeChannel( &foundEntity->iUsbPort );
+    foundEntity->iUsbPort.SetSignals( 0, KSignalDCEOutputs );
+    foundEntity->iUsbPort.Close();
+    iUsbPorts[foundIndex].iPortNum = KErrNotFound;
+    FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyConfigRemoval() complete")) );
+    return KErrNone;
+    }
+
+// ======== GLOBAL FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// NewLocalPluginL implements factory construction for
+// the class CDunUsbPlugin.
+// The function is exported at ordinal 1.
+// Returns: Pointer: The new instance of CDunUsbPlugin
+// ---------------------------------------------------------------------------
+//
+EXPORT_C MDunLocalMediaPlugin* NewLocalPluginL()
+    {
+    return new (ELeave) CDunUsbPlugin;
+    }