[USBEHCI_NEW]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Fri, 15 Apr 2011 17:57:24 +0000 (17:57 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Fri, 15 Apr 2011 17:57:24 +0000 (17:57 +0000)
- Create Interface IDispatchIrp which is used to handle ioctl requests
- Partly implement IHubController interface

svn path=/branches/usb-bringup/; revision=51355

drivers/usb/usbehci_new/CMakeLists.txt
drivers/usb/usbehci_new/hcd_controller.cpp
drivers/usb/usbehci_new/hub_controller.cpp [new file with mode: 0644]
drivers/usb/usbehci_new/interfaces.h
drivers/usb/usbehci_new/usbehci.cpp
drivers/usb/usbehci_new/usbehci.h

index a167e30..ab79d54 100644 (file)
@@ -10,6 +10,7 @@ add_library(usbehci SHARED
     hardware.cpp
     misc.cpp
     purecall.cpp
+    hub_controller.cpp
     usbehci.rc)
 
 target_link_libraries(usbehci
index f0be143..7312513 100644 (file)
@@ -11,7 +11,8 @@
 #define INITGUID
 #include "usbehci.h"
 
-class CHCDController : public IHCDController
+class CHCDController : public IHCDController,
+                       public IDispatchIrp
 {
 public:
     STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
@@ -33,8 +34,10 @@ public:
         return m_Ref;
     }
 
-    // interface functions
+    // IHCDController interface functions
     NTSTATUS Initialize(IN PROOTHDCCONTROLLER RootHCDController, IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject);
+
+    // IDispatchIrp interface functions
     NTSTATUS HandlePnp(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
     NTSTATUS HandlePower(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
     NTSTATUS HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
@@ -42,8 +45,7 @@ public:
     // local functions
     NTSTATUS CreateFDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
     NTSTATUS CreatePDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
-    NTSTATUS HandleQueryInterface(PIO_STACK_LOCATION IoStack);
-    NTSTATUS SetDeviceInterface(BOOLEAN bEnable);
+    NTSTATUS SetSymbolicLink(BOOLEAN Enable);
 
     // constructor / destructor
     CHCDController(IUnknown *OuterUnknown){}
@@ -57,10 +59,7 @@ protected:
     PDEVICE_OBJECT m_FunctionalDeviceObject;
     PDEVICE_OBJECT m_NextDeviceObject;
     PUSBHARDWAREDEVICE m_Hardware;
-    PDEVICE_OBJECT m_BusPDO;
-    UNICODE_STRING m_HubDeviceInterfaceString;
-    BOOLEAN m_InterfaceEnabled;
-    ULONG m_PDODeviceNumber;
+    PHUBCONTROLLER m_HubController;
     ULONG m_FDODeviceNumber;
 };
 
@@ -73,15 +72,6 @@ CHCDController::QueryInterface(
     IN  REFIID refiid,
     OUT PVOID* Output)
 {
-    UNICODE_STRING GuidString;
-
-    if (IsEqualGUIDAligned(refiid, IID_IUnknown))
-    {
-        *Output = PVOID(PUNKNOWN(this));
-        PUNKNOWN(*Output)->AddRef();
-        return STATUS_SUCCESS;
-    }
-
     return STATUS_UNSUCCESSFUL;
 }
 
@@ -187,7 +177,7 @@ CHCDController::Initialize(
     //
     DeviceExtension->IsFDO = TRUE;
     DeviceExtension->IsHub = FALSE;
-    DeviceExtension->HcdController = PHCDCONTROLLER(this);
+    DeviceExtension->Dispatcher = PDISPATCHIRP(this);
 
     //
     // device is initialized
@@ -345,18 +335,18 @@ CHCDController::HandlePnp(
     PCM_RESOURCE_LIST RawResourceList;
     PCM_RESOURCE_LIST TranslatedResourceList;
     PDEVICE_RELATIONS DeviceRelations;
-    PDEVICE_CAPABILITIES DeviceCapabilities;
-    LPGUID Guid;
     NTSTATUS Status;
-    ULONG Index;
-
-    DPRINT("HandlePnp\n");
 
     //
     // get device extension
     //
     DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
 
+    //
+    // sanity check
+    //
+    PC_ASSERT(DeviceExtension->IsFDO);
+
     //
     // get current stack location
     //
@@ -366,90 +356,67 @@ CHCDController::HandlePnp(
     {
         case IRP_MN_START_DEVICE:
         {
-            DPRINT1("IRP_MN_START FDO: %lu\n", DeviceExtension->IsFDO);
+            DPRINT1("CHCDController::HandlePnp IRP_MN_START FDO\n");
+
+            //
+            // first start lower device object
+            //
+            Status = SyncForwardIrp(m_NextDeviceObject, Irp);
 
-            if (DeviceExtension->IsFDO)
+            if (NT_SUCCESS(Status))
             {
                 //
-                // first start lower device object
+                // operation succeeded, lets start the device
                 //
-                Status = SyncForwardIrp(m_NextDeviceObject, Irp);
+                RawResourceList = IoStack->Parameters.StartDevice.AllocatedResources;
+                TranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
 
-                if (NT_SUCCESS(Status))
+                if (m_Hardware)
                 {
                     //
-                    // operation succeeded, lets start the device
+                    // start the hardware
                     //
-                    RawResourceList = IoStack->Parameters.StartDevice.AllocatedResources;
-                    TranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
-
-                    if (m_Hardware)
-                    {
-                        //
-                        // start the hardware
-                        //
-                        Status = m_Hardware->PnpStart(RawResourceList, TranslatedResourceList);
-                    }
+                    Status = m_Hardware->PnpStart(RawResourceList, TranslatedResourceList);
                 }
 
                 //
-                // HACK / FIXME: Windows XP SP3 fails to enumerate the PDO correctly, which
-                //               causes the PDO device never to startup.
+                // enable symbolic link
                 //
-                Status = SetDeviceInterface(TRUE);
+                Status = SetSymbolicLink(TRUE);
             }
-            else
-            {
-                //
-                // start the PDO device
-                //
-                ASSERT(0);
-
-                //
-                //FIXME create the parent root hub device
-                //
-
-                //
-                // register device interface 
-                //
-                Status = SetDeviceInterface(TRUE);
-            }
-
-            DPRINT1("IRP_MN_START FDO: %lu Status %x\n", DeviceExtension->IsFDO, Status);
 
+            DPRINT1("CHCDController::HandlePnp IRP_MN_START FDO: Status %x\n", Status);
             break;
         }
         case IRP_MN_QUERY_DEVICE_RELATIONS:
         {
-            DPRINT1("IRP_MN_QUERY_DEVICE_RELATIONS Type %lx FDO: \n", IoStack->Parameters.QueryDeviceRelations.Type, DeviceExtension->IsFDO);
+            DPRINT1("CHCDController::HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %lx\n", IoStack->Parameters.QueryDeviceRelations.Type);
 
-            if (m_BusPDO == NULL)
+            if (m_HubController == NULL)
             {
                 //
-                // create bus PDO
+                // create hub controller
                 //
-                Status = CreatePDO(m_DriverObject, &m_BusPDO);
-
+                Status = CreateHubController(&m_HubController);
                 if (!NT_SUCCESS(Status))
                 {
                     //
-                    // failed to create bus device object
+                    // failed to create hub controller
                     //
                     break;
                 }
 
                 //
-                // initialize extension
+                // initialize hub controller
                 //
-                DeviceExtension = (PCOMMON_DEVICE_EXTENSION)m_BusPDO->DeviceExtension;
-                DeviceExtension->IsFDO = FALSE;
-                DeviceExtension->IsHub = FALSE;
-                DeviceExtension->HcdController = (this);
-
-                //
-                // clear init flag
-                //
-                m_BusPDO->Flags &= ~DO_DEVICE_INITIALIZING;
+                Status = m_HubController->Initialize(m_DriverObject, PHCDCONTROLLER(this), m_Hardware, TRUE, 0 /* FIXME*/);
+                if (!NT_SUCCESS(Status))
+                {
+                    //
+                    // failed to initialize hub controller
+                    //
+                    break;
+                }
             }
 
             if (IoStack->Parameters.QueryDeviceRelations.Type == BusRelations)
@@ -472,9 +439,14 @@ CHCDController::HandlePnp(
                 // init device relations
                 //
                 DeviceRelations->Count = 1;
-                DeviceRelations->Objects [0] = m_BusPDO;
+                Status = m_HubController->GetHubControllerDeviceObject(&DeviceRelations->Objects [0]);
+
+                //
+                // sanity check
+                //
+                PC_ASSERT(Status == STATUS_SUCCESS);
 
-                ObReferenceObject(m_BusPDO);
+                ObReferenceObject(DeviceRelations->Objects [0]);
 
                 //
                 // store result
@@ -482,12 +454,19 @@ CHCDController::HandlePnp(
                 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
                 Status = STATUS_SUCCESS;
             }
+            else
+            {
+                //
+                // not supported
+                //
+                PC_ASSERT(0);
+                Status = STATUS_NOT_SUPPORTED;
+            }
             break;
         }
-
         case IRP_MN_STOP_DEVICE:
         {
-            DPRINT1("IRP_MN_STOP_DEVICE FDO: %lu\n", DeviceExtension->IsFDO);
+            DPRINT1("CHCDController::HandlePnp IRP_MN_STOP_DEVICE\n");
 
             if (m_Hardware)
             {
@@ -513,153 +492,31 @@ CHCDController::HandlePnp(
             }
             break;
         }
-        case IRP_MN_QUERY_CAPABILITIES:
+        case IRP_MN_REMOVE_DEVICE:
         {
-            DPRINT1("IRP_MN_QUERY_CAPABILITIES FDO: %lu\n", DeviceExtension->IsFDO);
-
-            if (DeviceExtension->IsFDO == FALSE)
-            {
-                DeviceCapabilities = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities;
-
-                DeviceCapabilities->LockSupported = FALSE;
-                DeviceCapabilities->EjectSupported = FALSE;
-                DeviceCapabilities->Removable = FALSE;
-                DeviceCapabilities->DockDevice = FALSE;
-                DeviceCapabilities->UniqueID = FALSE;
-                DeviceCapabilities->SilentInstall = FALSE;
-                DeviceCapabilities->RawDeviceOK = FALSE;
-                DeviceCapabilities->SurpriseRemovalOK = FALSE;
-                DeviceCapabilities->Address = 0;
-                DeviceCapabilities->UINumber = 0;
-                DeviceCapabilities->DeviceD2 = 1;
-
-                /* FIXME */
-                DeviceCapabilities->HardwareDisabled = FALSE;
-                DeviceCapabilities->NoDisplayInUI = FALSE;
-                DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
-                for (Index = 0; Index < PowerSystemMaximum; Index++)
-                    DeviceCapabilities->DeviceState[Index] = PowerDeviceD3;
-                DeviceCapabilities->DeviceWake = PowerDeviceUnspecified;
-                DeviceCapabilities->D1Latency = 0;
-                DeviceCapabilities->D2Latency = 0;
-                DeviceCapabilities->D3Latency = 0;
-
-                Status = STATUS_SUCCESS;
-            }
-            else
-            {
-                //
-                // forward irp to next device object
-                //
-                IoSkipCurrentIrpStackLocation(Irp);
-                return IoCallDriver(m_NextDeviceObject, Irp);
-            }
+            DPRINT1("CHCDController::HandlePnp IRP_MN_REMOVE_DEVICE FDO\n");
 
-            break;
-        }
-        case IRP_MN_QUERY_INTERFACE:
-        {
-            DPRINT1("IRP_MN_QUERY_INTERFACE FDO %u\n", DeviceExtension->IsFDO);
             //
-            // check if the device is FDO
+            // detach device from device stack
             //
-            if (DeviceExtension->IsFDO)
-            {
-                //
-                // just pass the irp to next device object
-                //
-                IoSkipCurrentIrpStackLocation(Irp);
-                return IoCallDriver(m_NextDeviceObject, Irp);
-            }
+            IoDetachDevice(m_NextDeviceObject);
 
             //
-            // handle device interface requests
+            // delete device
             //
-            Status = HandleQueryInterface(IoStack);
-            break;
-        }
-        case IRP_MN_QUERY_BUS_INFORMATION:
-        {
-            DPRINT1("IRP_MN_QUERY_BUS_INFORMATION FDO %lx\n", DeviceExtension->IsFDO);
-
-            if (DeviceExtension->IsFDO == FALSE)
-            {
-                //
-                // allocate buffer for bus guid
-                //
-                Guid = (LPGUID)ExAllocatePool(PagedPool, sizeof(GUID));
-                if (Guid)
-                {
-                    //
-                    // copy BUS guid
-                    //
-                    RtlMoveMemory(Guid, &GUID_BUS_TYPE_USB, sizeof(GUID));
-                    Status = STATUS_SUCCESS;
-                    Irp->IoStatus.Information = (ULONG_PTR)Guid;
-                }
-            }
-            break;
-        }
-        case IRP_MN_REMOVE_DEVICE:
-        {
-            DPRINT1("IRP_MN_REMOVE_DEVICE FDO: %lu\n", DeviceExtension->IsFDO);
-
-            if (DeviceExtension->IsFDO == FALSE)
-            {
-                //
-                // deactivate device interface for BUS PDO
-                //
-                SetDeviceInterface(FALSE);
-
-                //
-                // complete the request first
-                //
-                Irp->IoStatus.Status = STATUS_SUCCESS;
-                IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-                //
-                // now delete device
-                //
-                IoDeleteDevice(m_BusPDO);
-
-                //
-                // nullify pointer
-                //
-                m_BusPDO = 0;
-                return STATUS_SUCCESS;
-            }
-            else
-            {
-                //
-                // detach device from device stack
-                //
-                IoDetachDevice(m_NextDeviceObject);
-
-                //
-                // delete device
-                //
-                IoDeleteDevice(m_FunctionalDeviceObject);
-            }
+            IoDeleteDevice(m_FunctionalDeviceObject);
 
             Status = STATUS_SUCCESS;
             break;
         }
         default:
         {
-            if (DeviceExtension->IsFDO)
-            {
-                DPRINT1("HandlePnp> FDO Dispatch to lower device object %lu\n", IoStack->MinorFunction);
-
-                //
-                // forward irp to next device object
-                //
-                IoSkipCurrentIrpStackLocation(Irp);
-                return IoCallDriver(m_NextDeviceObject, Irp);
-            }
-            else
-            {
-                DPRINT1("UNHANDLED PDO Request %lu\n", IoStack->MinorFunction);
-            }
+            DPRINT1("CHCDController::HandlePnp Dispatch to lower device object %lu\n", IoStack->MinorFunction);
+            //
+            // forward irp to next device object
+            //
+            IoSkipCurrentIrpStackLocation(Irp);
+            return IoCallDriver(m_NextDeviceObject, Irp);
         }
     }
 
@@ -685,44 +542,6 @@ CHCDController::HandlePower(
     return STATUS_NOT_IMPLEMENTED;
 }
 
-NTSTATUS
-CHCDController::HandleQueryInterface(
-    PIO_STACK_LOCATION IoStack)
-{
-    UNICODE_STRING GuidBuffer;
-    NTSTATUS Status;
-
-    if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_HUB_GUID))
-    {
-        DPRINT1("HandleQueryInterface> UNIMPLEMENTED USB_BUS_INTERFACE_HUB_GUID Version %x\n", IoStack->Parameters.QueryInterface.Version);
-
-    }
-    else if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_USBDI_GUID))
-    {
-        DPRINT1("HandleQueryInterface> UNIMPLEMENTED USB_BUS_INTERFACE_USBDI_GUID Version %x\n", IoStack->Parameters.QueryInterface.Version);
-    }
-    else
-    {
-        //
-        // convert guid to string
-        //
-        Status = RtlStringFromGUID(*IoStack->Parameters.QueryInterface.InterfaceType, &GuidBuffer);
-        if (NT_SUCCESS(Status))
-        {
-            //
-            // print interface
-            //
-            DPRINT1("HandleQueryInterface GUID: %wZ Version %x\n", &GuidBuffer, IoStack->Parameters.QueryInterface.Version);
-
-            //
-            // free guid buffer
-            //
-            RtlFreeUnicodeString(&GuidBuffer);
-        }
-    }
-    return STATUS_NOT_SUPPORTED;
-}
-
 NTSTATUS
 CHCDController::CreateFDO(
     PDRIVER_OBJECT DriverObject,
@@ -796,7 +615,7 @@ CHCDController::CreateFDO(
 }
 
 NTSTATUS
-CHCDController::SetDeviceInterface(
+CHCDController::SetSymbolicLink(
     BOOLEAN Enable)
 {
     NTSTATUS Status;
@@ -806,28 +625,10 @@ CHCDController::SetDeviceInterface(
 
     if (Enable)
     {
-        //
-        // register device interface
-        //
-        Status = IoRegisterDeviceInterface(m_PhysicalDeviceObject, &GUID_DEVINTERFACE_USB_HUB, 0, &m_HubDeviceInterfaceString);
-
-        if (NT_SUCCESS(Status))
-        {
-            //
-            // now enable the device interface
-            //
-            Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, TRUE);
-
-            //
-            // enable interface
-            //
-            m_InterfaceEnabled = TRUE;
-        }
-
         //
         // create legacy link
         //
-        swprintf(LinkName, L"\\DosDevices\\HCD%d", m_PDODeviceNumber);
+        swprintf(LinkName, L"\\DosDevices\\HCD%d", m_FDODeviceNumber);
         swprintf(FDOName, L"\\Device\\USBFDO-%d", m_FDODeviceNumber);
         RtlInitUnicodeString(&Link, LinkName);
         RtlInitUnicodeString(&FDO, FDOName);
@@ -845,101 +646,31 @@ CHCDController::SetDeviceInterface(
             ASSERT(0);
         }
     }
-    else if (m_InterfaceEnabled)
-    {
-        //
-        // disable device interface
-        //
-        Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, FALSE);
-
-        if (NT_SUCCESS(Status))
-        {
-            //
-            // now delete interface string
-            //
-            RtlFreeUnicodeString(&m_HubDeviceInterfaceString);
-        }
-
-            //
-            // disable interface
-            //
-            m_InterfaceEnabled = FALSE;
-
-    }
-
-    //
-    // done
-    //
-    return Status;
-}
-
-NTSTATUS
-CHCDController::CreatePDO(
-    PDRIVER_OBJECT DriverObject,
-    PDEVICE_OBJECT * OutDeviceObject)
-{
-    WCHAR CharDeviceName[64];
-    NTSTATUS Status;
-    ULONG UsbDeviceNumber = 0;
-    UNICODE_STRING DeviceName;
-
-    while (TRUE)
+    else
     {
         //
-        // construct device name
-        //
-        swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber);
-
-        //
-        // initialize device name
+        // create legacy link
         //
-        RtlInitUnicodeString(&DeviceName, CharDeviceName);
+        swprintf(LinkName, L"\\DosDevices\\HCD%d", m_FDODeviceNumber);
+        RtlInitUnicodeString(&Link, LinkName);
 
         //
-        // create device
+        // now delete the symbolic link
         //
-        Status = IoCreateDevice(DriverObject,
-                                sizeof(COMMON_DEVICE_EXTENSION),
-                                &DeviceName,
-                                FILE_DEVICE_CONTROLLER,
-                                0,
-                                FALSE,
-                                OutDeviceObject);
+        Status = IoDeleteSymbolicLink(&Link);
 
-        /* check for success */
-        if (NT_SUCCESS(Status))
-            break;
-
-        //
-        // is there a device object with that same name
-        //
-        if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
+        if (!NT_SUCCESS(Status))
         {
             //
-            // Try the next name
+            // FIXME: handle me
             //
-            UsbDeviceNumber++;
-            continue;
-        }
-
-        //
-        // bail out on other errors
-        //
-        if (!NT_SUCCESS(Status))
-        {
-            DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName, Status);
-            return Status;
+            ASSERT(0);
         }
     }
 
     //
-    // store PDO number
+    // done
     //
-    m_PDODeviceNumber = UsbDeviceNumber;
-
-    DPRINT1("CreateFDO: DeviceName %wZ\n", &DeviceName);
-
-    /* done */
     return Status;
 }
 
diff --git a/drivers/usb/usbehci_new/hub_controller.cpp b/drivers/usb/usbehci_new/hub_controller.cpp
new file mode 100644 (file)
index 0000000..d3cd506
--- /dev/null
@@ -0,0 +1,522 @@
+/*
+ * PROJECT:     ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/usb/usbehci/hub_controller.cpp
+ * PURPOSE:     USB EHCI device driver.
+ * PROGRAMMERS:
+ *              Michael Martin (michael.martin@reactos.org)
+ *              Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+#define INITGUID
+#include "usbehci.h"
+
+class CHubController : public IHubController,
+                       public IDispatchIrp
+{
+public:
+    STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
+
+    STDMETHODIMP_(ULONG) AddRef()
+    {
+        InterlockedIncrement(&m_Ref);
+        return m_Ref;
+    }
+    STDMETHODIMP_(ULONG) Release()
+    {
+        InterlockedDecrement(&m_Ref);
+
+        if (!m_Ref)
+        {
+            delete this;
+            return 0;
+        }
+        return m_Ref;
+    }
+
+    // IHubController interface functions
+    virtual NTSTATUS Initialize(IN PDRIVER_OBJECT DriverObject, IN PHCDCONTROLLER Controller, IN PUSBHARDWAREDEVICE Device, IN BOOLEAN IsRootHubDevice, IN ULONG DeviceAddress);
+
+    // IDispatchIrp interface functions
+    virtual NTSTATUS HandlePnp(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
+    virtual NTSTATUS HandlePower(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
+    virtual NTSTATUS HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
+
+    // local functions
+    NTSTATUS HandleQueryInterface(PIO_STACK_LOCATION IoStack);
+    NTSTATUS SetDeviceInterface(BOOLEAN bEnable);
+    NTSTATUS CreatePDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
+    NTSTATUS GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject);
+
+    // constructor / destructor
+    CHubController(IUnknown *OuterUnknown){}
+    virtual ~CHubController(){}
+
+protected:
+    LONG m_Ref;
+    PHCDCONTROLLER m_Controller;
+    PUSBHARDWAREDEVICE m_Hardware;
+    BOOLEAN m_IsRootHubDevice;
+    ULONG m_DeviceAddress;
+    ULONG m_PDODeviceNumber;
+    BOOLEAN m_InterfaceEnabled;
+    UNICODE_STRING m_HubDeviceInterfaceString;
+    PDEVICE_OBJECT m_HubControllerDeviceObject;
+    PDRIVER_OBJECT m_DriverObject;
+};
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+STDMETHODCALLTYPE
+CHubController::QueryInterface(
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    return STATUS_UNSUCCESSFUL;
+}
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::Initialize(
+    IN PDRIVER_OBJECT DriverObject,
+    IN PHCDCONTROLLER Controller,
+    IN PUSBHARDWAREDEVICE Device,
+    IN BOOLEAN IsRootHubDevice,
+    IN ULONG DeviceAddress)
+{
+    NTSTATUS Status;
+    PCOMMON_DEVICE_EXTENSION DeviceExtension;
+
+    DPRINT1("CHubController::Initialize\n");
+
+    //
+    // initialize members
+    //
+    m_Controller = Controller;
+    m_Hardware = Device;
+    m_IsRootHubDevice = IsRootHubDevice;
+    m_DeviceAddress = DeviceAddress;
+    m_DriverObject = DriverObject;
+
+    //
+    // create PDO
+    //
+    Status = CreatePDO(m_DriverObject, &m_HubControllerDeviceObject);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to create hub device object
+        //
+        return Status;
+    }
+
+    //
+    // get device extension
+    //
+    DeviceExtension = (PCOMMON_DEVICE_EXTENSION)m_HubControllerDeviceObject->DeviceExtension;
+
+    //
+    // initialize device extension
+    //
+    DeviceExtension->IsFDO = FALSE;
+    DeviceExtension->IsHub = TRUE; //FIXME
+    DeviceExtension->Dispatcher = PDISPATCHIRP(this);
+
+    //
+    // clear init flag
+    //
+    m_HubControllerDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+
+
+    return STATUS_SUCCESS;
+}
+
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject)
+{
+    //
+    // store controller object
+    //
+    *HubDeviceObject = m_HubControllerDeviceObject;
+
+    return STATUS_SUCCESS;
+}
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::HandlePnp(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN OUT PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    PCOMMON_DEVICE_EXTENSION DeviceExtension;
+    PDEVICE_CAPABILITIES DeviceCapabilities;
+    LPGUID Guid;
+    NTSTATUS Status;
+    ULONG Index;
+
+    //
+    // get device extension
+    //
+    DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    //
+    // sanity check
+    //
+    ASSERT(DeviceExtension->IsFDO == FALSE);
+
+    //
+    // get current stack location
+    //
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    switch(IoStack->MinorFunction)
+    {
+        case IRP_MN_START_DEVICE:
+        {
+            DPRINT1("CHubController::HandlePnp IRP_MN_START_DEVICE\n");
+            //
+            // register device interface 
+            //
+            Status = SetDeviceInterface(TRUE);
+            break;
+        }
+        case IRP_MN_QUERY_CAPABILITIES:
+        {
+            DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_CAPABILITIES\n");
+
+            DeviceCapabilities = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities;
+
+            DeviceCapabilities->LockSupported = FALSE;
+            DeviceCapabilities->EjectSupported = FALSE;
+            DeviceCapabilities->Removable = FALSE;
+            DeviceCapabilities->DockDevice = FALSE;
+            DeviceCapabilities->UniqueID = FALSE;
+            DeviceCapabilities->SilentInstall = FALSE;
+            DeviceCapabilities->RawDeviceOK = FALSE;
+            DeviceCapabilities->SurpriseRemovalOK = FALSE;
+            DeviceCapabilities->Address = 0;
+            DeviceCapabilities->UINumber = 0;
+            DeviceCapabilities->DeviceD2 = 1;
+
+            /* FIXME */
+            DeviceCapabilities->HardwareDisabled = FALSE;
+            DeviceCapabilities->NoDisplayInUI = FALSE;
+            DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
+            for (Index = 0; Index < PowerSystemMaximum; Index++)
+                DeviceCapabilities->DeviceState[Index] = PowerDeviceD3;
+            DeviceCapabilities->DeviceWake = PowerDeviceUnspecified;
+            DeviceCapabilities->D1Latency = 0;
+            DeviceCapabilities->D2Latency = 0;
+            DeviceCapabilities->D3Latency = 0;
+
+            Status = STATUS_SUCCESS;
+            break;
+        }
+        case IRP_MN_QUERY_INTERFACE:
+        {
+            DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_INTERFACE\n");
+
+            //
+            // handle device interface requests
+            //
+            Status = HandleQueryInterface(IoStack);
+            break;
+        }
+        case IRP_MN_REMOVE_DEVICE:
+        {
+            DPRINT1("CHubController::HandlePnp IRP_MN_REMOVE_DEVICE\n");
+
+            //
+            // deactivate device interface for BUS PDO
+            //
+            SetDeviceInterface(FALSE);
+
+            //
+            // complete the request first
+            //
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+            //
+            // now delete device
+            //
+            IoDeleteDevice(m_HubControllerDeviceObject);
+
+            //
+            // nullify pointer
+            //
+            m_HubControllerDeviceObject = 0;
+            return STATUS_SUCCESS;
+        }
+        case IRP_MN_QUERY_BUS_INFORMATION:
+        {
+            DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n");
+
+            //
+            // allocate buffer for bus guid
+            //
+            Guid = (LPGUID)ExAllocatePool(PagedPool, sizeof(GUID));
+            if (Guid)
+            {
+                //
+                // copy BUS guid
+                //
+                RtlMoveMemory(Guid, &GUID_BUS_TYPE_USB, sizeof(GUID));
+                Status = STATUS_SUCCESS;
+                Irp->IoStatus.Information = (ULONG_PTR)Guid;
+            }
+            else
+            {
+                //
+                // no memory
+                //
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+            }
+            break;
+        }
+        case IRP_MN_STOP_DEVICE:
+        {
+            DPRINT1("CHubController::HandlePnp IRP_MN_STOP_DEVICE\n");
+            //
+            // stop device
+            //
+            Status = STATUS_SUCCESS;
+            break;
+        }
+        default:
+        {
+            DPRINT1("CHubController::HandlePnp Unhandeled %x\n", IoStack->MinorFunction);
+            Status = STATUS_NOT_SUPPORTED;
+            break;
+        }
+    }
+
+    //
+    // complete request
+    //
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    //
+    // done
+    //
+    return Status;
+}
+
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::HandlePower(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN OUT PIRP Irp)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::HandleDeviceControl(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN OUT PIRP Irp)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+
+NTSTATUS
+CHubController::HandleQueryInterface(
+    PIO_STACK_LOCATION IoStack)
+{
+    UNICODE_STRING GuidBuffer;
+    NTSTATUS Status;
+
+    if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_HUB_GUID))
+    {
+        DPRINT1("HandleQueryInterface> UNIMPLEMENTED USB_BUS_INTERFACE_HUB_GUID Version %x\n", IoStack->Parameters.QueryInterface.Version);
+
+    }
+    else if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_USBDI_GUID))
+    {
+        DPRINT1("HandleQueryInterface> UNIMPLEMENTED USB_BUS_INTERFACE_USBDI_GUID Version %x\n", IoStack->Parameters.QueryInterface.Version);
+    }
+    else
+    {
+        //
+        // convert guid to string
+        //
+        Status = RtlStringFromGUID(*IoStack->Parameters.QueryInterface.InterfaceType, &GuidBuffer);
+        if (NT_SUCCESS(Status))
+        {
+            //
+            // print interface
+            //
+            DPRINT1("HandleQueryInterface GUID: %wZ Version %x\n", &GuidBuffer, IoStack->Parameters.QueryInterface.Version);
+
+            //
+            // free guid buffer
+            //
+            RtlFreeUnicodeString(&GuidBuffer);
+        }
+    }
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+CHubController::SetDeviceInterface(
+    BOOLEAN Enable)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    if (Enable)
+    {
+        //
+        // register device interface
+        //
+        Status = IoRegisterDeviceInterface(m_HubControllerDeviceObject, &GUID_DEVINTERFACE_USB_HUB, 0, &m_HubDeviceInterfaceString);
+
+        if (NT_SUCCESS(Status))
+        {
+            //
+            // now enable the device interface
+            //
+            Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, TRUE);
+
+            //
+            // enable interface
+            //
+            m_InterfaceEnabled = TRUE;
+        }
+    }
+    else if (m_InterfaceEnabled)
+    {
+        //
+        // disable device interface
+        //
+        Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, FALSE);
+
+        if (NT_SUCCESS(Status))
+        {
+            //
+            // now delete interface string
+            //
+            RtlFreeUnicodeString(&m_HubDeviceInterfaceString);
+        }
+
+        //
+        // disable interface
+        //
+        m_InterfaceEnabled = FALSE;
+    }
+
+    //
+    // done
+    //
+    return Status;
+}
+
+NTSTATUS
+CHubController::CreatePDO(
+    PDRIVER_OBJECT DriverObject,
+    PDEVICE_OBJECT * OutDeviceObject)
+{
+    WCHAR CharDeviceName[64];
+    NTSTATUS Status;
+    ULONG UsbDeviceNumber = 0;
+    UNICODE_STRING DeviceName;
+
+    while (TRUE)
+    {
+        //
+        // construct device name
+        //
+        swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber);
+
+        //
+        // initialize device name
+        //
+        RtlInitUnicodeString(&DeviceName, CharDeviceName);
+
+        //
+        // create device
+        //
+        Status = IoCreateDevice(DriverObject,
+                                sizeof(COMMON_DEVICE_EXTENSION),
+                                &DeviceName,
+                                FILE_DEVICE_CONTROLLER,
+                                0,
+                                FALSE,
+                                OutDeviceObject);
+
+        /* check for success */
+        if (NT_SUCCESS(Status))
+            break;
+
+        //
+        // is there a device object with that same name
+        //
+        if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
+        {
+            //
+            // Try the next name
+            //
+            UsbDeviceNumber++;
+            continue;
+        }
+
+        //
+        // bail out on other errors
+        //
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName, Status);
+            return Status;
+        }
+    }
+
+    //
+    // store PDO number
+    //
+    //m_PDODeviceNumber = UsbDeviceNumber;
+
+    DPRINT1("CreateFDO: DeviceName %wZ\n", &DeviceName);
+
+    /* done */
+    return Status;
+}
+
+
+
+NTSTATUS
+CreateHubController(
+    PHUBCONTROLLER *OutHcdController)
+{
+    PHUBCONTROLLER This;
+
+    //
+    // allocate controller
+    //
+    This = new(NonPagedPool, TAG_USBEHCI) CHubController(0);
+    if (!This)
+    {
+        //
+        // failed to allocate
+        //
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // add reference count
+    //
+    This->AddRef();
+
+    //
+    // return result
+    //
+    *OutHcdController = (PHUBCONTROLLER)This;
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
index ba289fd..3abb71a 100644 (file)
@@ -103,33 +103,6 @@ DECLARE_INTERFACE_(IHCDController, IUnknown)
                                 IN PDRIVER_OBJECT DriverObject,
                                 IN PDEVICE_OBJECT PhysicalDeviceObject) = 0;
 
-//-----------------------------------------------------------------------------------------
-//
-// HandlePnp
-//
-// Description: This function handles all pnp requests
-
-    virtual NTSTATUS HandlePnp(IN PDEVICE_OBJECT DeviceObject,
-                               IN OUT PIRP Irp) = 0;
-
-//-----------------------------------------------------------------------------------------
-//
-// HandlePower
-//
-// Description: This function handles all power pnp requests
-//
-    virtual NTSTATUS HandlePower(IN PDEVICE_OBJECT DeviceObject,
-                                 IN OUT PIRP Irp) = 0;
-
-//-----------------------------------------------------------------------------------------
-//
-// HandleDeviceControl
-//
-// Description: handles device io control requests
-
-    virtual NTSTATUS HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject,
-                                         IN OUT PIRP Irp) = 0;
-
 };
 
 typedef IHCDController *PHCDCONTROLLER;
