diff -r 000000000000 -r a41df078684a kernel/eka/include/d32usbdi_hubdriver.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/include/d32usbdi_hubdriver.inl Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,442 @@ +// 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 the License "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 + + The driver's name + + @return The name of the driver + + @internalComponent +*/ +inline const TDesC& RUsbHubDriver::Name() + { + _LIT(KDriverName,"USBHUBDRIVER"); + return KDriverName; + } + +/** + The driver's version + + @return The version number of the driver +*/ +inline TVersion RUsbHubDriver::VersionRequired() + { + const TInt KMajorVersionNumber=1; + const TInt KMinorVersionNumber=0; + const TInt KBuildVersionNumber=KE32BuildVersionNumber; + return TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); + } + + +#ifndef __KERNEL_MODE__ + +/** +Open a handle to the host controller. +@return System-wide error code giving status of connection attempt. +*/ +TInt RUsbHubDriver::Open() + { + TInt rc = KErrNone; + + // Check to see if this object has already been opened - if it has, + // there will be a handle set. + + if ( Handle() ) + { + User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverAlreadyOpened); + } + + rc = DoCreate(Name(),VersionRequired(),KNullUnit,NULL,NULL,EOwnerThread); + + if ( rc != KErrNone ) + { + RDebug::Print(_L("********************************")); + RDebug::Print(_L("* RUsbHubDriver::Open() Fault! *")); + RDebug::Print(_L("********************************")); + } + + return rc; + } + + +/** +Start the host stack. +*/ +TInt RUsbHubDriver::StartHost() + { + return DoControl(EStartHost); + } + + +/** +Stop the host stack. +*/ +void RUsbHubDriver::StopHost() + { + DoControl(EStopHost); + } + + +/** +Wait for a bus event. These include device attachments and detachments. +@see TBusEvent +@param aEvent The details of the event that occured, filled in when the request completes. +@param aStatus Completed when an event occurs +*/ +void RUsbHubDriver::WaitForBusEvent(TBusEvent& aEvent, TRequestStatus& aStatus) + { + DoRequest(EWaitForBusEvent, aStatus, &aEvent); + } + + +/** +Cancel a request to wait for bus events. +*/ +void RUsbHubDriver::CancelWaitForBusEvent() + { + DoCancel(ECancelWaitForBusEvent); + } + + +RUsbDevice::RUsbDevice() + : iHeadDeviceDescriptor(NULL) + , iHeadConfDescriptor(NULL) + , iConfigurationDescriptorData(NULL) + , iHub(NULL) + , iHandle(0) + { + } + +/** +Open a handle to a device. +*/ +TInt RUsbDevice::Open(RUsbHubDriver& aHub, TUint aHandle) + { + if(iHandle) + { + return KErrInUse; + } + + TInt err; + err = aHub.DoControl(EOpen, (TAny*)aHandle); + + + if (err == KErrNone) + { + iHub = &aHub; + iHandle = aHandle; + } + else + { + return err; + } + + TRAP(err, GetLocalDescriptorsL()); + // GetLocalDescriptorsL should roll back iHandle etc on error. + __ASSERT_DEBUG(err == KErrNone || !iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverNoRollBackAfterFailedDeviceOpen)); + + return err; + } + +void RUsbDevice::GetLocalDescriptorsL() + { + CleanupClosePushL(*this); // Ensure that we roll back to closed on error. + + // Get Device Descriptor Data. + User::LeaveIfError(GetDeviceDescriptor(iDeviceDescriptorData)); + + // Get Configuration Descriptor Data + TInt configSize = 0; + User::LeaveIfError(GetConfigurationDescriptorSize(configSize)); + + iConfigurationDescriptorData = HBufC8::NewL(configSize); + TPtr8 ptr = iConfigurationDescriptorData->Des(); + User::LeaveIfError(GetConfigurationDescriptor(ptr)); + + + TUsbGenericDescriptor* parsed = NULL; + + // Parse Device Descriptor + User::LeaveIfError(UsbDescriptorParser::Parse(iDeviceDescriptorData, parsed)); + iHeadDeviceDescriptor = TUsbDeviceDescriptor::Cast(parsed); + if(!iHeadDeviceDescriptor) + { + User::Leave(KErrCorrupt); + } + + // Parse Configuration Descriptor + User::LeaveIfError(UsbDescriptorParser::Parse(*iConfigurationDescriptorData, parsed)); + iHeadConfDescriptor = TUsbConfigurationDescriptor::Cast(parsed); + if(!iHeadConfDescriptor) + { + User::Leave(KErrCorrupt); + } + + CleanupStack::Pop(); // this + } + + +/** +Close a handle to a device. +*/ +void RUsbDevice::Close() + { + if(iHub) + { + iHub->DoControl(EClose, (TAny*)iHandle); + } + + if(iHeadConfDescriptor) + { + iHeadConfDescriptor->DestroyTree(); + delete iHeadConfDescriptor; + iHeadConfDescriptor = NULL; + } + + if(iHeadDeviceDescriptor) + { + iHeadDeviceDescriptor->DestroyTree(); + delete iHeadDeviceDescriptor; + iHeadDeviceDescriptor = NULL; + } + + delete iConfigurationDescriptorData; + iConfigurationDescriptorData = NULL; + + iHub = NULL; + iHandle = 0; + } + + +/** +Return the handle to a device +*/ +TUint RUsbDevice::Handle() const + { + return iHandle; + } + + +/** +Places the device into a suspended state. +*/ +TInt RUsbDevice::Suspend() + { + __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); + __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); + return iHub->DoControl(ESuspend, (TAny*)iHandle); + } + + +/** +Resumes the device from a suspended state. +*/ +TInt RUsbDevice::Resume() + { + __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); + __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); + return iHub->DoControl(EResume, (TAny*)iHandle); + } + + +TInt RUsbDevice::GetStringDescriptor(TDes8& aStringDescriptor, TInt aIndex, TInt aLangId) + { + __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); + __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); + __ASSERT_ALWAYS(aStringDescriptor.MaxLength() >= 255, + User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverInsufficientSizeToHoldStringDescriptor)); + + aStringDescriptor.Zero(); + + TStringDescParams stringDescParams; + stringDescParams.iTarget = &aStringDescriptor; + stringDescParams.iIndex = aIndex; + stringDescParams.iLangId = aLangId; + + return iHub->DoControl(EGetStringDescriptor, (TAny*)iHandle, &stringDescParams); + } + + +/** +Return a token which may be used to uniquely identify the supplied interface on this device. The returned +token may then be passed to a function driver, to allow it to open the required interface. + +@param [in] aInterfaceNumber Interface to return a token for. +@param [out] aToken The token assigned to the interface. +@return System wide error code, for instance KErrNotFound if the supplied interface number is unknown. +*/ +TInt RUsbDevice::GetTokenForInterface(TInt aInterfaceNumber, TUint32& aToken) + { + __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); + __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); + + TInterfaceTokenParameters params; + params.iInterfaceNumber = aInterfaceNumber; + params.iToken = &aToken; + + return iHub->DoControl(EGetInterfaceToken, (TAny*)iHandle, ¶ms); + } + +/** +Queues an asynchronous request for changes in the state of the device represented by this handle. + +@param [out] aNewState The new state of the device +@param [out] aRequest The request status completed when a state change has occured. +*/ +void RUsbDevice::QueueDeviceStateChangeNotification(TDeviceState& aNewState, TRequestStatus& aRequest) + { + __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); + __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); + iHub->DoRequest(EDeviceStateChange, aRequest, (TAny*)iHandle, &aNewState); + } + + +/** +Cancels an outstanding request for device state changes +@see QueueDeviceStateChangeNotification +*/ +void RUsbDevice::CancelDeviceStateChangeNotification() + { + __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); + __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); + iHub->DoControl(ECancelDeviceStateChange, (TAny*)iHandle); + } + + +/** +Return the USB Device Descriptor for this device. + +Note: the supplied TUsbDeviceDescriptor is owned by the caller, but any descriptor objects linked to it +remain the property of the RUsbDevice object. Memory leaks will result if the head pointer is not +cleaned up, but the pointed to objects should not be destroyed. + +@param [out] aDescriptor The supplied TUsbDeviceDescriptor object will be populated from the data retrieved from the +device. + +@return KErrNone on success, otherwise a system wide error code. +*/ +TInt RUsbDevice::GetDeviceDescriptor(TUsbDeviceDescriptor& aDescriptor) + { + __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); + __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); + aDescriptor = *iHeadDeviceDescriptor; + return KErrNone; + } + +/** +Return the USB Configuration Descriptor for this device. + +Note: the supplied TUsbConfigurationDescriptor is owned by the caller, but any descriptor objects linked to it +remain the property of the RUsbDevice object. Memory leaks will result if the head pointer is not +cleaned up, but the pointed to objects should not be destroyed. + +@param [out] aDescriptor The supplied TUsbConfigurationDescriptor object will be populated from the data retrieved from +the device. Note that the caller owns the head of the list, but not any children or peers. + +@return KErrNone on success, otherwise a system wide error code. +*/ +TInt RUsbDevice::GetConfigurationDescriptor(TUsbConfigurationDescriptor& aDescriptor) + { + __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); + __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); + aDescriptor = *iHeadConfDescriptor; + return KErrNone; + } + +TInt RUsbDevice::GetStringDescriptor(TUsbStringDescriptor*& aDescriptor, TDes8& aTarget, TInt aIndex) + { + __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); + __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); + + aDescriptor = NULL; + // aTarget will be Zero-ed in the GetStringDescriptor overload. + + TInt err = GetStringDescriptor(aTarget, aIndex); + if(err != KErrNone) + { + return err; + } + return ParseStringDescriptor(aDescriptor, aTarget); + } + +TInt RUsbDevice::GetStringDescriptor(TUsbStringDescriptor*& aDescriptor, TDes8& aTarget, TInt aIndex, TInt aLangId) + { + __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); + __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); + + aDescriptor = NULL; + // aTarget will be Zero-ed in the GetStringDescriptor overload. + + TInt err = GetStringDescriptor(aTarget, aIndex, aLangId); + if(err != KErrNone) + { + return err; + } + + return ParseStringDescriptor(aDescriptor, aTarget); + } + +TInt RUsbDevice::ParseStringDescriptor(TUsbStringDescriptor*& aDescriptor, const TDesC8& aData) + { + TUsbGenericDescriptor* parsed = NULL; + TInt err = UsbDescriptorParser::Parse(aData, parsed); + if(err == KErrNone) + { + aDescriptor = TUsbStringDescriptor::Cast(parsed); + if(aDescriptor) + { + return KErrNone; + } + } + // If here then there has been an error when parsing the descriptor + if(parsed) + { + parsed->DestroyTree(); + delete parsed; + } + return (err != KErrNone) ? err : KErrCorrupt; + } + + + + +TInt RUsbDevice::GetDeviceDescriptor(TDes8& aDeviceDesc) + { + __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); + __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); + return iHub->DoControl(EGetDeviceDescriptor, (TAny*)iHandle, &aDeviceDesc); + } + + +TInt RUsbDevice::GetConfigurationDescriptorSize(TInt& aSize) + { + __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); + __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); + return iHub->DoControl(EGetConfigurationDescriptorSize, (TAny*)iHandle, &aSize); + } + + +TInt RUsbDevice::GetConfigurationDescriptor(TDes8& aConfigDesc) + { + __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbHubDriverPanicCat, UsbdiPanics::EUsbHubDriverRequestMadeWhileClosed)); + __ASSERT_DEBUG(iHub, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbDeviceHasHandleButNoHubDriver)); + return iHub->DoControl(EGetConfigurationDescriptor, (TAny*)iHandle, &aConfigDesc); + } + + +#endif // !__KERNEL_MODE__