Author: janderwald
Date: Tue Apr 19 18:35:40 2011
New Revision: 51406
URL:
http://svn.reactos.org/svn/reactos?rev=51406&view=rev
Log:
[USBEHCI_NEW]
- Fix warning because comparing signed vs unsigned
- Implement function for retrieving the device descriptor
- Implement function for retrieving a configuration descriptor (including contained
interface descriptor and endpoint descriptor)
- Cleanup interface for IUSBRequest:
- When caller initializes IUSBRequest with an IRP, then the operation mode is
asynchronously. Therefore when the request is completed,
IUSBRequest::ShouldReleaseRequestAfterCompletion will return true, which makes IUSBQueue
call Release on IUSBRequest
- When the caller initializes IUSBRequest with an setup packet, the operation mode is
synchronously. After submitting the IUSBRequest to queue, the caller should call
IUSBRequest::GetResultStatus. This function will then block untill the operation has been
completed. However, the caller needs to call Release() as those requests are not cleaned
up by the IUSBQueue
Modified:
branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp
branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h
branches/usb-bringup/drivers/usb/usbehci_new/usb_device.cpp
branches/usb-bringup/drivers/usb/usbehci_new/usb_request.cpp
Modified: branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp [iso-8859-1]
(original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp [iso-8859-1] Tue Apr
19 18:35:40 2011
@@ -288,7 +288,7 @@
return STATUS_UNSUCCESSFUL;
}
- if (BufferLength < m_HubDeviceInterfaceString.Length - 8)
+ if (BufferLength < (ULONG)m_HubDeviceInterfaceString.Length - 8)
{
//
// buffer too small
@@ -774,7 +774,7 @@
//
// sanity check
//
- PC_ASSERT(Urb->UrbControlVendorClassRequest.Index - 1 < NumPort);
+ PC_ASSERT(Urb->UrbControlVendorClassRequest.Index - 1 < (USHORT)NumPort);
//
// port range reported start from 1 -n
@@ -1882,7 +1882,8 @@
//
// submit urb
//
- Status = UsbDevice->SubmitUrb(Urb);
+ //Status = UsbDevice->SubmitUrb(Urb);
+ UNIMPLEMENTED
if (NT_SUCCESS(Status))
{
Modified: branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h [iso-8859-1] Tue Apr 19
18:35:40 2011
@@ -171,6 +171,15 @@
// Do not call Initialize on IUSBQueue, the object is already initialized
virtual NTSTATUS GetUSBQueue(OUT struct IUSBQueue **OutUsbQueue) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetDMA
+//
+// Description: returns the DMA object which can be used to allocate memory from the
common buffer
+
+ virtual NTSTATUS GetDMA(OUT struct IDMAMemoryManager **OutDMAMemoryManager) = 0;
+
//-----------------------------------------------------------------------------------------
//
@@ -363,40 +372,33 @@
// The irp contains an URB block which contains all necessary information
virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager,
- IN OUT PIRP Irp);
-
-//-----------------------------------------------------------------------------------------
-//
-// SetCompletionEvent
-//
-// Description: sets up completion event which is signaled when the
-// request is completed or cancelled
-
- virtual NTSTATUS SetCompletionEvent(IN PKEVENT Event) = 0;
+ IN OUT PIRP Irp) = 0;
//-----------------------------------------------------------------------------------------
//
// CompletionCallback
//
// Description: called when request has been completed. It is called when
-// IUSBQueue completes the request
+// IUSBQueue completes a queue head
virtual VOID CompletionCallback(IN NTSTATUS NtStatusCode,
- IN ULONG UrbStatusCode) = 0;
+ IN ULONG UrbStatusCode,
+ IN struct _QUEUE_HEAD *QueueHead) = 0;
//-----------------------------------------------------------------------------------------
//
// CancelCallback
//
-// Description: called when request is cancelled. Called by IUSBQueue
-
- virtual VOID CancelCallback(IN NTSTATUS NtStatusCode) = 0;
+// Description: called when the queue head is cancelled
+
+ virtual VOID CancelCallback(IN NTSTATUS NtStatusCode,
+ IN struct _QUEUE_HEAD *QueueHead) = 0;
//-----------------------------------------------------------------------------------------
//
// GetQueueHead
//
-// Description: returns an initialized queue head with contains the all transfer
descriptors
+// Description: returns an initialized queue head which contains all transfer
descriptors
virtual NTSTATUS GetQueueHead(struct _QUEUE_HEAD ** OutHead) = 0;
@@ -406,6 +408,9 @@
//
// Description: returns true when the request has been completed
// Should be called after the CompletionCallback has been invoked
+// This function is called by IUSBQueue after queue head has been completed
+// If the function returns true, IUSBQueue will then call
ShouldReleaseRequestAfterCompletion
+// If that function returns also true, it calls Release() to delete the IUSBRequest
virtual BOOLEAN IsRequestComplete() = 0;
@@ -417,6 +422,34 @@
virtual ULONG GetTransferType() = 0;
+//-----------------------------------------------------------------------------------------
+//
+// GetResultStatus
+//
+// Description: returns the status code of the result
+// Note: this function will block the caller untill the request has been completed
+
+ virtual VOID GetResultStatus(OUT OPTIONAL NTSTATUS * NtStatusCode,
+ OUT OPTIONAL PULONG UrbStatusCode) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// IsRequestInitialized
+//
+// Description: returns true when the request has been successfully initialized using
InitializeXXX methods
+
+ virtual BOOLEAN IsRequestInitialized() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// ShouldReleaseRequestAfterCompletion
+//
+// Description: this function gets called when the request returns
+// IUSBQueue will then call Release() on the object to release all associated memory
+// This function will typically return true when the request has been initialized with an
irp
+// If the request was initialized with an setup packet, it will return false
+
+ virtual BOOLEAN ShouldReleaseRequestAfterCompletion() = 0;
};
typedef IUSBRequest *PUSBREQUEST;
@@ -446,7 +479,7 @@
//
// GetPendingRequestCount
//
-// Description: returns the number of pending requests
+// Description: returns the number of pending requests true from IsRequestComplete
virtual ULONG GetPendingRequestCount() = 0;
@@ -608,7 +641,7 @@
//
// Description: gets the device address of the this device
- virtual ULONG GetDeviceAddress() = 0;
+ virtual UCHAR GetDeviceAddress() = 0;
//-----------------------------------------------------------------------------------------
@@ -657,7 +690,7 @@
//
// Description: sets device handle data
- virtual NTSTATUS SetDeviceAddress(ULONG DeviceAddress) = 0;
+ virtual NTSTATUS SetDeviceAddress(UCHAR DeviceAddress) = 0;
//-----------------------------------------------------------------------------------------
//
@@ -677,11 +710,11 @@
//-----------------------------------------------------------------------------------------
//
-// SubmitUrb
-//
-// Description: submits an urb
-
- virtual NTSTATUS SubmitUrb(PURB Urb) = 0;
+// SubmitIrp
+//
+// Description: submits an irp containing an urb
+
+ virtual NTSTATUS SubmitIrp(PIRP Urb) = 0;
};
Modified: branches/usb-bringup/drivers/usb/usbehci_new/usb_device.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/usb_device.cpp [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/usb_device.cpp [iso-8859-1] Tue Apr 19
18:35:40 2011
@@ -11,6 +11,24 @@
#define INITGUID
#include "usbehci.h"
+typedef struct _USB_ENDPOINT
+{
+ USB_ENDPOINT_DESCRIPTOR EndPointDescriptor;
+} USB_ENDPOINT, *PUSB_ENDPOINT;
+
+typedef struct _USB_INTERFACE
+{
+ USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+ USB_ENDPOINT *EndPoints;
+} USB_INTERFACE, *PUSB_INTERFACE;
+
+typedef struct _USB_CONFIGURATION
+{
+ USB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
+ USB_INTERFACE *Interfaces;
+} USB_CONFIGURATION, *PUSB_CONFIGURATION;
+
+
class CUSBDevice : public IUSBDevice
{
public:
@@ -37,20 +55,22 @@
virtual NTSTATUS Initialize(IN PHUBCONTROLLER HubController, IN PUSBHARDWAREDEVICE
Device, IN PVOID Parent, IN ULONG Port, IN ULONG PortStatus);
virtual BOOLEAN IsHub();
virtual NTSTATUS GetParent(PVOID * Parent);
- virtual ULONG GetDeviceAddress();
+ virtual UCHAR GetDeviceAddress();
virtual ULONG GetPort();
virtual USB_DEVICE_SPEED GetSpeed();
virtual USB_DEVICE_TYPE GetType();
virtual ULONG GetState();
virtual void SetDeviceHandleData(PVOID Data);
- virtual NTSTATUS SetDeviceAddress(ULONG DeviceAddress);
+ virtual NTSTATUS SetDeviceAddress(UCHAR DeviceAddress);
virtual void GetDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor);
virtual UCHAR GetConfigurationValue();
- virtual NTSTATUS SubmitUrb(PURB Urb);
+ virtual NTSTATUS SubmitIrp(PIRP Irp);
// local function
- virtual NTSTATUS CommitUrb(PURB Urb);
- virtual NTSTATUS CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, IN ULONG
BufferLength, IN OUT PVOID Buffer, IN OPTIONAL PIRP Irp, IN OPTIONAL PKEVENT pEvent);
+ virtual NTSTATUS CommitIrp(PIRP Irp);
+ virtual NTSTATUS CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, IN ULONG
BufferLength, IN OUT PMDL Mdl);
+ virtual NTSTATUS CreateConfigurationDescriptor(ULONG ConfigurationIndex);
+ virtual NTSTATUS CreateDeviceDescriptor();
// constructor / destructor
CUSBDevice(IUnknown *OuterUnknown){}
@@ -62,13 +82,15 @@
PUSBHARDWAREDEVICE m_Device;
PVOID m_Parent;
ULONG m_Port;
- ULONG m_DeviceAddress;
+ UCHAR m_DeviceAddress;
PVOID m_Data;
KSPIN_LOCK m_Lock;
USB_DEVICE_DESCRIPTOR m_DeviceDescriptor;
ULONG m_PortStatus;
PUSBQUEUE m_Queue;
PDMAMEMORYMANAGER m_DmaManager;
+
+ PUSB_CONFIGURATION m_ConfigurationDescriptors;
};
//----------------------------------------------------------------------------------------
@@ -126,19 +148,445 @@
}
//
- // FIXME: get dma manager
- //
- //Status = m_Device->GetDMA(&m_DmaManager);
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to get usb queue
- //
- DPRINT1("CUSBDevice::Initialize GetUsbQueue failed with %x\n",
Status);
- return Status;
- }
-
-
+ // get dma manager
+ //
+ Status = m_Device->GetDMA(&m_DmaManager);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to get dma manager
+ //
+ DPRINT1("CUSBDevice::Initialize GetDMA failed with %x\n", Status);
+ return Status;
+ }
+
+ //
+ // sanity check
+ //
+ PC_ASSERT(m_DmaManager);
+
+ //
+ // get device descriptor
+ //
+ Status = CreateDeviceDescriptor();
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to get device descriptor
+ //
+ DPRINT1("CUSBDevice::Initialize Failed to get device descriptor with
%x\n", Status);
+ return Status;
+ }
+
+ //
+ // done
+ //
+ return Status;
+}
+
+//----------------------------------------------------------------------------------------
+BOOLEAN
+CUSBDevice::IsHub()
+{
+ //
+ // USB Standard Device Class see
http://www.usb.org/developers/defined_class/#BaseClass09h
+ // for details
+ //
+ return (m_DeviceDescriptor.bDeviceClass == 0x09 &&
m_DeviceDescriptor.bDeviceSubClass == 0x00);
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBDevice::GetParent(
+ PVOID * Parent)
+{
+ //
+ // returns parent
+ //
+ *Parent = m_Parent;
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
+}
+
+//----------------------------------------------------------------------------------------
+UCHAR
+CUSBDevice::GetDeviceAddress()
+{
+ //
+ // get device address
+ //
+ return m_DeviceAddress;
+}
+
+//----------------------------------------------------------------------------------------
+ULONG
+CUSBDevice::GetPort()
+{
+ //
+ // get port to which this device is connected to
+ //
+ return m_Port;
+}
+
+//----------------------------------------------------------------------------------------
+USB_DEVICE_SPEED
+CUSBDevice::GetSpeed()
+{
+ if (m_PortStatus & USB_PORT_STATUS_LOW_SPEED)
+ {
+ //
+ // low speed device
+ //
+ return UsbLowSpeed;
+ }
+ else if (m_PortStatus & USB_PORT_STATUS_HIGH_SPEED)
+ {
+ //
+ // high speed device
+ //
+ return UsbHighSpeed;
+ }
+
+ //
+ // default to full speed
+ //
+ return UsbFullSpeed;
+}
+
+//----------------------------------------------------------------------------------------
+USB_DEVICE_TYPE
+CUSBDevice::GetType()
+{
+ //
+ // device is encoded into bcdUSB
+ //
+ if (m_DeviceDescriptor.bcdUSB == 0x110)
+ {
+ //
+ // USB 1.1 device
+ //
+ return Usb11Device;
+ }
+ else if (m_DeviceDescriptor.bcdUSB == 0x200)
+ {
+ //
+ // USB 2.0 device
+ //
+ return Usb20Device;
+ }
+
+ DPRINT1("CUSBDevice::GetType Unknown bcdUSB Type %x\n",
m_DeviceDescriptor.bcdUSB);
+ PC_ASSERT(FALSE);
+
+ return Usb11Device;
+}
+
+//----------------------------------------------------------------------------------------
+ULONG
+CUSBDevice::GetState()
+{
+ UNIMPLEMENTED
+ return FALSE;
+}
+
+//----------------------------------------------------------------------------------------
+void
+CUSBDevice::SetDeviceHandleData(
+ PVOID Data)
+{
+ //
+ // set device data, for debugging issues
+ //
+ m_Data = Data;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBDevice::SetDeviceAddress(
+ UCHAR DeviceAddress)
+{
+ USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+ NTSTATUS Status;
+ UCHAR OldAddress;
+ ULONG Index;
+
+ //
+ // zero request
+ //
+ RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+
+ //
+ // initialize request
+ //
+ CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS;
+ CtrlSetup.wValue.W = (USHORT)DeviceAddress;
+
+ //
+ // set device address
+ //
+ Status = CommitSetupPacket(&CtrlSetup, 0, 0);
+
+ //
+ // check for success
+ //
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to set device address
+ //
+ DPRINT1("CUSBDevice::SetDeviceAddress> failed to set device address with
%x Address %x\n", Status, DeviceAddress);
+ return Status;
+ }
+
+ //
+ // back up old address
+ //
+ OldAddress = m_DeviceAddress;
+
+ //
+ // store new device address
+ //
+ m_DeviceAddress = DeviceAddress;
+
+ //
+ // check that setting device address succeeded by retrieving the device descriptor
+ //
+ Status = CreateDeviceDescriptor();
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to retrieve device descriptor
+ //
+ DPRINT1("CUSBbDevice::SetDeviceAddress> failed to set new device address
%d, falling back to %d Error %x\n", DeviceAddress, OldAddress, Status);
+ m_DeviceAddress = OldAddress;
+
+ //
+ // return error status
+ //
+ return Status;
+ }
+
+ //
+ // sanity checks
+ //
+ PC_ASSERT(m_DeviceDescriptor.bNumConfigurations);
+
+ //
+ // allocate configuration descriptor
+ //
+ m_ConfigurationDescriptors = (PUSB_CONFIGURATION) ExAllocatePoolWithTag(NonPagedPool,
sizeof(USB_CONFIGURATION) * m_DeviceDescriptor.bNumConfigurations, TAG_USBEHCI);
+
+ //
+ // zero configuration descriptor
+ //
+ RtlZeroMemory(m_ConfigurationDescriptors, sizeof(USB_CONFIGURATION) *
m_DeviceDescriptor.bNumConfigurations);
+
+ //
+ // retrieve the configuration descriptors
+ //
+ for(Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++)
+ {
+ //
+ // retrieve configuration descriptors from device
+ //
+ Status = CreateConfigurationDescriptor(Index);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CUSBDevice::SetDeviceAddress> failed to retrieve
configuration %lu\n", Index);
+ break;
+ }
+ }
+
+ //
+ // done
+ //
+ return Status;
+
+}
+
+//----------------------------------------------------------------------------------------
+void
+CUSBDevice::GetDeviceDescriptor(
+ PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
+{
+ RtlMoveMemory(DeviceDescriptor, &m_DeviceDescriptor,
sizeof(USB_DEVICE_DESCRIPTOR));
+}
+
+//----------------------------------------------------------------------------------------
+UCHAR
+CUSBDevice::GetConfigurationValue()
+{
+ UNIMPLEMENTED
+ return 0x1;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBDevice::CommitIrp(
+ PIRP Irp)
+{
+ NTSTATUS Status;
+ PUSBREQUEST Request;
+
+ if (!m_Queue || m_DmaManager)
+ {
+ //
+ // no queue, wtf?
+ //
+ DPRINT1("CUSBDevice::CommitUrb> no queue / dma !!!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // build usb request
+ //
+ Status = m_Queue->CreateUSBRequest(&Request);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to build request
+ //
+ DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with
%x\n", Status);
+ return Status;
+ }
+
+ //
+ // initialize request
+ //
+ Status = Request->InitializeWithIrp(m_DmaManager, Irp);
+
+ //
+ // now add the request
+ //
+ Status = m_Queue->AddUSBRequest(Request);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to add request
+ //
+ DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with
%x\n", Status);
+ Request->Release();
+ return Status;
+ }
+
+ //
+ // done
+ //
+ return Status;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBDevice::SubmitIrp(
+ PIRP Irp)
+{
+ KIRQL OldLevel;
+ NTSTATUS Status;
+
+ //
+ // acquire device lock
+ //
+ KeAcquireSpinLock(&m_Lock, &OldLevel);
+
+ //
+ // commit urb
+ //
+ Status = CommitIrp(Irp);
+
+ //
+ // release lock
+ //
+ KeReleaseSpinLock(&m_Lock, OldLevel);
+
+ return Status;
+}
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBDevice::CommitSetupPacket(
+ PUSB_DEFAULT_PIPE_SETUP_PACKET Packet,
+ IN ULONG BufferLength,
+ IN OUT PMDL Mdl)
+{
+ NTSTATUS Status;
+ PUSBREQUEST Request;
+
+ if (!m_Queue)
+ {
+ //
+ // no queue, wtf?
+ //
+ DPRINT1("CUSBDevice::CommitSetupPacket> no queue!!!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // build usb request
+ //
+ Status = m_Queue->CreateUSBRequest(&Request);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to build request
+ //
+ DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with
%x\n", Status);
+ return Status;
+ }
+
+ //
+ // initialize request
+ //
+ Status = Request->InitializeWithSetupPacket(m_DmaManager, Packet, BufferLength,
Mdl);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to initialize request
+ //
+ DPRINT1("CUSBDevice::CommitSetupPacket> failed to initialize usb request
with %x\n", Status);
+ Request->Release();
+ return Status;
+ }
+
+
+ //
+ // now add the request
+ //
+ Status = m_Queue->AddUSBRequest(Request);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to add request
+ //
+ DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with
%x\n", Status);
+ Request->Release();
+ return Status;
+ }
+
+ //
+ // get the result code when the operation has been finished
+ //
+ Request->GetResultStatus(&Status, NULL);
+
+ //
+ // release request
+ //
+ Request->Release();
+
+ //
+ // done
+ //
+ return Status;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBDevice::CreateDeviceDescriptor()
+{
+ USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+ PMDL Mdl;
+ NTSTATUS Status;
//
// zero descriptor
@@ -155,362 +603,239 @@
CtrlSetup.bmRequestType.B = 0x80;
//
+ // allocate mdl describing the device descriptor
+ //
+ Mdl = IoAllocateMdl(&m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR), FALSE,
FALSE, 0);
+ if (!Mdl)
+ {
+ //
+ // failed to allocate mdl
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // build mdl for non paged pool
+ //
+ MmBuildMdlForNonPagedPool(Mdl);
+
+ //
// commit setup packet
//
- Status = CommitSetupPacket(&CtrlSetup, sizeof(USB_DEVICE_DESCRIPTOR),
&m_DeviceDescriptor, 0, 0);
-
- //
- // check for success
- //
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("CUSBDevice::Initialize CommitSetupPacket failed with %x\n",
Status);
- }
+ Status = CommitSetupPacket(&CtrlSetup, sizeof(USB_DEVICE_DESCRIPTOR), Mdl);
+
+ //
+ // now free the mdl
+ //
+ IoFreeMdl(Mdl);
//
// done
//
return Status;
-}
-
-//----------------------------------------------------------------------------------------
-BOOLEAN
-CUSBDevice::IsHub()
-{
- //
- // USB Standard Device Class see
http://www.usb.org/developers/defined_class/#BaseClass09h
- // for details
- //
- return (m_DeviceDescriptor.bDeviceClass == 0x09 &&
m_DeviceDescriptor.bDeviceSubClass == 0x00);
-}
-
-//----------------------------------------------------------------------------------------
-NTSTATUS
-CUSBDevice::GetParent(
- PVOID * Parent)
-{
- //
- // returns parent
- //
- *Parent = m_Parent;
-
- //
- // done
- //
- return STATUS_SUCCESS;
-}
-
-//----------------------------------------------------------------------------------------
-ULONG
-CUSBDevice::GetDeviceAddress()
-{
- //
- // get device address
- //
- return m_DeviceAddress;
-}
-
-//----------------------------------------------------------------------------------------
-ULONG
-CUSBDevice::GetPort()
-{
- //
- // get port to which this device is connected to
- //
- return m_Port;
-}
-
-//----------------------------------------------------------------------------------------
-USB_DEVICE_SPEED
-CUSBDevice::GetSpeed()
-{
- if (m_PortStatus & USB_PORT_STATUS_LOW_SPEED)
- {
- //
- // low speed device
- //
- return UsbLowSpeed;
- }
- else if (m_PortStatus & USB_PORT_STATUS_HIGH_SPEED)
- {
- //
- // high speed device
- //
- return UsbHighSpeed;
- }
-
- //
- // default to full speed
- //
- return UsbFullSpeed;
-}
-
-//----------------------------------------------------------------------------------------
-USB_DEVICE_TYPE
-CUSBDevice::GetType()
-{
- //
- // device is encoded into bcdUSB
- //
- if (m_DeviceDescriptor.bcdUSB == 0x110)
- {
- //
- // USB 1.1 device
- //
- return Usb11Device;
- }
- else if (m_DeviceDescriptor.bcdUSB == 0x200)
- {
- //
- // USB 2.0 device
- //
- return Usb20Device;
- }
-
- DPRINT1("CUSBDevice::GetType Unknown bcdUSB Type %x\n",
m_DeviceDescriptor.bcdUSB);
- PC_ASSERT(FALSE);
-
- return Usb11Device;
-}
-
-//----------------------------------------------------------------------------------------
-ULONG
-CUSBDevice::GetState()
-{
- UNIMPLEMENTED
- return FALSE;
-}
-
-//----------------------------------------------------------------------------------------
-void
-CUSBDevice::SetDeviceHandleData(
- PVOID Data)
-{
- //
- // set device data, for debugging issues
- //
- m_Data = Data;
-}
-
-//----------------------------------------------------------------------------------------
-NTSTATUS
-CUSBDevice::SetDeviceAddress(
- ULONG DeviceAddress)
-{
+
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBDevice::CreateConfigurationDescriptor(
+ ULONG Index)
+{
+ PVOID Buffer;
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
NTSTATUS Status;
-
- //
- // zero request
- //
- RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
-
- //
- // initialize request
- //
- CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS;
- CtrlSetup.wValue.W = (USHORT)DeviceAddress;
-
- //
- // set device address
- //
- Status = CommitSetupPacket(&CtrlSetup, 0, 0, 0, 0);
-
- //
- // check for success
- //
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to set device address
- //
- DPRINT1("CUSBDevice::SetDeviceAddress> failed to set device address with
%x Address %x\n", Status, DeviceAddress);
- return Status;
- }
-
- //
- // store device address
- //
- m_DeviceAddress = DeviceAddress;
+ PMDL Mdl;
+ ULONG InterfaceIndex, EndPointIndex;
+ PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
+ PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+ PUSB_ENDPOINT_DESCRIPTOR EndPointDescriptor;
+
+
+ //
+ // sanity checks
+ //
+ PC_ASSERT(m_ConfigurationDescriptors);
+
+ //
+ // first allocate a buffer which should be enough to store all different interfaces
and endpoints
+ //
+ Buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, TAG_USBEHCI);
+ if (!Buffer)
+ {
+ //
+ // failed to allocate buffer
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // build setup packet
+ //
+ CtrlSetup.bmRequestType._BM.Recipient = BMREQUEST_TO_DEVICE;
+ CtrlSetup.bmRequestType._BM.Type = BMREQUEST_STANDARD;
+ CtrlSetup.bmRequestType._BM.Reserved = 0;
+ CtrlSetup.bmRequestType._BM.Dir = BMREQUEST_DEVICE_TO_HOST;
+ CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
+ CtrlSetup.wValue.LowByte = 0;
+ CtrlSetup.wValue.HiByte = USB_CONFIGURATION_DESCRIPTOR_TYPE;
+ CtrlSetup.wIndex.W = 0;
+ CtrlSetup.wLength = PAGE_SIZE;
+
+ //
+ // FIXME: where put configuration index?
+ //
+
+ //
+ // now build MDL describing the buffer
+ //
+ Mdl = IoAllocateMdl(Buffer, PAGE_SIZE, FALSE, FALSE, 0);
+ if (!Mdl)
+ {
+ //
+ // failed to allocate mdl
+ //
+ ExFreePoolWithTag(Buffer, TAG_USBEHCI);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // build mdl for non paged pool
+ //
+ MmBuildMdlForNonPagedPool(Mdl);
+
+ //
+ // commit packet
+ //
+ Status = CommitSetupPacket(&CtrlSetup, PAGE_SIZE, Mdl);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to issue request, cleanup
+ //
+ IoFreeMdl(Mdl);
+ ExFreePool(Buffer);
+ return Status;
+ }
+
+ //
+ // now free the mdl
+ //
+ IoFreeMdl(Mdl);
+
+ //
+ // get configuration descriptor
+ //
+ ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)Buffer;
+
+ //
+ // sanity check
+ //
+ PC_ASSERT(ConfigurationDescriptor->bLength ==
sizeof(USB_CONFIGURATION_DESCRIPTOR));
+ PC_ASSERT(ConfigurationDescriptor->wTotalLength <= PAGE_SIZE);
+ PC_ASSERT(ConfigurationDescriptor->bNumInterfaces);
+
+ //
+ // request is complete, initialize configuration descriptor
+ //
+ RtlCopyMemory(&m_ConfigurationDescriptors[Index].ConfigurationDescriptor,
ConfigurationDescriptor, ConfigurationDescriptor->bLength);
+
+ //
+ // now allocate interface descriptors
+ //
+ m_ConfigurationDescriptors[Index].Interfaces =
(PUSB_INTERFACE)ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_INTERFACE) *
ConfigurationDescriptor->bNumInterfaces, TAG_USBEHCI);
+ if (!m_ConfigurationDescriptors[Index].Interfaces)
+ {
+ //
+ // failed to allocate interface descriptors
+ //
+ ExFreePool(Buffer);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // zero interface descriptor
+ //
+ RtlZeroMemory(m_ConfigurationDescriptors[Index].Interfaces, sizeof(USB_INTERFACE) *
ConfigurationDescriptor->bNumInterfaces);
+
+ //
+ // get first interface descriptor
+ //
+ InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)(ConfigurationDescriptor + 1);
+
+ //
+ // setup interface descriptors
+ //
+ for(InterfaceIndex = 0; InterfaceIndex <
ConfigurationDescriptor->bNumInterfaces; InterfaceIndex++)
+ {
+ //
+ // sanity check
+ //
+ PC_ASSERT(InterfaceDescriptor->bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
+ PC_ASSERT(InterfaceDescriptor->bNumEndpoints);
+
+ //
+ // copy current interface descriptor
+ //
+
RtlCopyMemory(&m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].InterfaceDescriptor,
InterfaceDescriptor, InterfaceDescriptor->bLength);
+
+ //
+ // allocate end point descriptors
+ //
+ m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].EndPoints =
(PUSB_ENDPOINT)ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_ENDPOINT) *
InterfaceDescriptor->bNumEndpoints, TAG_USBEHCI);
+ if (!m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].EndPoints)
+ {
+ //
+ // failed to allocate endpoint
+ //
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+
+ //
+ // zero memory
+ //
+
RtlZeroMemory(m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].EndPoints,
sizeof(USB_ENDPOINT) * InterfaceDescriptor->bNumEndpoints);
+
+ //
+ // initialize end point descriptors
+ //
+ EndPointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)(InterfaceDescriptor + 1);
+
+ for(EndPointIndex = 0; EndPointIndex < InterfaceDescriptor->bNumEndpoints;
EndPointIndex++)
+ {
+ //
+ // sanity check
+ //
+ PC_ASSERT(EndPointDescriptor->bLength ==
sizeof(USB_ENDPOINT_DESCRIPTOR));
+
+ //
+ // copy endpoint descriptor
+ //
+
RtlCopyMemory(&m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].EndPoints[EndPointIndex].EndPointDescriptor,
EndPointDescriptor, EndPointDescriptor->bLength);
+
+ //
+ // move to next offset
+ //
+ EndPointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)EndPointDescriptor
+ EndPointDescriptor->bLength);
+ }
+
+ //
+ // update interface descriptor offset
+ //
+ InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)EndPointDescriptor;
+ }
+
+ //
+ // free buffer
+ //
+ ExFreePoolWithTag(Buffer, TAG_USBEHCI);
//
// done
//
- return STATUS_SUCCESS;
-}
-
-//----------------------------------------------------------------------------------------
-void
-CUSBDevice::GetDeviceDescriptor(
- PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
-{
- RtlMoveMemory(DeviceDescriptor, &m_DeviceDescriptor,
sizeof(USB_DEVICE_DESCRIPTOR));
-}
-
-//----------------------------------------------------------------------------------------
-UCHAR
-CUSBDevice::GetConfigurationValue()
-{
- UNIMPLEMENTED
- return 0x1;
-}
-
-//----------------------------------------------------------------------------------------
-NTSTATUS
-CUSBDevice::CommitUrb(
- PURB Urb)
-{
- UNIMPLEMENTED
- return STATUS_NOT_IMPLEMENTED;
-}
-
-//----------------------------------------------------------------------------------------
-NTSTATUS
-CUSBDevice::SubmitUrb(
- PURB Urb)
-{
- KIRQL OldLevel;
- NTSTATUS Status;
-
- //
- // acquire device lock
- //
- KeAcquireSpinLock(&m_Lock, &OldLevel);
-
- //
- // commit urb
- //
- Status = CommitUrb(Urb);
-
- //
- // release lock
- //
- KeReleaseSpinLock(&m_Lock, OldLevel);
-
return Status;
}
-//----------------------------------------------------------------------------------------
-NTSTATUS
-CUSBDevice::CommitSetupPacket(
- PUSB_DEFAULT_PIPE_SETUP_PACKET Packet,
- IN ULONG BufferLength,
- IN OUT PVOID Buffer,
- IN PIRP Irp,
- IN PKEVENT pEvent)
-{
- NTSTATUS Status;
- PUSBREQUEST Request;
- KEVENT Event;
- BOOLEAN Wait = FALSE;
- PMDL Mdl = 0;
-
-
- if (!m_Queue)
- {
- //
- // no queue, wtf?
- //
- DPRINT1("CUSBDevice::CommitSetupPacket> no queue!!!\n");
- return STATUS_UNSUCCESSFUL;
- }
-
- //
- // build usb request
- //
- Status = m_Queue->CreateUSBRequest(&Request);
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to build request
- //
- DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with
%x\n", Status);
- return Status;
- }
-
- /* FIXME build MDL */
-
- //
- // initialize request
- //
- Status = Request->InitializeWithSetupPacket(m_DmaManager, Packet, BufferLength,
Mdl);
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to initialize request
- //
- DPRINT1("CUSBDevice::CommitSetupPacket> failed to initialize usb request
with %x\n", Status);
- Request->Release();
- return Status;
- }
-
- //
- // is a irp or event provided ?
- //
- if (Irp == NULL && pEvent == NULL)
- {
- //
- // no completion details provided, requestor wants synchronized
- //
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- pEvent = &Event;
- Wait = TRUE;
- }
-
- //
- // set completion details
- //
- Status = Request->SetCompletionEvent(pEvent);
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to set completion details
- //
- DPRINT1("CUSBDevice::CommitSetupPacket> failed to set completion details
with %x\n", Status);
- Request->Release();
- return Status;
- }
-
- //
- // now add the request
- //
- Status = m_Queue->AddUSBRequest(Request);
- if (!NT_SUCCESS(Status))
- {
- //
- // failed to add request
- //
- DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with
%x\n", Status);
- Request->Release();
- return Status;
- }
-
- if (Wait)
- {
- //
- // wait for the operation to complete
- //
- KeWaitForSingleObject(pEvent, Executive, KernelMode, FALSE, NULL);
- }
-
- //TODO:
- // Get result code from operation
- //
-
- //
- // returns the result code when the operation has been finished
- //
- //Status = Request->GetResultCode();
-
- //
- // release request
- //
- Request->Release();
-
- //
- // done
- //
- return Status;
-}
+
//----------------------------------------------------------------------------------------
NTSTATUS
CreateUSBDevice(
Modified: branches/usb-bringup/drivers/usb/usbehci_new/usb_request.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/usb_request.cpp [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/usb_request.cpp [iso-8859-1] Tue Apr 19
18:35:40 2011
@@ -38,12 +38,14 @@
// IUSBRequest interface functions
virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager, IN
PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN OUT ULONG TransferBufferLength, IN OUT PMDL
TransferBuffer);
virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager, IN OUT PIRP
Irp);
- virtual NTSTATUS SetCompletionEvent(IN PKEVENT Event);
- virtual VOID CompletionCallback(IN NTSTATUS NtStatusCode, IN ULONG UrbStatusCode);
- virtual VOID CancelCallback(IN NTSTATUS NtStatusCode);
+ virtual VOID CompletionCallback(IN NTSTATUS NtStatusCode, IN ULONG UrbStatusCode, IN
struct _QUEUE_HEAD *QueueHead);
+ virtual VOID CancelCallback(IN NTSTATUS NtStatusCode, IN struct _QUEUE_HEAD
*QueueHead);
virtual NTSTATUS GetQueueHead(struct _QUEUE_HEAD ** OutHead);
virtual BOOLEAN IsRequestComplete();
virtual ULONG GetTransferType();
+ virtual VOID GetResultStatus(OUT OPTIONAL NTSTATUS *NtStatusCode, OUT OPTIONAL PULONG
UrbStatusCode);
+ virtual BOOLEAN IsRequestInitialized();
+ virtual BOOLEAN ShouldReleaseRequestAfterCompletion();
// local functions
ULONG InternalGetTransferType();
@@ -60,17 +62,60 @@
protected:
LONG m_Ref;
+
+ //
+ // memory manager for allocating setup packet / queue head / transfer descriptors
+ //
PDMAMEMORYMANAGER m_DmaManager;
+
+ //
+ // caller provided irp packet containing URB request
+ //
+ PIRP m_Irp;
+
+ //
+ // transfer buffer length
+ //
+ ULONG m_TransferBufferLength;
+
+ //
+ // transfer buffer MDL
+ //
+ PMDL m_TransferBufferMDL;
+
+
+ //
+ // caller provided setup packet
+ //
PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket;
- ULONG m_TransferBufferLength;
- PMDL m_TransferBufferMDL;
- PIRP m_Irp;
+
+ //
+ // completion event for callers who initialized request with setup packet
+ //
PKEVENT m_CompletionEvent;
+ //
+ // DMA queue head
+ //
PQUEUE_HEAD m_QueueHead;
+
+ //
+ // DMA transfer descriptors linked to the queue head
+ //
PQUEUE_TRANSFER_DESCRIPTOR m_TransferDescriptors[3];
+
+ //
+ // allocated setup packet from the DMA pool
+ //
PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket;
PHYSICAL_ADDRESS m_DescriptorSetupPacket;
+
+ //
+ // stores the result of the operation
+ //
+ NTSTATUS m_NtStatusCode;
+ ULONG m_UrbStatusCode;
+
};
//----------------------------------------------------------------------------------------
@@ -106,6 +151,23 @@
m_TransferBufferMDL = TransferBuffer;
//
+ // allocate completion event
+ //
+ m_CompletionEvent = (PKEVENT)ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT),
TAG_USBEHCI);
+ if (!m_CompletionEvent)
+ {
+ //
+ // failed to allocate completion event
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // initialize completion event
+ //
+ KeInitializeEvent(m_CompletionEvent, NotificationEvent, FALSE);
+
+ //
// done
//
return STATUS_SUCCESS;
@@ -166,7 +228,7 @@
if (Urb->UrbBulkOrInterruptTransfer.TransferBufferLength)
{
//
- // it must have an MDL
+ // FIXME: it must have an MDL
//
PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
@@ -189,38 +251,27 @@
return STATUS_SUCCESS;
}
-//----------------------------------------------------------------------------------------
-NTSTATUS
-CUSBRequest::SetCompletionEvent(
- IN PKEVENT Event)
-{
- if (m_QueueHead)
- {
- //
- // WTF? operation is already in progress
- //
- return STATUS_UNSUCCESSFUL;
- }
-
- //
- // store completion event
- //
- m_CompletionEvent = Event;
-
- //
- // done
- //
- return STATUS_SUCCESS;
-}
+
//----------------------------------------------------------------------------------------
VOID
CUSBRequest::CompletionCallback(
IN NTSTATUS NtStatusCode,
- IN ULONG UrbStatusCode)
+ IN ULONG UrbStatusCode,
+ IN struct _QUEUE_HEAD *QueueHead)
{
PIO_STACK_LOCATION IoStack;
PURB Urb;
+ //
+ // FIXME: support linked queue heads
+ //
+
+ //
+ // store completion code
+ //
+ m_NtStatusCode = NtStatusCode;
+ m_UrbStatusCode = UrbStatusCode;
+
if (m_Irp)
{
//
@@ -260,23 +311,33 @@
//
IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
}
-
- if (m_CompletionEvent)
- {
- //
- // FIXME: make sure the request was not split
- //
+ else
+ {
+ //
+ // signal completion event
+ //
+ PC_ASSERT(m_CompletionEvent);
KeSetEvent(m_CompletionEvent, 0, FALSE);
}
}
//----------------------------------------------------------------------------------------
VOID
CUSBRequest::CancelCallback(
- IN NTSTATUS NtStatusCode)
+ IN NTSTATUS NtStatusCode,
+ IN struct _QUEUE_HEAD *QueueHead)
{
PIO_STACK_LOCATION IoStack;
PURB Urb;
+ //
+ // FIXME: support linked queue heads
+ //
+
+ //
+ // store cancelleation code
+ //
+ m_NtStatusCode = NtStatusCode;
+
if (m_Irp)
{
//
@@ -306,12 +367,12 @@
//
IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
}
-
- if (m_CompletionEvent)
- {
- //
- // FIXME: make sure the request was not split
- //
+ else
+ {
+ //
+ // signal completion event
+ //
+ PC_ASSERT(m_CompletionEvent);
KeSetEvent(m_CompletionEvent, 0, FALSE);
}
}
@@ -370,6 +431,7 @@
//
// FIXME: check if request was split
//
+ UNIMPLEMENTED
return TRUE;
}
//----------------------------------------------------------------------------------------
@@ -451,7 +513,6 @@
NTSTATUS Status;
ULONG NumTransferDescriptors, Index;
PQUEUE_HEAD QueueHead;
-
//
// first allocate the queue head
@@ -802,3 +863,75 @@
return Status;
}
+//----------------------------------------------------------------------------------------
+VOID
+CUSBRequest::GetResultStatus(
+ OUT OPTIONAL NTSTATUS * NtStatusCode,
+ OUT OPTIONAL PULONG UrbStatusCode)
+{
+ //
+ // sanity check
+ //
+ PC_ASSERT(m_CompletionEvent);
+
+ //
+ // wait for the operation to complete
+ //
+ KeWaitForSingleObject(m_CompletionEvent, Executive, KernelMode, FALSE, NULL);
+
+ //
+ // copy status
+ //
+ if (NtStatusCode)
+ {
+ *NtStatusCode = m_NtStatusCode;
+ }
+
+ //
+ // copy urb status
+ //
+ if (UrbStatusCode)
+ {
+ *UrbStatusCode = m_UrbStatusCode;
+ }
+
+}
+
+
+//-----------------------------------------------------------------------------------------
+BOOLEAN
+CUSBRequest::IsRequestInitialized()
+{
+ if (m_Irp || m_SetupPacket)
+ {
+ //
+ // request is initialized
+ //
+ return TRUE;
+ }
+
+ //
+ // request is not initialized
+ //
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------------------
+BOOLEAN
+CUSBRequest::ShouldReleaseRequestAfterCompletion()
+{
+ if (m_Irp)
+ {
+ //
+ // the request is completed, release it
+ //
+ return TRUE;
+ }
+ else
+ {
+ //
+ // created with an setup packet, don't release
+ //
+ return FALSE;
+ }
+}