@@ -178,14 +151,6 @@ DECLARE_INTERFACE_(IUSBHardwareDevice, IUnknown)
 
     virtual NTSTATUS PnpStop(void) = 0;
 
-//-----------------------------------------------------------------------------------------
-//
-// HandlePower
-//
-// Description: handles power requests
-
-    virtual NTSTATUS HandlePower(PIRP Irp) = 0;
-
 //-----------------------------------------------------------------------------------------
 //
 // GetDeviceDetails
@@ -451,11 +416,35 @@ DECLARE_INTERFACE_(IHubController, IUnknown)
 //
 // Description: Initializes the hub controller
 
-    virtual NTSTATUS Initialize(IN PHCDCONTROLLER Controller,
+    virtual NTSTATUS Initialize(IN PDRIVER_OBJECT DriverObject,
+                                IN PHCDCONTROLLER Controller,
                                 IN PUSBHARDWAREDEVICE Device,
                                 IN BOOLEAN IsRootHubDevice,
                                 IN ULONG DeviceAddress) = 0;
 
+//----------------------------------------------------------------------------------------
+//
+// GetHubControllerDeviceObject
+//
+// Description: Returns the hub controller device object
+
+    virtual NTSTATUS GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject) = 0;
+
+};
+
+typedef IHubController *PHUBCONTROLLER;
+
+//=========================================================================================
+//
+// class IDispatchIrp
+//
+// Description: This class is used to handle irp dispatch requests
+// 
+
+DECLARE_INTERFACE_(IDispatchIrp, IUnknown)
+{
+    DEFINE_ABSTRACT_UNKNOWN()
+
 //-----------------------------------------------------------------------------------------
 //
 // HandlePnp
@@ -484,7 +473,6 @@ DECLARE_INTERFACE_(IHubController, IUnknown)
                                          IN OUT PIRP Irp) = 0;
 };
 
