/*
* Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/

#include <usb/usblogger.h>
#include "cusbhost.h"
#include "OstTraceDefinitions.h"
#ifdef OST_TRACE_COMPILER_IN_USE
#include "cusbhostTraces.h"
#endif


CUsbHost* CUsbHost::iInstance = 0;

CUsbHost* CUsbHost::NewL()
	{
	if(iInstance == 0)
		{
		iInstance = new (ELeave) CUsbHost();		
		CleanupStack::PushL(iInstance);		
		iInstance->ConstructL();		
		CleanupStack::Pop(iInstance);
		}	
	return iInstance;
	}

CUsbHost::~CUsbHost()
	{
    OstTraceFunctionEntry0( CUSBHOST_CUSBHOST_DES_ENTRY );

	Stop();

	TInt i =0;
	for(i=0;i<ENumMonitor;i++)
		{
		delete iUsbHostWatcher[i];
		iUsbHostWatcher[i] = NULL;
		}
	iObservers.Close();
	iInstance = 0;
	OstTraceFunctionExit0( CUSBHOST_CUSBHOST_DES_EXIT );
	}

CUsbHost::CUsbHost()
	{
    OstTraceFunctionEntry0( CUSBHOST_CUSBHOST_CONS_ENTRY );
	OstTraceFunctionExit0( CUSBHOST_CUSBHOST_CONS_EXIT );
	}

void CUsbHost::ConstructL()
	{
    OstTraceFunctionEntry0( CUSBHOST_CONSTRUCTL_ENTRY );

	iUsbHostWatcher[EHostEventMonitor] = 
			CActiveUsbHostEventWatcher::NewL(iUsbHostStack,*this,iHostEventInfo);
	iUsbHostWatcher[EHostMessageMonitor] = 
			CActiveUsbHostMessageWatcher::NewL(iUsbHostStack,*this,iHostMessage);
	OstTraceFunctionExit0( CUSBHOST_CONSTRUCTL_EXIT );
	}
void CUsbHost::StartL()
	{
	OstTraceFunctionEntry0( CUSBHOST_STARTL_ENTRY );

	if(!iHasBeenStarted)
		{
		TInt err = iUsbHostStack.Connect();
		if(err < 0)
		    {
            OstTrace1( TRACE_NORMAL, CUSBHOST_STARTL, "CUsbHost::StartL; iUsbHostStack.Connect() error. Leave error=%d", err );
            User::Leave(err);
		    }

		for(TInt i=0;i<ENumMonitor;i++)
			{
			iUsbHostWatcher[i]->Post();
			}
		iHasBeenStarted = ETrue;
		}
	OstTraceFunctionExit0( CUSBHOST_STARTL_EXIT );
	}

void CUsbHost::Stop()
	{
	OstTraceFunctionEntry0( CUSBHOST_STOP_ENTRY );

	TInt i=0;
	for(i=0;i<ENumMonitor;i++)
		{
		if (iUsbHostWatcher[i])
			{
			iUsbHostWatcher[i]->Cancel();
			}
		}

	iUsbHostStack.Close();

	iHasBeenStarted = EFalse;
	OstTraceFunctionExit0( CUSBHOST_STOP_EXIT );
	}

void CUsbHost::RegisterObserverL(MUsbOtgHostNotifyObserver& aObserver)
	{
	OstTraceFunctionEntry0( CUSBHOST_REGISTEROBSERVERL_ENTRY );

	iObservers.AppendL(&aObserver);
	UpdateNumOfObservers();
	OstTraceFunctionExit0( CUSBHOST_REGISTEROBSERVERL_EXIT );
	}

void CUsbHost::DeregisterObserver(MUsbOtgHostNotifyObserver& aObserver)
	{
	OstTraceFunctionEntry0( CUSBHOST_DEREGISTEROBSERVER_ENTRY );
	TInt index = iObservers.Find(&aObserver);
	if(index == KErrNotFound)
		{
        OstTrace0( TRACE_NORMAL, CUSBHOST_DEREGISTEROBSERVER, "CUsbHost::DeregisterObserver;  Cannot remove observer, not found" );
		}
	else
		{
		iObservers.Remove(index);
		}

	UpdateNumOfObservers();
	OstTraceFunctionExit0( CUSBHOST_DEREGISTEROBSERVER_EXIT );
	}

TInt CUsbHost::GetSupportedLanguages(TUint aDeviceId,RArray<TUint>& aLangIds)
	{
	OstTraceFunctionEntry0( CUSBHOST_GETSUPPORTEDLANGUAGES_ENTRY );
	TInt err = KErrNone;
	if ( iUsbHostStack.Handle() )
		{
		err = iUsbHostStack.GetSupportedLanguages(aDeviceId,aLangIds);
		}
	else
		{
		err = KErrBadHandle;
		}
	OstTraceFunctionExit0( CUSBHOST_GETSUPPORTEDLANGUAGES_EXIT );
	return err;
	}

TInt CUsbHost::GetManufacturerStringDescriptor(TUint aDeviceId,TUint aLangId,TName& aString)
	{
	OstTraceFunctionEntry0( CUSBHOST_GETMANUFACTURERSTRINGDESCRIPTOR_ENTRY );
	TInt err = KErrNone;
	if ( iUsbHostStack.Handle() )
		{
		err = iUsbHostStack.GetManufacturerStringDescriptor(aDeviceId,aLangId,aString);
		}
	else
		{
		err = KErrBadHandle;
		}
	OstTraceFunctionExit0( CUSBHOST_GETMANUFACTURERSTRINGDESCRIPTOR_EXIT );
	return err;
	}

TInt CUsbHost::GetProductStringDescriptor(TUint aDeviceId,TUint aLangId,TName& aString)
	{
	OstTraceFunctionEntry0( CUSBHOST_GETPRODUCTSTRINGDESCRIPTOR_ENTRY );
	TInt err = KErrNone;
	if ( iUsbHostStack.Handle() )
		{
		err = iUsbHostStack.GetProductStringDescriptor(aDeviceId,aLangId,aString);
		}
	else
		{
		err = KErrBadHandle;
		}
	OstTraceFunctionExit0( CUSBHOST_GETPRODUCTSTRINGDESCRIPTOR_EXIT );
	return err;
	}

TInt CUsbHost::GetOtgDescriptor(TUint aDeviceId, TOtgDescriptor& otgDescriptor)
	{
	OstTraceFunctionEntry0( CUSBHOST_GETOTGDESCRIPTOR_ENTRY );
	
	TInt err(KErrNone);
	
	if (iUsbHostStack.Handle())
		{
		err = iUsbHostStack.GetOtgDescriptor(aDeviceId, otgDescriptor);
		}
	else
		{
		err = KErrBadHandle;
		}
	
	OstTraceFunctionExit0( CUSBHOST_GETOTGDESCRIPTOR_EXIT );
	return err;
	}

void CUsbHost::NotifyHostEvent(TUint aWatcherId)
	{
    OstTraceFunctionEntry0( CUSBHOST_NOTIFYHOSTEVENT_ENTRY );

	if(aWatcherId == EHostEventMonitor)
		{
		OstTrace1( TRACE_NORMAL, CUSBHOST_NOTIFYHOSTEVENT, "CUsbHost::NotifyHostEvent;DeviceId=%d", iHostEventInfo.iDeviceId );
		OstTrace1( TRACE_NORMAL, CUSBHOST_NOTIFYHOSTEVENT_DUP1, "CUsbHost::NotifyHostEvent;iEventType=%d", iHostEventInfo.iEventType );
		OstTrace1( TRACE_NORMAL, CUSBHOST_NOTIFYHOSTEVENT_DUP2, "CUsbHost::NotifyHostEvent;TDriverLoadStatus=%d", iHostEventInfo.iDriverLoadStatus );
		OstTrace1( TRACE_NORMAL, CUSBHOST_NOTIFYHOSTEVENT_DUP3, "CUsbHost::NotifyHostEvent;VID=%d", iHostEventInfo.iVid );
		OstTrace1( TRACE_NORMAL, CUSBHOST_NOTIFYHOSTEVENT_DUP4, "CUsbHost::NotifyHostEvent;Pid=%d", iHostEventInfo.iPid );

		for(TUint i=0;i<iNumOfObservers;i++)
			{
			iObservers[i]->UsbHostEvent(iHostEventInfo);
			}
		}
	else
		{
		OstTrace1( TRACE_NORMAL, CUSBHOST_NOTIFYHOSTEVENT_DUP5, "CUsbHost::NotifyHostEvent;Host Message=%d", iHostMessage );
		
		for(TUint i=0;i<iNumOfObservers;i++)
			{
			iObservers[i]->UsbOtgHostMessage(iHostMessage);
			}
		}
	OstTraceFunctionExit0( CUSBHOST_NOTIFYHOSTEVENT_EXIT );
	}

void CUsbHost::UpdateNumOfObservers()
	{
	OstTraceFunctionEntry0( CUSBHOST_UPDATENUMOFOBSERVERS_ENTRY );
	iNumOfObservers = iObservers.Count();
	OstTraceFunctionExit0( CUSBHOST_UPDATENUMOFOBSERVERS_EXIT );
	}

TInt CUsbHost::EnableDriverLoading()
	{
	OstTraceFunctionEntry0( CUSBHOST_ENABLEDRIVERLOADING_ENTRY );
	TInt err = KErrNone;
	if ( iUsbHostStack.Handle() )
		{
		err = iUsbHostStack.EnableDriverLoading();
		}
	else
		{
		err = KErrBadHandle;
		}
	OstTraceFunctionExit0( CUSBHOST_ENABLEDRIVERLOADING_EXIT );
	return err;
	}

void CUsbHost::DisableDriverLoading()
	{
	OstTraceFunctionEntry0( CUSBHOST_DISABLEDRIVERLOADING_ENTRY );
	if ( iUsbHostStack.Handle() )
		{
		iUsbHostStack.DisableDriverLoading();
		}
	OstTraceFunctionExit0( CUSBHOST_DISABLEDRIVERLOADING_EXIT );
	}
