--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usbengines/usbdevcon/src/cusbdevcon.cpp Thu Dec 17 09:14:30 2009 +0200
@@ -0,0 +1,419 @@
+/*
+* Copyright (c) 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: Takes control of device&vendor-specific control messages over EP0
+*
+*/
+
+
+#include <usbman.h>
+
+#include "cusbdevcon.h"
+#include "cusbstatewatcher.h"
+#include "crequestshandler.h"
+#include "cstatemachine.h"
+#include "debug.h"
+
+// LITERALS
+_LIT( KUsbDevConName, "UsbDevCon" );
+
+// ---------------------------------------------------------------------------
+// Two-phase construction
+// ---------------------------------------------------------------------------
+//
+CUsbDevCon* CUsbDevCon::NewLC()
+ {
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::NewLC" ) );
+
+ CUsbDevCon* self = new (ELeave) CUsbDevCon();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Two-phase construction
+// ---------------------------------------------------------------------------
+//
+CUsbDevCon* CUsbDevCon::NewL()
+ {
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::NewL" ) );
+
+ CUsbDevCon* self = CUsbDevCon::NewLC();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Two-phase construction
+// ---------------------------------------------------------------------------
+//
+void CUsbDevCon::ConstructL()
+ {
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::ConstructL" ) );
+
+ // usbc
+ User::LeaveIfError(iLdd.Open(0));
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::ConstructL RDevUsbcClient opened OK" ) );
+
+ // usb manager
+ User::LeaveIfError(iUsbManager.Connect());
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::ConstructL RUsb connected OK" ) );
+
+ // usb watcher
+ User::LeaveIfError(iUsbWatcher.Connect());
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::ConstructL RUsbWatcher connected OK" ) );
+
+ // device state watcher
+ iUsbStateWatcher = CUsbStateWatcher::NewL(*this, iLdd);
+
+ // Requests handler
+ iRequestsHandler = CRequestsHandler::NewL(iLdd, iUsbWatcher, iUsbManager);
+
+ // state machine
+ iStateMachine = CStateMachine::NewL(*iRequestsHandler, iLdd);
+
+ User::LeaveIfError(iShutdownTimer.CreateLocal());
+
+ // get usb state, and act accordingly to it
+ TUsbcDeviceState usbcstate(EUsbcDeviceStateUndefined);
+ iLdd.DeviceStatus(usbcstate);
+
+ FTRACE(FPrint(
+ _L("[USBDEVCON]\tCUsbDevCon::ConstructL: Usbc state = %d" ),usbcstate));
+
+ ActAccordinglyToUsbStateL(usbcstate);
+
+ }
+
+// ---------------------------------------------------------------------------
+// Default construction
+// ---------------------------------------------------------------------------
+//
+CUsbDevCon::CUsbDevCon() : CActive(EPriorityStandard),
+ iUsbStateWatcher(0),
+ iStateMachine (0),
+ iRequestsHandler(0),
+ iPrevUsbState(EUsbcDeviceStateUndefined)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+// ---------------------------------------------------------------------------
+// Destruction
+// ---------------------------------------------------------------------------
+//
+CUsbDevCon::~CUsbDevCon()
+ {
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::~CUsbDevCon" ) );
+
+ Cancel();
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::~CUsbDevCon Cancel" ) );
+
+ delete iStateMachine;
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::~CUsbDevCon StateMachine" ) );
+
+ delete iRequestsHandler;
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::~CUsbDevCon RequestsHandler" ) );
+
+ delete iUsbStateWatcher;
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::~CUsbDevCon UsbStateWatcher" ) );
+
+ iUsbWatcher.Close();
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::~CUsbDevCon UsbWatcher" ) );
+
+ iUsbManager.Close();
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::~CUsbDevCon UsbManager" ) );
+
+ iLdd.Close();
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::~CUsbDevCon LDD" ) );
+
+ iShutdownTimer.Close();
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::~CUsbDevCon Timer" ) );
+
+ }
+
+// ---------------------------------------------------------------------------
+// Acts accordingly to USB state
+// ---------------------------------------------------------------------------
+//
+void CUsbDevCon::ActAccordinglyToUsbStateL(TUsbcDeviceState aUsbcState)
+ {
+
+ switch (aUsbcState)
+ {
+ case EUsbcDeviceStateUndefined:
+ {
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::ActAccordinglyToUsbStateL State: Undefined" ) );
+
+ StopL();
+ break;
+ }
+
+ case EUsbcDeviceStateAttached:
+ {
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::ActAccordinglyToUsbStateL State: Attached" ) );
+
+ StartL();
+ break;
+ }
+
+ case EUsbcDeviceStatePowered:
+ {
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::ActAccordinglyToUsbStateL State: Powered" ) );
+
+ StartL();
+ break;
+ }
+
+ case EUsbcDeviceStateDefault:
+ {
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::ActAccordinglyToUsbStateL State: Default" ) );
+
+ StartL();
+ break;
+ }
+
+ case EUsbcDeviceStateAddress:
+ {
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::ActAccordinglyToUsbStateL State: Addressed" ) );
+
+ StartL();
+ break;
+ }
+
+ case EUsbcDeviceStateConfigured:
+ {
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::ActAccordinglyToUsbStateL State: Configured" ) );
+
+ if(iPrevUsbState == EUsbcDeviceStateSuspended)
+ {
+ ResumeL();
+ }
+ else
+ {
+ StartL();
+ }
+
+ break;
+ }
+ case EUsbcDeviceStateSuspended:
+ {
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::ActAccordinglyToUsbStateL State: Suspended" ) );
+
+ break;
+ }
+
+ default:
+ {
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::ActAccordinglyToUsbStateL State: ***Undefined***" ) );
+
+ StopL();
+ break;
+ }
+ }
+
+ iPrevUsbState = aUsbcState;
+
+ // listen to USB states change
+ iUsbStateWatcher->Activate();
+
+ }
+
+ // ---------------------------------------------------------------------------
+// Timer is completed
+// ---------------------------------------------------------------------------
+//
+void CUsbDevCon::RunL()
+ {
+ FTRACE(FPrint(
+ _L("[USBDEVCON]\tCUsbDevCon::RunL: iStatus = %d" ),iStatus.Int()));
+
+ if(KErrNone == iStatus.Int())
+ {
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::RunL Exiting usbdevcon" ) );
+
+ // Shutdown timer is finished, exit program
+ CUsbDevCon:: ~CUsbDevCon(); // destruct resources
+ User::Exit(KErrNone);
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Cancellation
+// ---------------------------------------------------------------------------
+//
+void CUsbDevCon::DoCancel()
+ {
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::DoCancel" ) )
+ iShutdownTimer.Cancel();
+ }
+
+// ----------------------------------------------------------------------------
+// Standard active object error function.
+// ----------------------------------------------------------------------------
+//
+TInt CUsbDevCon::RunError( TInt /*aError*/ )
+ {
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// Starts UsbDevCon services
+// ---------------------------------------------------------------------------
+//
+void CUsbDevCon::StartL()
+ {
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::StartL" ) );
+
+ if(!iStateMachine->IsStarted())
+ {
+ // set device control
+ User::LeaveIfError(iLdd.SetDeviceControl());
+
+ // start state machine
+ iStateMachine->Start();
+
+ }
+
+ // Cancel shutdown timer, if it is started
+ iShutdownTimer.Cancel();
+ }
+
+// ---------------------------------------------------------------------------
+// Stops UsbDevCon services
+// ---------------------------------------------------------------------------
+//
+void CUsbDevCon::StopL()
+ {
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::StopL" ) );
+
+ if(iStateMachine->IsStarted())
+ {
+
+ // stop state machine
+ iStateMachine->Stop();
+
+ // release device control
+ User::LeaveIfError(iLdd.ReleaseDeviceControl());
+
+ }
+
+ if(!IsActive()) // not waiting for timer
+ {
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::StopL Starting timer" ) );
+ // run timer
+ iShutdownTimer.Cancel();
+
+ // RunL will be called after KInactiveTimeForShutDown milliseconds
+ iShutdownTimer.After(iStatus, TTimeIntervalMicroSeconds32(KInactiveTimeForShutDown));
+ SetActive();
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::StopL Timer is started" ) );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Resumes UsbDevCon services
+// ---------------------------------------------------------------------------
+//
+void CUsbDevCon::ResumeL()
+ {
+
+ FLOG( _L( "[USBDEVCON]\tCUsbDevCon::ResumeL" ) );
+
+ // Resume state machine
+ StartL();
+
+ }
+
+// ----------------------------------------------------------------------------
+// Constructs and installs the active scheduler, constructs UsbDevCon object.
+// ----------------------------------------------------------------------------
+//
+static void StartUsbDevConL()
+ {
+
+ FLOG( _L( "[USBDEVCON]\tStartUsbDevConL" ) );
+
+ // Construct and install the active scheduler
+ CActiveScheduler *myScheduler = new ( ELeave ) CActiveScheduler();
+
+ // Push onto the cleanup stack
+ CleanupStack::PushL( myScheduler );
+
+ // Install as the active scheduler
+ CActiveScheduler::Install( myScheduler );
+
+ CUsbDevCon* instance = CUsbDevCon::NewLC();
+
+ RProcess::Rendezvous(KErrNone); // signal to starter process, that usbdevcon started OK or failed to start
+
+ FLOG( _L( "[USBDEVCON]\tStartUsbDevConL Usbdevcon is started successfully" ) );
+
+ // returns only when UsbDevCon closing
+ CActiveScheduler::Start();
+
+ CleanupStack::PopAndDestroy( instance );
+ CleanupStack::PopAndDestroy( myScheduler );
+ }
+
+// ---------------------------------------------------------------------------
+// Main function of the application executable.
+// ---------------------------------------------------------------------------
+//
+GLDEF_C TInt E32Main()
+ {
+ TInt err;
+
+ // rename the thread so it is easy to find the panic application
+ err = User::RenameThread(KUsbDevConName);
+
+ if(KErrNone != err)
+ {
+ return err;
+ }
+
+ __UHEAP_MARK;
+
+ // create clean-up stack
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+
+ TRAP( err, StartUsbDevConL() );
+
+ delete cleanup; // destroy clean-up stack
+ __UHEAP_MARKEND;
+
+ return err;
+ }
+
+
+