-typedef IHubController *PHUBCONTROLLER;
-
+typedef IDispatchIrp *PDISPATCHIRP;
 
 #endif
index 28bf19b..7d535c5 100644 (file)
@@ -79,12 +79,7 @@ EHCI_Dispatch(
     //
     // sanity checks
     //
-    PC_ASSERT(DeviceExtension->HcdController);
-
-    //
-    // FIXME: support bus device
-    //
-    PC_ASSERT(DeviceExtension->IsHub == FALSE);
+    PC_ASSERT(DeviceExtension->Dispatcher);
 
     switch(IoStack->MajorFunction)
     {
@@ -93,7 +88,7 @@ EHCI_Dispatch(
             //
             // dispatch pnp
             //
-            return DeviceExtension->HcdController->HandlePnp(DeviceObject, Irp);
+            return DeviceExtension->Dispatcher->HandlePnp(DeviceObject, Irp);
         }
 
         case IRP_MJ_POWER:
@@ -101,7 +96,7 @@ EHCI_Dispatch(
             //
             // dispatch pnp
             //
-            return DeviceExtension->HcdController->HandlePower(DeviceObject, Irp);
+            return DeviceExtension->Dispatcher->HandlePower(DeviceObject, Irp);
         }
         case IRP_MJ_SYSTEM_CONTROL:
         case IRP_MJ_DEVICE_CONTROL:
@@ -109,7 +104,7 @@ EHCI_Dispatch(
             //
             // dispatch pnp
             //
-            return DeviceExtension->HcdController->HandleDeviceControl(DeviceObject, Irp);
+            return DeviceExtension->Dispatcher->HandleDeviceControl(DeviceObject, Irp);
         }
         case IRP_MJ_CREATE:
         {
@@ -134,7 +129,6 @@ EHCI_Dispatch(
     Irp->IoStatus.Status = Status;
     IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
-
     return Status;
 }
 
index bf651e0..f602eeb 100644 (file)
@@ -25,11 +25,7 @@ typedef struct
 {
     BOOLEAN IsFDO;                                               // is device a FDO or PDO
     BOOLEAN IsHub;                                               // is device a hub / child - not yet used
-    union
-    {
-        PHCDCONTROLLER HcdController;                            // hcd controller
-        PHUBCONTROLLER HubController;                            // hub controller
-    };
+    PDISPATCHIRP Dispatcher;                                     // dispatches the code
 }COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
 
 //
@@ -62,6 +58,6 @@ NTSTATUS NTAPI SyncForwardIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp);
 //
 // root_hub_controller.cpp
 //
-NTSTATUS CreateRootHubController(PHUBCONTROLLER * OutHubController);
+NTSTATUS CreateHubController(PHUBCONTROLLER * OutHubController);
 
 #endif