kernel/eka/include/d32usbdi.inl
changeset 0 a41df078684a
child 87 2f92ad2dc5db
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/include/d32usbdi.inl	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,538 @@
+// 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:
+//
+
+/**
+ 
+ The driver's name
+ 
+ @return The name of the driver
+ 
+ @internalComponent
+*/
+const TDesC& RUsbInterface::Name()
+	{
+	_LIT(KDriverName,"USBDI");
+	return KDriverName;
+	}
+
+/**
+The driver's version
+
+@return The version number of the driver
+
+@internalComponent
+*/
+TVersion RUsbInterface::VersionRequired()
+	{
+	const TInt KMajorVersionNumber=1;
+	const TInt KMinorVersionNumber=0;
+	const TInt KBuildVersionNumber=KE32BuildVersionNumber;
+	return TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
+	}
+
+
+
+#ifndef __KERNEL_MODE__
+RUsbInterface::RUsbInterface()
+	: iHeadInterfaceDescriptor(NULL)
+	, iInterfaceDescriptorData(NULL)
+	, iTransferStrategy(NULL)
+	, iAlternateSetting(0)
+	{
+	}
+
+/**
+Signals to the hub driver that this interface is idle and may be suspended.
+As suspend operates at the device level, this will only trigger a removal of bus activity if all interfaces
+associated with the device are marked as suspended.
+
+@param [in] aResumeSignal The TRequestStatus that will be completed when the interface is resumed.
+*/
+void RUsbInterface::PermitSuspendAndWaitForResume(TRequestStatus& aResumeSignal)
+	{
+	DoRequest(ESuspend, aResumeSignal);
+	}
+
+/**
+Cancel the outstanding permission to suspend.
+*/
+void RUsbInterface::CancelPermitSuspend()
+	{
+	DoCancel(ECancelSuspend);
+	}
+
+/**
+Cancel the outstanding PermitSuspendAndWaitForResume request with KErrCancel
+*/
+void RUsbInterface::CancelWaitForResume()
+	{
+	DoCancel(ECancelWaitForResume);
+	}
+
+/**
+Request or clear the interface's remote wakeup flag.  If any interface on the device
+has this flag set, suspending the device will cause it to have remote wakeup capability
+enabled.  This function may only be called when the interface is active -- the device will
+not be woken to change the status if it is currently suspended.
+Note that clearing this flag will not prevent a device from using remote wakeup -- this
+will happen only if all interfaces on the device do not require it.
+By default the device will not have remote wakeup enabled.
+
+@param aAllowed ETrue if remote wakeup should be permitted, EFalse if this interface does
+not require it.
+
+@return KErrNotReady if two calls have been made in succession with the same parameter.
+KErrUsbDeviceSuspended if the interface is currently marked as suspended.
+*/
+TInt RUsbInterface::PermitRemoteWakeup(TBool aAllowed)
+	{
+	return DoControl(EPermitRemoteWakeup, (TAny*)aAllowed);
+	}
+
+
+/**
+Select the specified alternate interface.
+
+Asserts that all open pipes have been closed.
+
+@param [in] aAlternateInterface The alternate interface to select.
+
+@return KErrArgument if the specified alternate interface does not exist.
+@return KErrOverflow if selecting this alternate interface would overcommit the bus' bandwidth.
+*/
+TInt RUsbInterface::SelectAlternateInterface(TInt aAlternateInterface)
+	{
+	TInt err = DoControl(ESelectAlternateInterface, (TAny*)aAlternateInterface);
+	if(err == KErrNone)
+		{
+		iAlternateSetting = aAlternateInterface;
+		}
+	return err;
+	}
+
+TInt RUsbInterface::GetStringDescriptor(TDes8& aStringDescriptor, TUint8 aIndex, TUint16 aLangId)
+	{
+	TUint32 params;
+	params = aIndex | (aLangId << 16);
+	return DoControl(EGetStringDescriptor, &aStringDescriptor, &params);
+	}
+
+
+/**  
+Performs an Endpoint 0 transfer.
+*/
+void RUsbInterface::Ep0Transfer(TUsbTransferRequestDetails& aDetails, const TDesC8& aSend, TDes8& aRecv, TRequestStatus& aRequest)
+	{
+	aDetails.iSend         = &aSend;
+	aDetails.iRecv         = &aRecv;
+	DoRequest(EEp0Transfer, aRequest, (TAny*)&aDetails);
+	}
+
+/**  
+Cancel an Endpoint 0 transfer.
+*/
+void RUsbInterface::CancelEP0Transfer()
+	{
+	DoCancel(ECancelEp0Transfer);
+	}
+
+/**
+Establish a pipe between host and device.  The RUsbPipe object returned is ready for use.
+
+@param aPipe The pipe to connect to the remote endpoint. [out]
+@param aEndpoint The endpoint on the remote device to connect to. [in]
+@param aUseDMA In future implementations where DMA is supported this flag indicates DMA must be used. The Open attempt will fail if DMA cannot be offered on the pipe. [in]
+
+@return KErrArgument if the specified endpoint does not exist.
+@see SelectAlternateInterface
+*/
+TInt RUsbInterface::OpenPipeForEndpoint(RUsbPipe& aPipe, TInt aEndpoint, TBool /*aUseDMA*/)
+	{
+	if(aPipe.iHandle)
+		{
+		return KErrInUse;
+		}
+
+	TInt err = GetEndpointDescriptor(iAlternateSetting, aEndpoint, aPipe.iHeadEndpointDescriptor);
+	// Allow KErrNotFound as audio endpoint descriptors are not valid endpoint descriptors
+	if ((err == KErrNone) || (err == KErrNotFound))
+		{
+		TUint32 pipeHandle;
+		err = DoControl(EOpenPipe, &pipeHandle, reinterpret_cast<TAny*>(aEndpoint));
+		if (err == KErrNone)
+			{
+			aPipe.iHandle = pipeHandle;
+			aPipe.iInterface = this;
+			}
+		}
+
+	return err;
+	}
+
+/**
+@internalComponent
+*/
+TInt RUsbInterface::AllocateSharedChunk(RChunk& aChunk, TInt aSize, TInt& aOffset)
+	{
+	TInt chunkHandle = 0;
+	RUsbInterface::TChunkRequestDetails details;
+	details.iRequestSize = aSize;
+	details.iChunkHandle = &chunkHandle;
+	details.iOffset = &aOffset;
+	TInt err = DoControl(EAllocChunk, &details);
+	if(err == KErrNone)
+		{
+		aChunk.SetHandle(chunkHandle);
+		}
+	return err;
+	}
+
+/**
+Return the section of the USB Configuration Descriptor under this interface, including any alternate
+interfaces.
+
+Note: the supplied TUsbInterfaceDescriptor is owned by the caller, but any descriptor objects linked to it
+remain the property of the RUsbInterface 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 TUsbInterfaceDescriptor 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 System wide error code.
+*/
+TInt RUsbInterface::GetInterfaceDescriptor(TUsbInterfaceDescriptor& aDescriptor)
+	{
+	if (!iHeadInterfaceDescriptor)
+		{
+		return KErrNotReady;
+		}
+
+	aDescriptor = *iHeadInterfaceDescriptor;
+	return KErrNone;
+	}
+
+/**
+Find and return the section of the USB Configuration Descriptor under the supplied alternate interface.
+
+Note: the supplied TUsbInterfaceDescriptor is owned by the caller, but any descriptor objects linked to it
+remain the property of the RUsbInterface object.  Memory leaks will result if the head pointer is not
+cleaned up, but the pointed to objects should not be destroyed.
+
+@param aAlternateInterface The alternate interface number to return the descriptor for. [in]
+@param aDescriptor The supplied TUsbInterfaceDescriptor 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. [out]
+
+@return KErrArgument if the specified alternate interface does not exist.
+*/
+TInt RUsbInterface::GetAlternateInterfaceDescriptor(TInt aAlternateInterface, TUsbInterfaceDescriptor& aDescriptor)
+	{
+	if (!iHeadInterfaceDescriptor)
+		{
+		return KErrNotReady;
+		}
+
+	TUsbGenericDescriptor* descriptor = iHeadInterfaceDescriptor;
+	while (descriptor)
+		{
+		TUsbInterfaceDescriptor* interface = TUsbInterfaceDescriptor::Cast(descriptor);
+		if (interface)
+			{
+			if (interface->AlternateSetting() == aAlternateInterface)
+				{
+				aDescriptor = *interface;
+				return KErrNone;
+				}
+			}
+        // we must check any Interface Association Descriptors for
+        // Alternate Interface settings.  The spec is abiguous on how these may be organised so we
+        // presume the worst and do a full search
+		TUsbInterfaceAssociationDescriptor* iad = TUsbInterfaceAssociationDescriptor::Cast(descriptor);
+		if (iad)
+			{
+			TUsbGenericDescriptor* assocDes = iad->iFirstChild;
+			while (assocDes)
+				{
+				interface = TUsbInterfaceDescriptor::Cast(assocDes);
+				if (interface)
+					{
+					if (interface->AlternateSetting() == aAlternateInterface)
+						{
+						aDescriptor = *interface;
+						return KErrNone;
+						}
+					}
+				assocDes = assocDes->iNextPeer;
+				}
+			}
+		descriptor = descriptor->iNextPeer;
+		}
+
+	return KErrArgument;
+	}
+
+/**
+Find and return the section of the USB Configuration Descriptor under the supplied endpoint.
+
+Note: the supplied TUsbEndpointDescriptor is owned by the caller, but any descriptor objects linked to it
+remain the property of the RUsbInterface object.  Memory leaks will result if the head pointer is not
+cleaned up, but the pointed to objects should not be destroyed.
+
+@param aAlternateInterface The alternate interface number to return the descriptor for. [in]
+@param aEndpoint The endpoint number to return the descriptor for. [in]
+@param aDescriptor The supplied TUsbEndpointDescriptor 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. [out]
+
+@return KErrArgument if the specified alternate interface does not exist, or KErrNotFound if the specified
+endpoint cannot be found on the alternate interface.
+*/
+TInt RUsbInterface::GetEndpointDescriptor(TInt aAlternateInterface, TInt aEndpoint, TUsbEndpointDescriptor& aDescriptor)
+	{
+	TUsbEndpointDescriptor* descriptor = &aDescriptor;
+	TInt err = GetEndpointDescriptor(aAlternateInterface, aEndpoint, descriptor);
+    if ((err == KErrNone) && descriptor)
+		{
+		aDescriptor = *descriptor;
+		}
+	return err;
+	}
+
+TInt RUsbInterface::GetEndpointDescriptor(TInt aAlternateInterface, TInt aEndpoint, TUsbEndpointDescriptor*& aDescriptor)
+	{
+	aDescriptor = NULL;
+
+	TUsbInterfaceDescriptor alternate;
+	TInt err = GetAlternateInterfaceDescriptor(aAlternateInterface, alternate);
+	if (err != KErrNone)
+		{
+		return err;
+		}
+
+	TUsbGenericDescriptor* descriptor = alternate.iFirstChild;
+	while (descriptor)
+		{
+		TUsbEndpointDescriptor* endpoint = TUsbEndpointDescriptor::Cast(descriptor);
+		if (endpoint && (endpoint->EndpointAddress() == aEndpoint))
+			{
+			aDescriptor = endpoint;
+			return KErrNone;
+			}
+
+		descriptor = descriptor->iNextPeer;
+		}
+
+	return KErrNotFound;
+	}
+
+/**
+@return Number of alternate interface options on this interface.
+*/
+TInt RUsbInterface::GetAlternateInterfaceCount()
+	{
+	if (!iHeadInterfaceDescriptor)
+		{
+		return KErrNotReady;
+		}
+
+	TInt count = 0;
+
+	// Don't need to look for children of the interface -- all the alternates
+    // must be peers.
+	TUsbGenericDescriptor* descriptor = iHeadInterfaceDescriptor;
+	while (descriptor)
+		{
+		TUsbInterfaceDescriptor* interface = TUsbInterfaceDescriptor::Cast(descriptor);
+		if (interface)
+			{
+			++count;
+			}
+		else
+            {
+            // we must check any Interface Association Descriptors for
+            // Alternate Interface settings.  The spec is abiguous on how these may be organised so we
+            // presume the worst and do a full search
+            TUsbInterfaceAssociationDescriptor* iad = TUsbInterfaceAssociationDescriptor::Cast(descriptor);
+            if (iad)
+                {
+                TUsbGenericDescriptor* assocDes = iad->iFirstChild;
+                while (assocDes)
+                    {
+                    interface = TUsbInterfaceDescriptor::Cast(assocDes);
+                    if (interface)
+                        {
+                        ++count;
+                        }
+                    assocDes = assocDes->iNextPeer;
+                    }
+                }
+            }
+		descriptor = descriptor->iNextPeer;
+		}
+
+	return count;
+	}
+
+/**
+Count the endpoints on an alternate interface.
+
+@param [in] aAlternateInterface The alternate interface to count endpoints on.
+@return Number of endpoionts on the requested alternate interface or an error code.
+*/
+TInt RUsbInterface::EnumerateEndpointsOnInterface(TInt aAlternateInterface)
+	{
+	TUsbInterfaceDescriptor alternate;
+	TInt err = GetAlternateInterfaceDescriptor(aAlternateInterface, alternate);
+	if (err != KErrNone)
+		{
+		return err;
+		}
+
+	return alternate.NumEndpoints();
+	}
+	
+/**
+Returns an identifier that is unique for the bus that the device that provides this interface is on.
+@param aBusId On success provides an identifier that is unique for the bus this interface is on.
+@return KErrNone on success, otherwise a system-wide error code.
+*/
+TInt RUsbInterface::GetBusId(TUsbBusId& aBusId)
+	{
+	return DoControl(EGetBusId, &aBusId);
+	}
+
+/**
+Returns the size of pages used by the HCD.
+@internalComponent
+@return The HCD's page size.
+*/
+TInt RUsbInterface::HcdPageSize()
+	{
+	return DoControl(EHcdPageSize);
+	}
+
+/**
+Returns the speed the remote device is connected at.
+@param aDeviceSpeed On sucess an enumeration value describing the current speed of the remote device.
+@return KErrNone on success, otherwise a system-wide error code.
+*/
+TInt RUsbInterface::GetDeviceSpeed(RUsbInterface::TDeviceSpeed& aDeviceSpeed)
+	{
+	return DoControl(EGetDeviceSpeed, &aDeviceSpeed);
+	}
+
+
+
+
+
+RUsbPipe::RUsbPipe()
+	: iHandle(0)
+	, iInterface(NULL)
+	{
+	}
+
+TUint32 RUsbPipe::Handle() const
+	{
+	return iHandle;
+	}
+
+/**
+Close a pipe to a remote device.
+*/
+void RUsbPipe::Close()
+	{
+	if (iInterface)
+		{
+		static_cast<void>(iInterface->DoControl(EClose, (TAny*)iHandle));
+		}
+	iHeadEndpointDescriptor = NULL;
+	iInterface = NULL;
+	iHandle = 0;
+	}
+
+/**
+Clear a stall on the remote endpoint.
+
+@return System-wide error code.
+*/
+TInt RUsbPipe::ClearRemoteStall()
+	{
+	__ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbdiPanicCat, UsbdiPanics::EPipeRequestMadeWhileClosed));
+	__ASSERT_DEBUG(iInterface, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbPipeHasHandleButNoInterface));
+	return iInterface->DoControl(EClearRemoteStall, (TAny*)iHandle);
+	}
+
+/**
+Cancel all queued transfers
+*/
+void RUsbPipe::CancelAllTransfers()
+	{
+	__ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbdiPanicCat, UsbdiPanics::EPipeRequestMadeWhileClosed));
+	__ASSERT_DEBUG(iInterface, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbPipeHasHandleButNoInterface));
+	static_cast<void>(iInterface->DoControl(EAbort, (TAny*)iHandle));
+	}
+
+/**
+Issues a transfer.
+@internalComponent
+*/
+void RUsbPipe::IssueTransfer(TInt aTransferHandle, TRequestStatus& aRequest)
+	{
+	__ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbdiPanicCat, UsbdiPanics::EPipeRequestMadeWhileClosed));
+	__ASSERT_DEBUG(iInterface, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbPipeHasHandleButNoInterface));
+	iInterface->DoRequest(EIssueTransfer, aRequest, (TAny*)iHandle, (TAny*)aTransferHandle);
+	}
+
+/**
+Get endpoint ID
+*/
+TInt RUsbPipe::GetEndpointId(TUsbEndpointId& aEndpointId)
+	{
+	__ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbdiPanicCat, UsbdiPanics::EPipeRequestMadeWhileClosed));
+	__ASSERT_DEBUG(iInterface, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbPipeHasHandleButNoInterface));
+	return iInterface->DoControl(EGetEndpointId, reinterpret_cast<TAny*>(iHandle), &aEndpointId);
+	}
+
+/**
+Get Bus ID
+*/
+TInt RUsbPipe::GetBusId(TUsbBusId& aBusId)
+	{
+	__ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbdiPanicCat, UsbdiPanics::EPipeRequestMadeWhileClosed));
+	__ASSERT_DEBUG(iInterface, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbPipeHasHandleButNoInterface));
+	return iInterface->GetBusId(aBusId);
+	}
+
+/**
+Return the section of the USB Configuration Descriptor under the supplied endpoint.
+
+@param [out] aDescriptor The descriptor tree for this endpoint.
+@return System-wide error code.
+*/
+TInt RUsbPipe::GetEndpointDescriptor(TUsbEndpointDescriptor& aDescriptor)
+	{
+    __ASSERT_ALWAYS(iHandle, User::Panic(UsbdiPanics::KUsbdiPanicCat, UsbdiPanics::EPipeRequestMadeWhileClosed));
+    __ASSERT_DEBUG(iInterface, User::Panic(UsbdiFaults::KUsbdiFaultCat, UsbdiFaults::EUsbPipeHasHandleButNoInterface));
+
+	if (iHeadEndpointDescriptor)
+		{
+		aDescriptor = *iHeadEndpointDescriptor;
+		return KErrNone;
+		}
+	else
+		{
+		return KErrNotFound;
+		}
+	}
+
+#endif