localconnectivityservice/dun/plugins/src/usb/DunUsbPlugin.cpp
branchRCL_3
changeset 20 4a793f564d72
parent 19 0aa8cc770c8a
child 21 74aa6861c87d
equal deleted inserted replaced
19:0aa8cc770c8a 20:4a793f564d72
     1 /*
       
     2 * Copyright (c) 2006-2007 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:  DUN USB plugin
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <c32comm.h>
       
    20 #include <d32usbc.h>
       
    21 #include "DunPlugin.h"
       
    22 #include "DunUtils.h"
       
    23 #include "DunUsbPlugin.h"
       
    24 #include "DunDebug.h"
       
    25 
       
    26 _LIT( KUsbCsyName,     "ECACM"    );
       
    27 _LIT( KUsbPortName,    "ACM"      );
       
    28 _LIT( KUsbPortPort,    "::"       );
       
    29 _LIT( KUsbLddName,     "EUSBC"    );
       
    30 _LIT( KUsbChannelName, "DUNUSB::" );
       
    31 
       
    32 const TInt   KCharactersInTInt      = 10;    // For "2147483648"
       
    33 const TUint8 KDefaultAcmProtocolNum = 0x01;  // Hayes compatible modem
       
    34 
       
    35 // ======== MEMBER FUNCTIONS ========
       
    36 
       
    37 // ---------------------------------------------------------------------------
       
    38 // CDunUsbPlugin::CDunUsbPlugin
       
    39 // ---------------------------------------------------------------------------
       
    40 //
       
    41 CDunUsbPlugin::CDunUsbPlugin() :
       
    42     iServer( NULL ),
       
    43     iUsbListen( NULL ),
       
    44     iUsbConfig( NULL ),
       
    45     iTransporter( NULL )
       
    46     {
       
    47     }
       
    48 
       
    49 // ---------------------------------------------------------------------------
       
    50 // Destructor.
       
    51 // ---------------------------------------------------------------------------
       
    52 //
       
    53 CDunUsbPlugin::~CDunUsbPlugin()
       
    54     {
       
    55     FTRACE(FPrint( _L( "CDunUsbPlugin::~CDunUsbPlugin()" ) ));
       
    56     Uninitialize();
       
    57     FTRACE(FPrint( _L( "CDunUsbPlugin::~CDunUsbPlugin() complete" ) ));
       
    58     }
       
    59 
       
    60 // ---------------------------------------------------------------------------
       
    61 // State of this plugin
       
    62 // ---------------------------------------------------------------------------
       
    63 //
       
    64 TDunPluginState CDunUsbPlugin::PluginState()
       
    65     {
       
    66     return iServer->GetPluginStateByUid( KDunUsbPluginUid );
       
    67     }
       
    68 
       
    69 // ---------------------------------------------------------------------------
       
    70 // Constructs a listener object for this plugin
       
    71 // ---------------------------------------------------------------------------
       
    72 //
       
    73 void CDunUsbPlugin::ConstructListenerL()
       
    74     {
       
    75     FTRACE(FPrint(_L("CDunUsbPlugin::ConstructListenerL()")));
       
    76     if ( PluginState() != EDunStateLoaded )
       
    77         {
       
    78         FTRACE(FPrint(_L("CDunUsbPlugin::ConstructListenerL() (not ready) complete")));
       
    79         User::Leave( KErrNotReady );
       
    80         }
       
    81     ReportStateChangeUp( EDunStateTryListen );
       
    82     if ( iUsbListen )
       
    83         {
       
    84         FTRACE(FPrint(_L("CDunUsbPlugin::ConstructListenerL() (already exists) complete")));
       
    85         User::Leave( KErrAlreadyExists );
       
    86         }
       
    87     InitUsbL();
       
    88     CDunUsbListen* listen = CDunUsbListen::NewL( iServer, this, iUsbServer );
       
    89     CleanupStack::PushL( listen );
       
    90     TInt retTemp = listen->IssueRequestL();
       
    91     CleanupStack::Pop( listen );
       
    92     iUsbListen = listen;
       
    93     // Here return value of KErrAlreadyExists means the device is already
       
    94     // configured
       
    95     // In this case we have to switch directly to channeled mode
       
    96     ReportStateChangeUp( EDunStateListening );
       
    97     if ( retTemp == KErrAlreadyExists )
       
    98         {
       
    99         TBool noFreeChans = EFalse;
       
   100         // noFreeChans will be omitted (not needed to set to RComm)
       
   101         NotifyChannelAllocate( noFreeChans );  // Create channel and change state
       
   102         }
       
   103     FTRACE(FPrint(_L("CDunUsbPlugin::ConstructListenerL() complete")));
       
   104     }
       
   105 
       
   106 // ---------------------------------------------------------------------------
       
   107 // Initializes USB by loading LDD
       
   108 // ---------------------------------------------------------------------------
       
   109 //
       
   110 void CDunUsbPlugin::InitUsbL()
       
   111     {
       
   112     FTRACE(FPrint( _L( "CDunUsbPlugin::InitUsbL()") ));
       
   113     // Load Logical device driver for USB
       
   114     FTRACE(FPrint( _L( "CDunUsbPlugin::InitUsbL() LoadLogicalDevice") ));
       
   115     TInt retTemp = User::LoadLogicalDevice( KUsbLddName );
       
   116     if ( retTemp!=KErrAlreadyExists && retTemp!=KErrNone )
       
   117         {
       
   118         User::Leave( retTemp );
       
   119         }
       
   120     // Connect to the USB Manager server
       
   121     FTRACE(FPrint( _L( "CDunUsbPlugin::InitUsbL() Connect()") ));
       
   122     User::LeaveIfError( iUsbServer.Connect() );
       
   123     // Create USB configuration accessor and listener
       
   124     iUsbConfig = CDunUsbConfig::NewL( iServer, this, KDefaultAcmProtocolNum );
       
   125     FTRACE(FPrint( _L( "CDunUsbPlugin::InitUsbL() complete") ));
       
   126     }
       
   127 
       
   128 // ---------------------------------------------------------------------------
       
   129 // Initializes all usable USB ports for DUN
       
   130 // ---------------------------------------------------------------------------
       
   131 //
       
   132 TInt CDunUsbPlugin::InitPorts()
       
   133     {
       
   134     FTRACE(FPrint( _L( "CDunUsbPlugin::InitPorts() (num=%d)" ), iUsbPorts.Count()));
       
   135     TInt i;
       
   136     TInt retTemp = CreateAllPorts();
       
   137     if ( retTemp != KErrNone )
       
   138         {
       
   139         FTRACE(FPrint( _L( "CDunUsbPlugin::InitPorts() (ERROR) complete" )));
       
   140         return retTemp;
       
   141         }
       
   142     TInt count = iUsbPorts.Count();
       
   143     for ( i=0; i<count; i++ )
       
   144         {
       
   145         retTemp = InitOnePort( &iUsbPorts[i] );
       
   146         if ( retTemp != KErrNone )
       
   147             {
       
   148             FTRACE(FPrint( _L( "CDunUsbPlugin::InitPorts() (not ready) complete" )));
       
   149             return KErrGeneral;
       
   150             }
       
   151         }
       
   152     FTRACE(FPrint( _L( "CDunUsbPlugin::InitPorts() complete" )));
       
   153     return KErrNone;
       
   154     }
       
   155 
       
   156 // ---------------------------------------------------------------------------
       
   157 // Creates empty usable USB ports that can be used by DUN
       
   158 // ---------------------------------------------------------------------------
       
   159 //
       
   160 TInt CDunUsbPlugin::CreateAllPorts()
       
   161     {
       
   162     FTRACE(FPrint( _L( "CDunUsbPlugin::CreateAllPorts()" ) ));
       
   163     // Connect to comms server
       
   164     TInt retTemp = CDunUtils::ConnectCommsServer( iCommServer );
       
   165     if ( retTemp != KErrNone )
       
   166         {
       
   167         FTRACE(FPrint( _L( "CDunUsbPlugin::CreateAllPorts() (ERROR) complete" )));
       
   168         return retTemp;
       
   169         }
       
   170     // Load communications module
       
   171     retTemp = iCommServer.LoadCommModule( KUsbCsyName );
       
   172     if ( retTemp!=KErrNone && retTemp!=KErrAlreadyExists )
       
   173         {
       
   174         FTRACE(FPrint( _L( "CDunUsbPlugin::CreateAllPorts() (LoadCommModule failed) complete" ) ));
       
   175         return retTemp;
       
   176         }
       
   177     // Stop waiter now (just to be sure) before explicitly fetching port data
       
   178     iUsbConfig->Stop();
       
   179     // Find out what ports can be supported and append them to array
       
   180     TBool validConfig;
       
   181     TUsbPortEntity entity;
       
   182     for ( TInt i=0;; i++ )
       
   183         {
       
   184         retTemp = iUsbConfig->GetConfigValidityByIndex( i, validConfig );
       
   185         if ( retTemp != KErrNone )
       
   186             {
       
   187             break;
       
   188             }
       
   189         if ( !validConfig )
       
   190             {
       
   191             continue;
       
   192             }
       
   193         // Valid config found, append it to array
       
   194         entity.iPortNum = i;
       
   195         retTemp = iUsbPorts.Append( entity );
       
   196         if ( retTemp != KErrNone )
       
   197             {
       
   198             FTRACE(FPrint( _L( "CDunUsbPlugin::CreateAllPorts() (append failed!) complete" ) ));
       
   199             return retTemp;
       
   200             }
       
   201         }
       
   202     FTRACE(FPrint( _L( "CDunUsbPlugin::CreateAllPorts() complete" ) ));
       
   203     return KErrNone;
       
   204     }
       
   205 
       
   206 // ---------------------------------------------------------------------------
       
   207 // Initializes one USB port for DUN
       
   208 // ---------------------------------------------------------------------------
       
   209 //
       
   210 TInt CDunUsbPlugin::InitOnePort( TUsbPortEntity* aEntity )
       
   211     {
       
   212     FTRACE(FPrint( _L( "CDunUsbPlugin::InitOnePort()" )));
       
   213     if ( !aEntity )
       
   214         {
       
   215         FTRACE(FPrint( _L( "CDunUsbPlugin::InitOnePort() (not initialized!) complete" )));
       
   216         return KErrGeneral;
       
   217         }
       
   218     TInt retTemp;
       
   219     TName portName;
       
   220     portName.Copy( KUsbPortName );
       
   221     portName.Append( KUsbPortPort );
       
   222     portName.AppendNum( aEntity->iPortNum );
       
   223     retTemp = aEntity->iUsbPort.Open( iCommServer,
       
   224                                       portName,
       
   225                                       ECommExclusive,
       
   226                                       ECommRoleDCE );
       
   227     if ( retTemp != KErrNone )
       
   228         {
       
   229         FTRACE(FPrint( _L( "CDunUsbPlugin::InitOnePort() Open failed (%d)" ), retTemp));
       
   230         return retTemp;
       
   231         }
       
   232     TRAPD( retTrap, SetChannelL(aEntity) );
       
   233     if ( retTrap != KErrNone )
       
   234         {
       
   235         iTransporter->FreeChannel( &aEntity->iUsbPort );
       
   236         FTRACE(FPrint( _L( "CDunUsbPlugin::InitOnePort() (trapped!) complete" )));
       
   237         return retTrap;
       
   238         }
       
   239     FTRACE(FPrint( _L( "CDunUsbPlugin::InitOnePort() complete" )));
       
   240     return KErrNone;
       
   241     }
       
   242 
       
   243 // ---------------------------------------------------------------------------
       
   244 // Sets channel for one USB port
       
   245 // ---------------------------------------------------------------------------
       
   246 //
       
   247 void CDunUsbPlugin::SetChannelL( TUsbPortEntity* aEntity )
       
   248     {
       
   249     FTRACE(FPrint( _L( "CDunUsbPlugin::SetChannelL()" )));
       
   250     if ( !aEntity )
       
   251         {
       
   252         FTRACE(FPrint( _L( "CDunUsbPlugin::SetChannelL() (not initialized!) complete" )));
       
   253         User::Leave( KErrGeneral );
       
   254         }
       
   255     HBufC8* channelName = HBufC8::NewMaxLC( KUsbChannelName().Length() +
       
   256                           KCharactersInTInt );
       
   257     TPtr8 channelNamePtr = channelName->Des();
       
   258     channelNamePtr.Copy( KUsbChannelName );
       
   259     channelNamePtr.AppendNum( aEntity->iPortNum );
       
   260     iTransporter->AllocateChannelL( &aEntity->iUsbPort,
       
   261                                     KDunUsbPluginUid,
       
   262                                     channelNamePtr,
       
   263                                     ETrue,
       
   264                                     this );
       
   265     AddSkippedErrorL( KErrUsbInterfaceChange, &aEntity->iUsbPort );
       
   266     iTransporter->AddConnMonCallbackL( &aEntity->iUsbPort,
       
   267                                        this,
       
   268                                        EDunReaderUpstream,
       
   269                                        EFalse );
       
   270     iTransporter->AddConnMonCallbackL( &aEntity->iUsbPort,
       
   271                                        this,
       
   272                                        EDunWriterUpstream,
       
   273                                        EFalse );
       
   274     iTransporter->AddConnMonCallbackL( &aEntity->iUsbPort,
       
   275                                        this,
       
   276                                        EDunReaderDownstream,
       
   277                                        EFalse );
       
   278     iTransporter->AddConnMonCallbackL( &aEntity->iUsbPort,
       
   279                                        this,
       
   280                                        EDunWriterDownstream,
       
   281                                        EFalse );
       
   282     iTransporter->IssueTransferRequestsL( &aEntity->iUsbPort );
       
   283     CleanupStack::PopAndDestroy( channelName );
       
   284     FTRACE(FPrint( _L( "CDunUsbPlugin::SetChannelL() complete" )));
       
   285     }
       
   286 
       
   287 // ---------------------------------------------------------------------------
       
   288 // Adds skipped error code to Transporter
       
   289 // The skipped error is added to local media's read and write operations
       
   290 // ---------------------------------------------------------------------------
       
   291 //
       
   292 void CDunUsbPlugin::AddSkippedErrorL( TInt aError, RComm* aComm )
       
   293     {
       
   294     iTransporter->AddSkippedErrorL( aError, aComm, EDunReaderUpstream );
       
   295     iTransporter->AddSkippedErrorL( aError, aComm, EDunWriterDownstream );
       
   296     }
       
   297 
       
   298 // ---------------------------------------------------------------------------
       
   299 // Sets new state
       
   300 // New state must be one more than the old state
       
   301 // ---------------------------------------------------------------------------
       
   302 //
       
   303 TInt CDunUsbPlugin::ReportStateChangeUp( TDunPluginState aPluginState )
       
   304     {
       
   305     FTRACE(FPrint(_L("CDunUsbPlugin::ReportStateChangeUp()")));
       
   306     TInt retTemp = iServer->NotifyPluginStateChangeUp( aPluginState,
       
   307                                                        KDunUsbPluginUid );
       
   308     if ( retTemp != KErrNone )
       
   309         {
       
   310         FTRACE(FPrint(_L("CDunUsbPlugin::ReportStateChangeUp() (ERROR) complete")));
       
   311         return retTemp;
       
   312         }
       
   313     FTRACE(FPrint(_L("CDunUsbPlugin::ReportStateChangeUp() complete")));
       
   314     return KErrNone;
       
   315     }
       
   316 
       
   317 // ---------------------------------------------------------------------------
       
   318 // Sets new state
       
   319 // New state must be one less than the old state
       
   320 // ---------------------------------------------------------------------------
       
   321 //
       
   322 TInt CDunUsbPlugin::ReportStateChangeDown( TDunPluginState aPluginState )
       
   323     {
       
   324     FTRACE(FPrint(_L("CDunUsbPlugin::ReportStateChangeDown()")));
       
   325     TInt retTemp = iServer->NotifyPluginStateChangeDown( aPluginState,
       
   326                                                          KDunUsbPluginUid );
       
   327     if ( retTemp != KErrNone )
       
   328         {
       
   329         FTRACE(FPrint(_L("CDunUsbPlugin::ReportStateChangeDown() (ERROR) complete")));
       
   330         return retTemp;
       
   331         }
       
   332     FTRACE(FPrint(_L("CDunUsbPlugin::ReportStateChangeDown() complete")));
       
   333     return KErrNone;
       
   334     }
       
   335 
       
   336 // ---------------------------------------------------------------------------
       
   337 // Frees existing channels
       
   338 // ---------------------------------------------------------------------------
       
   339 //
       
   340 TInt CDunUsbPlugin::FreeChannels()
       
   341     {
       
   342     FTRACE(FPrint(_L("CDunUsbPlugin::FreeChannels()")));
       
   343     if ( PluginState() != EDunStateTryUninitialize )
       
   344         {
       
   345         FTRACE(FPrint( _L( "CDunUsbPlugin::FreeChannels() (not ready) complete" ) ));
       
   346         return KErrNotReady;
       
   347         }
       
   348     TInt i;
       
   349     TInt count = iUsbPorts.Count();
       
   350     for ( i=0; i<count; i++ )
       
   351         {
       
   352         FTRACE(FPrint( _L( "CDunUsbPlugin::FreeChannels() i=%d" ), i));
       
   353         if ( iUsbPorts[i].iUsbPort.SubSessionHandle() )
       
   354             {
       
   355             iTransporter->FreeChannel( &iUsbPorts[i].iUsbPort );
       
   356             iUsbPorts[i].iUsbPort.SetSignals( 0, KSignalDCEOutputs );
       
   357             iUsbPorts[i].iUsbPort.Close();
       
   358             }
       
   359         }
       
   360     iUsbPorts.Close();
       
   361     if ( iCommServer.Handle() != KNullHandle )
       
   362         {
       
   363         iCommServer.UnloadCommModule( KUsbCsyName );
       
   364         iCommServer.Close();
       
   365         }
       
   366     FTRACE(FPrint(_L("CDunUsbPlugin::FreeChannels() complete")));
       
   367     return KErrNone;
       
   368     }
       
   369 
       
   370 // ---------------------------------------------------------------------------
       
   371 // Uninitializes this plugin
       
   372 // ---------------------------------------------------------------------------
       
   373 //
       
   374 TInt CDunUsbPlugin::Uninitialize()
       
   375     {
       
   376     FTRACE(FPrint( _L( "CDunUsbPlugin::Uninitialize()" ) ));
       
   377     ReportStateChangeDown( EDunStateTryUninitialize );
       
   378     // Free channel(s), ignore errors
       
   379     FreeChannels();
       
   380     delete iUsbListen;  // delete before iUsbServer close
       
   381     iUsbListen = NULL;
       
   382     delete iUsbConfig;
       
   383     iUsbConfig = NULL;
       
   384     if ( iUsbServer.Handle() != KNullHandle )
       
   385         {
       
   386         iUsbServer.Close();
       
   387         }
       
   388     User::FreeLogicalDevice( KUsbLddName );
       
   389     ReportStateChangeUp( EDunStateUninitialized );
       
   390     ReportStateChangeUp( EDunStateTryLoad );
       
   391     ReportStateChangeUp( EDunStateLoaded );
       
   392     FTRACE(FPrint( _L( "CDunUsbPlugin::Uninitialize() complete" ) ));
       
   393     return KErrNone;
       
   394     }
       
   395 
       
   396 // ---------------------------------------------------------------------------
       
   397 // Gets port's index and entity by connection ID
       
   398 // ---------------------------------------------------------------------------
       
   399 //
       
   400 TInt CDunUsbPlugin::GetEntityByConnId( TConnId aConnId,
       
   401                                        TUsbPortEntity*& aEntity )
       
   402     {
       
   403     FTRACE(FPrint( _L( "CDunUsbPlugin::GetEntityByConnId()")) );
       
   404     TInt i;
       
   405     TInt count = iUsbPorts.Count();
       
   406     for ( i=0; i<count; i++ )
       
   407         {
       
   408         if ( &iUsbPorts[i].iUsbPort == aConnId )
       
   409             {
       
   410             aEntity = &iUsbPorts[i];
       
   411             FTRACE(FPrint( _L( "CDunUsbPlugin::GetEntityByConnId() complete")) );
       
   412             return i;
       
   413             }
       
   414         }
       
   415     aEntity = NULL;
       
   416     FTRACE(FPrint( _L( "CDunUsbPlugin::GetEntityByConnId() (not found) complete")) );
       
   417     return KErrNotFound;
       
   418     }
       
   419 
       
   420 // ---------------------------------------------------------------------------
       
   421 // Gets port's entity by port number
       
   422 // ---------------------------------------------------------------------------
       
   423 //
       
   424 TInt CDunUsbPlugin::GetEntityByPortNumber( TInt aPortNum,
       
   425                                            TUsbPortEntity*& aEntity )
       
   426     {
       
   427     FTRACE(FPrint( _L( "CDunUsbPlugin::GetEntityByPortNumber()")) );
       
   428     TInt i;
       
   429     TInt count = iUsbPorts.Count();
       
   430     for ( i=0; i<count; i++ )
       
   431         {
       
   432         if ( iUsbPorts[i].iPortNum == aPortNum )
       
   433             {
       
   434             aEntity = &iUsbPorts[i];
       
   435             FTRACE(FPrint( _L( "CDunUsbPlugin::GetEntityByPortNumber() complete")) );
       
   436             return i;
       
   437             }
       
   438         }
       
   439     aEntity = NULL;
       
   440     FTRACE(FPrint( _L( "CDunUsbPlugin::GetEntityByPortNumber() (not found) complete")) );
       
   441     return KErrNotFound;
       
   442     }
       
   443 
       
   444 // ---------------------------------------------------------------------------
       
   445 // Gets first free port's index and entity
       
   446 // ---------------------------------------------------------------------------
       
   447 //
       
   448 TInt CDunUsbPlugin::GetFirstFreeEntity( TUsbPortEntity*& aEntity )
       
   449     {
       
   450     FTRACE(FPrint( _L( "CDunUsbPlugin::GetFirstFreeEntity()")) );
       
   451     TInt i;
       
   452     TInt count = iUsbPorts.Count();
       
   453     for ( i=0; i<count; i++ )
       
   454         {
       
   455         if ( iUsbPorts[i].iPortNum == KErrNotFound &&
       
   456              !iUsbPorts[i].iUsbPort.SubSessionHandle() )
       
   457             {
       
   458             aEntity = &iUsbPorts[i];
       
   459             FTRACE(FPrint( _L( "CDunUsbPlugin::GetFirstFreeEntity() complete")) );
       
   460             return i;
       
   461             }
       
   462         }
       
   463     aEntity = NULL;
       
   464     FTRACE(FPrint( _L( "CDunUsbPlugin::GetFirstFreeEntity() (not found) complete")) );
       
   465     return KErrNotFound;
       
   466     }
       
   467 
       
   468 // ---------------------------------------------------------------------------
       
   469 // From class MDunLocalMediaPlugin.
       
   470 // CDunUsbPlugin::ConstructL
       
   471 // ---------------------------------------------------------------------------
       
   472 //
       
   473 void CDunUsbPlugin::ConstructL( MDunServerCallback* aServer,
       
   474                                 CDunTransporter* aTransporter )
       
   475     {
       
   476     FTRACE(FPrint( _L( "CDunUsbPlugin::ConstructL()" ) ));
       
   477     if ( !aServer || !aTransporter )
       
   478         {
       
   479         FTRACE(FPrint( _L( "CDunUsbPlugin::ConstructL() not initialized!" ) ));
       
   480         User::Leave( KErrGeneral );
       
   481         }
       
   482     iServer = aServer;
       
   483     iTransporter = aTransporter;
       
   484     FTRACE(FPrint( _L( "CDunUsbPlugin::ConstructL() complete" ) ));
       
   485     }
       
   486 
       
   487 // ---------------------------------------------------------------------------
       
   488 // From class MDunLocalMediaPlugin.
       
   489 // Gets called when server changes a plugin's state
       
   490 // ---------------------------------------------------------------------------
       
   491 //
       
   492 TInt CDunUsbPlugin::NotifyServerStateChange( TDunPluginState aPluginState )
       
   493     {
       
   494     FTRACE(FPrint(_L("CDunUsbPlugin::NotifyServerStateChange()")));
       
   495     TInt retTemp;
       
   496     switch ( aPluginState )
       
   497         {
       
   498         case EDunStateTryListen:
       
   499             if ( PluginState() != EDunStateLoaded )
       
   500                 {
       
   501                 FTRACE(FPrint(_L("CDunUsbPlugin::NotifyServerStateChange() (not ready) complete")));
       
   502                 return KErrNotReady;
       
   503                 }
       
   504             // Change to listening mode
       
   505             TRAPD( retTrap, ConstructListenerL() );
       
   506             if ( retTrap != KErrNone )
       
   507                 {
       
   508                 FTRACE(FPrint(_L("CDunUsbPlugin::NotifyServerStateChange() (ERROR) complete (%d)"), retTrap));
       
   509                 return retTrap;
       
   510                 }
       
   511             break;
       
   512         case EDunStateTryUninitialize:
       
   513             if ( PluginState() == EDunStateUninitialized )
       
   514                 {
       
   515                 FTRACE(FPrint(_L("CDunUsbPlugin::NotifyServerStateChange() (not ready) complete")));
       
   516                 return KErrNotReady;
       
   517                 }
       
   518             // Uninitialize
       
   519             retTemp = Uninitialize();
       
   520             if ( retTemp != KErrNone )
       
   521                 {
       
   522                 FTRACE(FPrint(_L("CDunUsbPlugin::NotifyServerStateChange() (not ready) complete (%d)"), retTemp));
       
   523                 return retTemp;
       
   524                 }
       
   525             break;
       
   526         default:
       
   527             FTRACE(FPrint(_L("CDunUsbPlugin::NotifyServerStateChange() (unknown state) complete")));
       
   528             return KErrNotSupported;
       
   529         }
       
   530     FTRACE(FPrint(_L("CDunUsbPlugin::NotifyServerStateChange() complete")));
       
   531     return KErrNone;
       
   532     }
       
   533 
       
   534 // ---------------------------------------------------------------------------
       
   535 // From class MDunLocalMediaPlugin.
       
   536 // Gets called when server needs to know the active connection
       
   537 // ---------------------------------------------------------------------------
       
   538 //
       
   539 TConnId CDunUsbPlugin::ActiveConnection()
       
   540     {
       
   541     FTRACE(FPrint(_L("CDunUsbPlugin::ActiveConnection()")));
       
   542     FTRACE(FPrint(_L("CDunUsbPlugin::ActiveConnection() (not found) complete")));
       
   543     return NULL;
       
   544     }
       
   545 
       
   546 // ---------------------------------------------------------------------------
       
   547 // From class MDunListenCallback.
       
   548 // Gets called when new channel must be created
       
   549 // ---------------------------------------------------------------------------
       
   550 //
       
   551 TInt CDunUsbPlugin::NotifyChannelAllocate( TBool& /*aNoFreeChans*/ )
       
   552     {
       
   553     FTRACE(FPrint(_L("CDunUsbPlugin::NotifyChannelAllocate()")));
       
   554     if ( PluginState() != EDunStateListening )
       
   555         {
       
   556         FTRACE(FPrint(_L("CDunUsbPlugin::NotifyChannelAllocate() (not ready) complete")));
       
   557         return KErrNotReady;
       
   558         }
       
   559     ReportStateChangeUp( EDunStateTryChannel );
       
   560     TInt retTemp = InitPorts();
       
   561     if ( retTemp != KErrNone )
       
   562         {
       
   563         FTRACE(FPrint(_L("CDunUsbPlugin::NotifyChannelAllocate() (ERROR) complete")));
       
   564         return retTemp;
       
   565         }
       
   566     // Channels allocated so start to wait for possible port config change
       
   567     retTemp = iUsbConfig->IssueRequest();
       
   568     if ( retTemp != KErrNone )
       
   569         {
       
   570         FTRACE(FPrint(_L("CDunUsbPlugin::NotifyChannelAllocate() (ERROR) complete")));
       
   571         return retTemp;
       
   572         }
       
   573     iShutdown = EFalse;
       
   574     ReportStateChangeUp( EDunStateChanneled );
       
   575     FTRACE(FPrint(_L("CDunUsbPlugin::NotifyChannelAllocate() complete")));
       
   576     return KErrNone;
       
   577     }
       
   578 
       
   579 // ---------------------------------------------------------------------------
       
   580 // From class MDunListenCallback.
       
   581 // Gets called when an existing channel must be freed
       
   582 // ---------------------------------------------------------------------------
       
   583 //
       
   584 TInt CDunUsbPlugin::NotifyChannelFree()
       
   585     {
       
   586     FTRACE(FPrint(_L("CDunUsbPlugin::NotifyChannelFree()")));
       
   587     if ( PluginState() != EDunStateChanneled )
       
   588         {
       
   589         FTRACE(FPrint(_L("CDunUsbPlugin::NotifyChannelFree() (not ready) complete")));
       
   590         return KErrNotReady;
       
   591         }
       
   592     // Cable removed or PC sleep, hibernate or reset.
       
   593     // Just remove channels.
       
   594     ReportStateChangeDown( EDunStateTryUninitialize );
       
   595     TInt retTemp = FreeChannels();
       
   596     if ( retTemp != KErrNone )
       
   597         {
       
   598         FTRACE(FPrint(_L("CDunUsbPlugin::NotifyChannelFree() (ERROR) complete")));
       
   599         return retTemp;
       
   600         }
       
   601     ReportStateChangeUp( EDunStateUninitialized );
       
   602     ReportStateChangeUp( EDunStateTryLoad );
       
   603     ReportStateChangeUp( EDunStateLoaded );
       
   604     ReportStateChangeUp( EDunStateTryListen );
       
   605     ReportStateChangeUp( EDunStateListening );
       
   606     FTRACE(FPrint(_L("CDunUsbPlugin::NotifyChannelFree() complete")));
       
   607     return KErrNone;
       
   608     }
       
   609 
       
   610 // ---------------------------------------------------------------------------
       
   611 // From class MDunConnMon.
       
   612 // Gets called when line status changes or when any type of error is detected
       
   613 // ---------------------------------------------------------------------------
       
   614 //
       
   615 void CDunUsbPlugin::NotifyProgressChangeL(
       
   616     TConnId aConnId,
       
   617     TDunConnectionReason aConnReason )
       
   618     {
       
   619     FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyProgressChangeL()")) );
       
   620     // Find matching failed ID
       
   621     TUsbPortEntity* foundEntity = NULL;
       
   622     TInt foundIndex = GetEntityByConnId( aConnId, foundEntity );
       
   623     if ( !foundEntity )
       
   624         {
       
   625         FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyProgressChangeL() (not found) complete")) );
       
   626         User::Leave( KErrNotFound );
       
   627         }
       
   628     if ( aConnReason.iReasonType == EDunReasonTypeRW ||
       
   629          aConnReason.iReasonType == EDunReasonTypeRunL )
       
   630         {
       
   631         // The following check will make it possible for CDunUsbListen to react
       
   632         // to cable removal (<KErrUsbDriverBase) or to the case when personality
       
   633         // is changed from USBUI and LOCOD/USBWatcher is too slow to notify the
       
   634         // change (KErrAccessDenied).
       
   635         if ( aConnReason.iErrorCode < KErrUsbDriverBase ||
       
   636              aConnReason.iErrorCode == KErrAccessDenied )
       
   637             {
       
   638             FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyProgressChangeL() (shutdown now) complete")) );
       
   639             iShutdown = ETrue;
       
   640             return;
       
   641             }
       
   642         }
       
   643     if ( iShutdown )
       
   644         {
       
   645         FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyProgressChangeL() (shutdown) complete")) );
       
   646         return;
       
   647         }
       
   648     // Now indications are down indications from local media side
       
   649     if ( foundEntity->iUsbPort.SubSessionHandle() )
       
   650         {
       
   651         iTransporter->FreeChannel( &foundEntity->iUsbPort );
       
   652         foundEntity->iUsbPort.SetSignals( 0, KSignalDCEOutputs );
       
   653         foundEntity->iUsbPort.Close();
       
   654         }
       
   655     TInt retTemp = InitOnePort( foundEntity );
       
   656     if ( retTemp != KErrNone )
       
   657         {
       
   658         FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyProgressChangeL() (ERROR) complete")) );
       
   659         User::Leave( KErrGeneral );
       
   660         }
       
   661     // Now this plugin was basically "restarted", but only for one
       
   662     // channel. Because transporter has channels with waiters, notify
       
   663     // server to reopen queued plugin(s)
       
   664     iServer->NotifyPluginReopenRequest();
       
   665     FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyProgressChangeL() complete")) );
       
   666     }
       
   667 
       
   668 // ---------------------------------------------------------------------------
       
   669 // From class MDunBufferCorrection.
       
   670 // Gets called when request to change local media's buffer size
       
   671 // ---------------------------------------------------------------------------
       
   672 //
       
   673 TInt CDunUsbPlugin::NotifyBufferCorrection( TInt aLength )
       
   674     {
       
   675     FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyBufferCorrection()")) );
       
   676     /*
       
   677      * This method modifies the default buffer length to match the maximum value
       
   678      * used by "CanHandleZLP=0" configuration option. This length is nearest length
       
   679      * divisible by 64 - 1. With slow USB compared to high speed HSDPA some products
       
   680      * can start to collect data to Dataport which results in full packet writes to
       
   681      * USB. However, the default full packet must not be divisible by 64, which results
       
   682      * in the ACM to send the full packet to LDD plus one extra packet with one byte
       
   683      * (disabling interrupts for a long time with current non-DMA USB driver).
       
   684      */
       
   685     TInt newLength = aLength;
       
   686     if ( newLength % 64 == 0 )
       
   687         {
       
   688         newLength = ((aLength >> 6) << 6) - 1;
       
   689         }
       
   690     FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyBufferCorrection() complete")) );
       
   691     return newLength;
       
   692     }
       
   693 
       
   694 // ---------------------------------------------------------------------------
       
   695 // From class MDunUsbConfig.
       
   696 // Gets called when one or more ACM configurations are added
       
   697 // ---------------------------------------------------------------------------
       
   698 //
       
   699 TInt CDunUsbPlugin::NotifyConfigAddition( TInt aIndex )
       
   700     {
       
   701     FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyConfigAddition()")) );
       
   702     // Configuration added so aIndex is the port number to be added to array.
       
   703     // This port number must not already exist in the array.
       
   704     TUsbPortEntity* foundEntity = NULL;
       
   705     TInt foundIndex = GetEntityByPortNumber( aIndex, foundEntity );
       
   706     if ( foundEntity )
       
   707         {
       
   708         FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyConfigAddition() (already exists) complete")) );
       
   709         return KErrAlreadyExists;
       
   710         }
       
   711     // Now either find port with KErrNotFound set as port number or if that is
       
   712     // not found then try to append to array
       
   713     foundIndex = GetFirstFreeEntity( foundEntity );
       
   714     if ( !foundEntity )  // free not found so add new
       
   715         {
       
   716         // Now append the new port to array
       
   717         TUsbPortEntity newEntity;
       
   718         newEntity.iPortNum = aIndex;
       
   719         TInt retTemp = iUsbPorts.Append( newEntity );
       
   720         if ( retTemp != KErrNone )
       
   721             {
       
   722             FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyConfigAddition() (append failed!) complete")) );
       
   723             return KErrGeneral;
       
   724             }
       
   725         // entity not valid here so set now
       
   726         foundEntity = &iUsbPorts[iUsbPorts.Count()-1];
       
   727         }
       
   728     else  // free found so change array
       
   729         {
       
   730         foundEntity->iPortNum = aIndex;
       
   731         }
       
   732     // Open port and create channel for it
       
   733     TInt retTemp = InitOnePort( foundEntity );
       
   734     if ( retTemp != KErrNone )
       
   735         {
       
   736         FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyConfigAddition() (ERROR) complete" )));
       
   737         return KErrGeneral;
       
   738         }
       
   739     FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyConfigAddition() complete")) );
       
   740     return KErrNone;
       
   741     }
       
   742 
       
   743 // ---------------------------------------------------------------------------
       
   744 // From class MDunUsbConfig.
       
   745 // Gets called when one or more ACM configurations are removed
       
   746 // ---------------------------------------------------------------------------
       
   747 //
       
   748 TInt CDunUsbPlugin::NotifyConfigRemoval( TInt aIndex )
       
   749     {
       
   750     FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyConfigRemoval()")) );
       
   751     // Configuration removed so aIndex is the port number to be added to array.
       
   752     // This port number must already exist in the array.
       
   753     TUsbPortEntity* foundEntity = NULL;
       
   754     TInt foundIndex = GetEntityByPortNumber( aIndex, foundEntity );
       
   755     if ( !foundEntity )
       
   756         {
       
   757         FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyConfigRemoval() (not found) complete")) );
       
   758         return KErrNotFound;
       
   759         }
       
   760     // Now free channel and mark as unused
       
   761     iTransporter->FreeChannel( &foundEntity->iUsbPort );
       
   762     foundEntity->iUsbPort.SetSignals( 0, KSignalDCEOutputs );
       
   763     foundEntity->iUsbPort.Close();
       
   764     iUsbPorts[foundIndex].iPortNum = KErrNotFound;
       
   765     FTRACE(FPrint( _L( "CDunUsbPlugin::NotifyConfigRemoval() complete")) );
       
   766     return KErrNone;
       
   767     }
       
   768 
       
   769 // ======== GLOBAL FUNCTIONS ========
       
   770 
       
   771 // ---------------------------------------------------------------------------
       
   772 // NewLocalPluginL implements factory construction for
       
   773 // the class CDunUsbPlugin.
       
   774 // The function is exported at ordinal 1.
       
   775 // Returns: Pointer: The new instance of CDunUsbPlugin
       
   776 // ---------------------------------------------------------------------------
       
   777 //
       
   778 EXPORT_C MDunLocalMediaPlugin* NewLocalPluginL()
       
   779     {
       
   780     return new (ELeave) CDunUsbPlugin;
       
   781     }