--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/localconnectivityservice/dun/plugins/src/usb/DunUsbPlugin.cpp Mon Jan 18 21:03:15 2010 +0200
@@ -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;
+ }