usbmgmt/usbmgr/host/fdf/production/server/src/deviceproxy.cpp
changeset 0 c9bc50fca66e
child 29 59aa7d6e3e0f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbmgmt/usbmgr/host/fdf/production/server/src/deviceproxy.cpp	Tue Feb 02 02:02:59 2010 +0200
@@ -0,0 +1,444 @@
+/*
+* Copyright (c) 2007-2009 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:
+*
+*/
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include "deviceproxy.h"
+#include <usb/usblogger.h>
+#include <usbhostdefs.h>
+#include "utils.h"
+#include "event.h"
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, "fdf      ");
+#endif
+
+#ifdef _DEBUG
+PANICCATEGORY("devproxy");
+#endif
+
+#ifdef __FLOG_ACTIVE
+#define LOG Log()
+#else
+#define LOG
+#endif
+
+CDeviceProxy* CDeviceProxy::NewL(RUsbHubDriver& aHubDriver, TUint aDeviceId)
+	{
+	LOG_STATIC_FUNC_ENTRY
+
+	CDeviceProxy* self = new(ELeave) CDeviceProxy(aDeviceId);
+	CleanupStack::PushL(self);
+	self->ConstructL(aHubDriver);
+	CLEANUPSTACK_POP1(self);
+	return self;
+	}
+
+CDeviceProxy::CDeviceProxy(TUint aDeviceId)
+:	iId(aDeviceId)
+	{
+	LOG_FUNC
+	}
+
+void CDeviceProxy::ConstructL(RUsbHubDriver& aHubDriver)
+	{
+	LOG_FUNC
+
+	LEAVEIFERRORL(iHandle.Open(aHubDriver, iId));
+
+	// Pre-allocate objects relating to this device for the event queue.
+	iAttachmentEvent = new(ELeave) TDeviceEvent;
+	iAttachmentEvent->iInfo.iEventType = EDeviceAttachment;
+	iAttachmentEvent->iInfo.iDeviceId = iId;
+
+	iDriverLoadingEvent = new(ELeave) TDeviceEvent;
+	iDriverLoadingEvent->iInfo.iEventType = EDriverLoad;
+	iDriverLoadingEvent->iInfo.iDeviceId = iId;
+
+	iDetachmentEvent = new(ELeave) TDeviceEvent;
+	iDetachmentEvent->iInfo.iEventType = EDeviceDetachment;
+	iDetachmentEvent->iInfo.iDeviceId = iId;
+	
+	ReadStringDescriptorsL();
+
+	LOG;
+	}
+
+void CDeviceProxy::ReadStringDescriptorsL()
+	{
+	LOG_FUNC
+
+	// wait 10 ms before reading any string descriptors
+	// to avoid IOP issues with some USB devices (e.g. PNY Attache)
+	User::After(10000);
+
+	// First read string descriptor 0 (supported languages).
+	// For each supported language, read the manufacturer, product and serial
+	// number string descriptors (as supported). (These are not cached in
+	// USBD.)
+	// To look up these string descriptors we need to get the device
+	// descriptor. The device descriptor *is* cached in USBD, so we don't
+	// remember our own copy, even though it is queried later by the CFdf.
+
+	// '0' is the index of the string descriptor which holds the supported
+	// language IDs.
+	TBuf8<256> stringBuf;
+	TUsbStringDescriptor* stringDesc = NULL;
+	ASSERT_DEBUG(iHandle.Handle());
+	LEAVEIFERRORL(iHandle.GetStringDescriptor(stringDesc, stringBuf, 0));
+	CleanupStack::PushL(*stringDesc);
+
+	// Copy the language IDs into our array.
+	TUint index = 0;
+	TInt16 langId = stringDesc->GetLangId(index);
+	while ( langId != KErrNotFound )
+		{
+		LOGTEXT2(_L8("\tsupported language: 0x%04x"), langId);
+		iLangIds.AppendL(langId); // stored as TUint
+		++index;
+		langId = stringDesc->GetLangId(index);
+		}
+
+	CleanupStack::PopAndDestroy(stringDesc);
+
+	// Get the actual strings for each supported language.
+	TUsbDeviceDescriptor deviceDescriptor;
+	ASSERT_DEBUG(iHandle.Handle());
+	LEAVEIFERRORL(iHandle.GetDeviceDescriptor(deviceDescriptor));
+	TUint8 manufacturerStringDescriptorIndex = deviceDescriptor.ManufacturerIndex();
+	TUint8 productStringDescriptorIndex = deviceDescriptor.ProductIndex();
+	TUint8 serialNumberStringDescriptorIndex = deviceDescriptor.SerialNumberIndex();
+	PopulateStringDescriptorsL(manufacturerStringDescriptorIndex, iManufacturerStrings);
+	PopulateStringDescriptorsL(productStringDescriptorIndex, iProductStrings);
+	PopulateStringDescriptorsL(serialNumberStringDescriptorIndex, iSerialNumberStrings);
+	ASSERT_DEBUG(iManufacturerStrings.Count() == iLangIds.Count());
+	ASSERT_DEBUG(iProductStrings.Count() == iLangIds.Count());
+	ASSERT_DEBUG(iSerialNumberStrings.Count() == iLangIds.Count());
+	}
+
+// Populates the given array with the supported language variants of the given
+// string. Can only leave with KErrNoMemory, which fails instantiation of the
+// CDeviceProxy. (It is legal for instance for manufacturer strings to be
+// supported but serial number strings to *not* be.)
+void CDeviceProxy::PopulateStringDescriptorsL(TUint8 aStringDescriptorIndex, RArray<TName>& aStringArray)
+	{
+	LOG_FUNC
+
+	const TUint langCount = iLangIds.Count();
+	for ( TUint ii = 0 ; ii < langCount ; ++ii )
+		{
+		TName string;
+		TRAPD(err, GetStringDescriptorFromUsbdL(iLangIds[ii], string, aStringDescriptorIndex));
+		if ( err == KErrNotFound)
+			{
+			// Make sure the string is blanked before storing it.
+			string = KNullDesC();
+			}
+		else
+			{
+			LEAVEIFERRORL(err);
+			}
+
+		LEAVEIFERRORL(aStringArray.Append(string));
+		}
+	}
+
+CDeviceProxy::~CDeviceProxy()
+	{
+	LOG_FUNC
+	LOG;
+
+	// In the design, the event objects should all have had ownership taken
+	// onto the event queue by now. The owner of the device proxy is required
+	// to take ownership of these objects before destroying the proxy.
+	// However, we might hit the destructor due to an out-of-memory failure
+	// during construction, so we can't assert this, and we still have to
+	// destroy the objects.
+	delete iAttachmentEvent;
+	delete iDriverLoadingEvent;
+	delete iDetachmentEvent;
+	delete iOtgDescriptor;
+
+	iLangIds.Reset();
+	iManufacturerStrings.Reset();
+	iProductStrings.Reset();
+	iSerialNumberStrings.Reset();
+
+	iHandle.Close();
+	}
+
+TInt CDeviceProxy::GetDeviceDescriptor(TUsbDeviceDescriptor& aDescriptor)
+	{
+	LOG_FUNC
+
+	ASSERT_DEBUG(iHandle.Handle());
+	TInt err = iHandle.GetDeviceDescriptor(aDescriptor);
+
+	LOGTEXT2(_L8("\terr = %d"), err);
+	return err;
+	}
+
+TInt CDeviceProxy::GetConfigurationDescriptor(TUsbConfigurationDescriptor& aDescriptor) const
+	{
+	LOG_FUNC
+
+	ASSERT_DEBUG(iHandle.Handle());
+	TInt err = const_cast<RUsbDevice&>(iHandle).GetConfigurationDescriptor(aDescriptor);
+
+	LOGTEXT2(_L8("\terr = %d"), err);
+	return err;
+	}
+
+TInt CDeviceProxy::GetTokenForInterface(TUint aIndex, TUint32& aToken) const
+	{
+	LOG_FUNC
+
+	ASSERT_DEBUG(iHandle.Handle());
+	// We shouldn't need to worry about whether the device is suspended or
+	// resumed before doing this. This function is only called if we find FDs
+	// for the device, in which case we wouldn't have suspended it in the
+	// first place.
+	TInt err = const_cast<RUsbDevice&>(iHandle).GetTokenForInterface(aIndex, aToken);
+
+	LOGTEXT2(_L8("\terr = %d"), err);
+	return err;
+	}
+
+const RArray<TUint>& CDeviceProxy::GetSupportedLanguages() const
+	{
+	LOG_FUNC
+
+	return iLangIds;
+	}
+
+void CDeviceProxy::GetManufacturerStringDescriptorL(TUint32 aLangId, TName& aString) const
+	{
+	LOG_FUNC
+
+	GetStringDescriptorFromCacheL(aLangId, aString, iManufacturerStrings);
+	}
+
+void CDeviceProxy::GetProductStringDescriptorL(TUint32 aLangId, TName& aString) const
+	{
+	LOG_FUNC
+
+	GetStringDescriptorFromCacheL(aLangId, aString, iProductStrings);
+	}
+
+void CDeviceProxy::GetSerialNumberStringDescriptorL(TUint32 aLangId, TName& aString) const
+	{
+	LOG_FUNC
+
+	GetStringDescriptorFromCacheL(aLangId, aString, iSerialNumberStrings);
+	}
+
+void CDeviceProxy::GetOtgDescriptorL(TOtgDescriptor& aDescriptor) const
+	{
+	LOG_FUNC
+	
+	if (iOtgDescriptor)
+		{
+		aDescriptor = *iOtgDescriptor;
+		}
+	else
+		{
+		LEAVEL(KErrNotSupported);
+		}
+	}
+
+void CDeviceProxy::SetOtgDescriptorL(const TUsbOTGDescriptor& aDescriptor)
+	{
+	if (iOtgDescriptor)
+		{
+		delete iOtgDescriptor;
+		iOtgDescriptor = NULL;
+		}
+	iOtgDescriptor = new (ELeave) TOtgDescriptor();
+
+	iOtgDescriptor->iDeviceId = iId;
+	iOtgDescriptor->iAttributes = aDescriptor.Attributes();
+	}
+
+// Used during instantiation to read supported strings.
+void CDeviceProxy::GetStringDescriptorFromUsbdL(TUint32 aLangId, TName& aString, TUint8 aStringDescriptorIndex) const
+	{
+	LOG_FUNC
+	LOGTEXT3(_L8("\taLangId = 0x%04x, aStringDescriptorIndex = %d"), aLangId, aStringDescriptorIndex);
+
+	// If the string is not defined by the device, leave.
+	if ( aStringDescriptorIndex == 0 )
+		{
+		LEAVEL(KErrNotFound);
+		}
+
+	TBuf8<255> stringBuf;
+	TUsbStringDescriptor* stringDesc = NULL;
+	ASSERT_DEBUG(iHandle.Handle());
+	LEAVEIFERRORL(const_cast<RUsbDevice&>(iHandle).GetStringDescriptor(stringDesc, stringBuf, aStringDescriptorIndex, aLangId));
+	stringDesc->StringData(aString);
+	stringDesc->DestroyTree();
+	delete stringDesc;
+	LOGTEXT2(_L("\taString = \"%S\""), &aString);
+	}
+
+// Called indirectly by users of this class to query a string descriptor.
+void CDeviceProxy::GetStringDescriptorFromCacheL(TUint32 aLangId, TName& aString, const RArray<TName>& aStringArray) const
+	{
+	LOG_FUNC
+	LOGTEXT2(_L8("\taLangId = 0x%04x"), aLangId);
+
+	// If the lang ID is not supported by the device, leave. At the same time
+	// find the index of the required string in the given string array.
+	const TUint langCount = iLangIds.Count();
+	TUint index = 0;
+	for ( index = 0 ; index < langCount ; ++index )
+		{
+		if ( iLangIds[index] == aLangId )
+			{
+			break;
+			}
+		}
+	if ( index == langCount )
+		{
+		LEAVEL(KErrNotFound);
+		}
+
+	aString = aStringArray[index];
+	LOGTEXT2(_L("\taString = \"%S\""), &aString);
+	}
+
+TInt CDeviceProxy::Suspend()
+	{
+	LOG_FUNC
+
+	ASSERT_DEBUG(iHandle.Handle());
+	TInt ret = iHandle.Suspend();
+
+	LOGTEXT2(_L8("\tret = %d"), ret);
+	return ret;
+	}
+
+TUint CDeviceProxy::DeviceId() const
+	{
+	return iId;
+	}
+
+void CDeviceProxy::SetDriverLoadingEventData(TDriverLoadStatus aStatus, TInt aError)
+	{
+	LOG_FUNC
+	LOGTEXT3(_L8("\taStatus = %d, aError = %d"), aStatus, aError);
+
+	ASSERT_DEBUG(iDriverLoadingEvent);
+	iDriverLoadingEvent->iInfo.iDriverLoadStatus = aStatus;
+	iDriverLoadingEvent->iInfo.iError = aError;
+
+	LOG;
+	}
+
+TDeviceEvent* CDeviceProxy::GetAttachmentEventObject()
+	{
+	LOG_FUNC
+	LOG;
+
+	ASSERT_DEBUG(iAttachmentEvent);
+	TDeviceEvent* const obj = iAttachmentEvent;
+	iAttachmentEvent = NULL;
+	LOGTEXT2(_L8("\tobj = 0x%08x"), obj);
+	return obj;
+	}
+
+TDeviceEvent* CDeviceProxy::GetDriverLoadingEventObject()
+	{
+	LOG_FUNC
+	LOG;
+
+	ASSERT_DEBUG(iDriverLoadingEvent);
+	TDeviceEvent* const obj = iDriverLoadingEvent;
+	iDriverLoadingEvent = NULL;
+	LOGTEXT2(_L8("\tobj = 0x%08x"), obj);
+	return obj;
+	}
+
+TDeviceEvent* CDeviceProxy::GetDetachmentEventObject()
+	{
+	LOG_FUNC
+	LOG;
+
+	ASSERT_DEBUG(iDetachmentEvent);
+	TDeviceEvent* const obj = iDetachmentEvent;
+	iDetachmentEvent = NULL;
+	LOGTEXT2(_L8("\tobj = 0x%08x"), obj);
+	return obj;
+	}
+
+#ifdef __FLOG_ACTIVE
+
+void CDeviceProxy::Log()
+	{
+	LOG_FUNC
+
+	LOGTEXT2(_L8("\tiId = %d"), iId);
+	LOGTEXT2(_L8("\tiHandle.Handle() = %d"), iHandle.Handle());
+	if ( iAttachmentEvent )
+		{
+		LOGTEXT(_L8("\tlogging iAttachmentEvent"));
+		iAttachmentEvent->Log();
+		}
+	if ( iDriverLoadingEvent )
+		{
+		LOGTEXT(_L8("\tlogging iDriverLoadingEvent"));
+		iDriverLoadingEvent->Log();
+		}
+	if ( iDetachmentEvent )
+		{
+		LOGTEXT(_L8("\tlogging iDetachmentEvent"));
+		iDetachmentEvent->Log();
+		}
+	const TUint langCount = iLangIds.Count();
+	const TUint manufacturerCount = iManufacturerStrings.Count();
+	const TUint productCount = iProductStrings.Count();
+	const TUint serialNumberCount = iSerialNumberStrings.Count();
+
+	// from the code below we can see that some protection have been added
+	// if(ii<manufacturerCount) etc...
+	// This has been done to protect in case there have been an incomplete construction etc..
+	// when logging the data
+
+	LOGTEXT2(_L8("\tlangCount = %d"), langCount);
+	for ( TUint ii = 0 ; ii < langCount ; ++ii )
+		{
+		LOGTEXT2(_L("\tlang ID 0x%04x:"), iLangIds[ii]);
+		if(ii<manufacturerCount)
+			{
+			LOGTEXT2(_L("\t\tmanufacturer string: \"%S\""), &iManufacturerStrings[ii]);
+			}
+		if(ii<productCount)
+			{
+			LOGTEXT2(_L("\t\tproduct string: \"%S\""), &iProductStrings[ii]);
+			}
+		if(ii<serialNumberCount)
+			{
+			LOGTEXT2(_L("\t\tserial number string: \"%S\""), &iSerialNumberStrings[ii]);
+			}
+
+		}
+	}
+
+#endif