[USB-BRINGUP-TRUNK]
authorCameron Gutman <aicommander@gmail.com>
Fri, 20 Jan 2012 21:07:56 +0000 (21:07 +0000)
committerCameron Gutman <aicommander@gmail.com>
Fri, 20 Jan 2012 21:07:56 +0000 (21:07 +0000)
- Merge 51335-53500

svn path=/branches/usb-bringup-trunk/; revision=55019

62 files changed:
dll/win32/hid/hid.c
dll/win32/hid/stubs.c
drivers/usb/CMakeLists.txt
drivers/usb/hidparse/CMakeLists.txt [new file with mode: 0644]
drivers/usb/hidparse/hidparse.c [new file with mode: 0644]
drivers/usb/hidparse/hidparse.h [new file with mode: 0644]
drivers/usb/hidparse/hidparse.rc [new file with mode: 0644]
drivers/usb/hidparse/hidparse.spec [new file with mode: 0644]
drivers/usb/hidusb/CMakeLists.txt [new file with mode: 0644]
drivers/usb/hidusb/hidusb.c [new file with mode: 0644]
drivers/usb/hidusb/hidusb.h [new file with mode: 0644]
drivers/usb/usbd/usbd.spec
drivers/usb/usbehci_new/CMakeLists.txt [new file with mode: 0644]
drivers/usb/usbehci_new/hardware.cpp [new file with mode: 0644]
drivers/usb/usbehci_new/hardware.h [new file with mode: 0644]
drivers/usb/usbehci_new/hcd_controller.cpp [new file with mode: 0644]
drivers/usb/usbehci_new/hub_controller.cpp [new file with mode: 0644]
drivers/usb/usbehci_new/interfaces.h [new file with mode: 0644]
drivers/usb/usbehci_new/memory_manager.cpp [new file with mode: 0644]
drivers/usb/usbehci_new/misc.cpp [new file with mode: 0644]
drivers/usb/usbehci_new/purecall.cpp [new file with mode: 0644]
drivers/usb/usbehci_new/usb_device.cpp [new file with mode: 0644]
drivers/usb/usbehci_new/usb_queue.cpp [new file with mode: 0644]
drivers/usb/usbehci_new/usb_request.cpp [new file with mode: 0644]
drivers/usb/usbehci_new/usbehci.cpp [new file with mode: 0644]
drivers/usb/usbehci_new/usbehci.h [new file with mode: 0644]
drivers/usb/usbehci_new/usbehci.rc [new file with mode: 0644]
drivers/usb/usbhub_new/CMakeLists.txt [new file with mode: 0644]
drivers/usb/usbhub_new/fdo.c [new file with mode: 0644]
drivers/usb/usbhub_new/misc.c [new file with mode: 0644]
drivers/usb/usbhub_new/pdo.c [new file with mode: 0644]
drivers/usb/usbhub_new/usbhub.c [new file with mode: 0644]
drivers/usb/usbhub_new/usbhub.h [new file with mode: 0644]
drivers/usb/usbhub_new/usbhub.rc [new file with mode: 0644]
drivers/usb/usbohci/CMakeLists.txt [new file with mode: 0644]
drivers/usb/usbohci/hardware.cpp [new file with mode: 0644]
drivers/usb/usbohci/hardware.h [new file with mode: 0644]
drivers/usb/usbohci/hcd_controller.cpp [new file with mode: 0644]
drivers/usb/usbohci/hub_controller.cpp [new file with mode: 0644]
drivers/usb/usbohci/interfaces.h [new file with mode: 0644]
drivers/usb/usbohci/memory_manager.cpp [new file with mode: 0644]
drivers/usb/usbohci/misc.cpp [new file with mode: 0644]
drivers/usb/usbohci/purecall.cpp [new file with mode: 0644]
drivers/usb/usbohci/usb_device.cpp [new file with mode: 0644]
drivers/usb/usbohci/usb_queue.cpp [new file with mode: 0644]
drivers/usb/usbohci/usb_request.cpp [new file with mode: 0644]
drivers/usb/usbohci/usbohci.cpp [new file with mode: 0644]
drivers/usb/usbohci/usbohci.h [new file with mode: 0644]
drivers/usb/usbohci/usbohci.rc [new file with mode: 0644]
drivers/usb/usbstor/CMakeLists.txt
drivers/usb/usbstor/descriptor.c [new file with mode: 0644]
drivers/usb/usbstor/disk.c [new file with mode: 0644]
drivers/usb/usbstor/error.c [new file with mode: 0644]
drivers/usb/usbstor/fdo.c [new file with mode: 0644]
drivers/usb/usbstor/misc.c [new file with mode: 0644]
drivers/usb/usbstor/pdo.c [new file with mode: 0644]
drivers/usb/usbstor/queue.c [new file with mode: 0644]
drivers/usb/usbstor/scsi.c [new file with mode: 0644]
drivers/usb/usbstor/usbstor.c
drivers/usb/usbstor/usbstor.h
include/ddk/hidpddi.h [new file with mode: 0644]
include/ddk/hidport.h [new file with mode: 0644]

index 89cf57c..bf5bb5f 100644 (file)
@@ -70,7 +70,7 @@ HidD_FlushQueue(IN HANDLE HidDeviceObject)
   return DeviceIoControl(HidDeviceObject, IOCTL_HID_FLUSH_QUEUE,
                          NULL, 0,
                          NULL, 0,
-                         &RetLen, NULL);
+                         &RetLen, NULL) != 0;
 }
 
 
@@ -150,7 +150,7 @@ HidD_GetFeature(IN HANDLE HidDeviceObject,
   return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_FEATURE,
                          NULL, 0,
                          ReportBuffer, ReportBufferLength,
-                         &RetLen, NULL);
+                         &RetLen, NULL) != 0;
 }
 
 
@@ -182,7 +182,7 @@ HidD_GetInputReport(IN HANDLE HidDeviceObject,
   return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_INPUT_REPORT,
                          NULL, 0,
                          ReportBuffer, ReportBufferLength,
-                         &RetLen, NULL);
+                         &RetLen, NULL) != 0;
 }
 
 
@@ -201,7 +201,7 @@ HidD_GetManufacturerString(IN HANDLE HidDeviceObject,
   return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_MANUFACTURER_STRING,
                          NULL, 0,
                          Buffer, BufferLength,
-                         &RetLen, NULL);
+                         &RetLen, NULL) != 0;
 }
 
 
@@ -219,7 +219,7 @@ HidD_GetNumInputBuffers(IN HANDLE HidDeviceObject,
   return DeviceIoControl(HidDeviceObject, IOCTL_GET_NUM_DEVICE_INPUT_BUFFERS,
                          NULL, 0,
                          NumberBuffers, sizeof(ULONG),
-                         &RetLen, NULL);
+                         &RetLen, NULL) != 0;
 }
 
 
@@ -238,7 +238,7 @@ HidD_GetPhysicalDescriptor(IN HANDLE HidDeviceObject,
   return DeviceIoControl(HidDeviceObject, IOCTL_GET_PHYSICAL_DESCRIPTOR,
                          NULL, 0,
                          Buffer, BufferLength,
-                         &RetLen, NULL);
+                         &RetLen, NULL) != 0;
 }
 
 
@@ -254,7 +254,7 @@ HidD_GetPreparsedData(IN HANDLE HidDeviceObject,
 {
   HID_COLLECTION_INFORMATION hci;
   DWORD RetLen;
-  BOOL Ret;
+  BOOLEAN Ret;
 
   if(PreparsedData == NULL)
   {
@@ -279,7 +279,7 @@ HidD_GetPreparsedData(IN HANDLE HidDeviceObject,
   Ret = DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_COLLECTION_DESCRIPTOR,
                         NULL, 0,
                         *PreparsedData, hci.DescriptorSize,
-                        &RetLen, NULL);
+                        &RetLen, NULL) != 0;
 
   if(!Ret)
   {
@@ -312,7 +312,7 @@ HidD_GetProductString(IN HANDLE HidDeviceObject,
   return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_PRODUCT_STRING,
                          NULL, 0,
                          Buffer, BufferLength,
-                         &RetLen, NULL);
+                         &RetLen, NULL) != 0;
 }
 
 
@@ -331,7 +331,7 @@ HidD_GetSerialNumberString(IN HANDLE HidDeviceObject,
   return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_SERIALNUMBER_STRING,
                          NULL, 0,
                          Buffer, BufferLength,
-                         &RetLen, NULL);
+                         &RetLen, NULL) != 0;
 }
 
 
@@ -394,7 +394,7 @@ HidD_SetFeature(IN HANDLE HidDeviceObject,
   return DeviceIoControl(HidDeviceObject, IOCTL_HID_SET_FEATURE,
                          ReportBuffer, ReportBufferLength,
                          NULL, 0,
-                         &RetLen, NULL);
+                         &RetLen, NULL) != 0;
 }
 
 
@@ -412,7 +412,7 @@ HidD_SetNumInputBuffers(IN HANDLE HidDeviceObject,
   return DeviceIoControl(HidDeviceObject, IOCTL_SET_NUM_DEVICE_INPUT_BUFFERS,
                          &NumberBuffers, sizeof(ULONG),
                          NULL, 0,
-                         &RetLen, NULL);
+                         &RetLen, NULL) != 0;
 }
 
 
@@ -431,7 +431,112 @@ HidD_SetOutputReport(IN HANDLE HidDeviceObject,
   return DeviceIoControl(HidDeviceObject, IOCTL_HID_SET_OUTPUT_REPORT,
                          ReportBuffer, ReportBufferLength,
                          NULL, 0,
-                         &RetLen, NULL);
+                         &RetLen, NULL) != 0;
 }
 
+/*
+ * HidD_GetIndexedString                                                       EXPORTED
+ *
+ * @implemented
+ */
+HIDAPI
+BOOLEAN WINAPI
+HidD_GetIndexedString(IN HANDLE HidDeviceObject,
+                      IN ULONG StringIndex,
+                      OUT PVOID Buffer,
+                      IN ULONG BufferLength)
+{
+  DWORD RetLen;
+  return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_INDEXED_STRING,
+                         &StringIndex, sizeof(ULONG),
+                         Buffer, BufferLength,
+                         &RetLen, NULL) != 0;
+}
+
+/*
+ * HidD_GetMsGenreDescriptor                                                   EXPORTED
+ *
+ * @implemented
+ */
+HIDAPI
+BOOLEAN WINAPI
+HidD_GetMsGenreDescriptor(IN HANDLE HidDeviceObject,
+                          OUT PVOID Buffer,
+                          IN ULONG BufferLength)
+{
+  DWORD RetLen;
+  return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_MS_GENRE_DESCRIPTOR,
+                         0, 0,
+                         Buffer, BufferLength,
+                         &RetLen, NULL) != 0;
+}
+
+/*
+ * HidD_GetConfiguration                                                       EXPORTED
+ *
+ * @implemented
+ */
+HIDAPI
+BOOLEAN WINAPI
+HidD_GetConfiguration(IN HANDLE HidDeviceObject,
+                      OUT PHIDD_CONFIGURATION Configuration,
+                      IN ULONG ConfigurationLength)
+{
+
+  // magic cookie
+  Configuration->cookie = (PVOID)HidD_GetConfiguration;
+
+  return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_DRIVER_CONFIG,
+                         0, 0,
+                         &Configuration->size, ConfigurationLength - sizeof(ULONG),
+                         (PULONG)&Configuration->cookie, NULL) != 0;
+}
+
+/*
+ * HidD_SetConfiguration                                                       EXPORTED
+ *
+ * @implemented
+ */
+HIDAPI
+BOOLEAN WINAPI
+HidD_SetConfiguration(IN HANDLE HidDeviceObject,
+                      IN PHIDD_CONFIGURATION Configuration,
+                      IN ULONG ConfigurationLength)
+{
+    BOOLEAN Ret = FALSE;
+
+    if (Configuration->cookie == (PVOID)HidD_GetConfiguration)
+    {
+        Ret = DeviceIoControl(HidDeviceObject, IOCTL_HID_SET_DRIVER_CONFIG,
+                              0, 0,
+                              (PVOID)&Configuration->size, ConfigurationLength - sizeof(ULONG),
+                              (PULONG)&Configuration->cookie, NULL) != 0;
+    }
+    else
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+    }
+
+    return Ret;
+}
+
+/*
+ * HidP_GetUsagesEx                                                    EXPORTED
+ *
+ * @implemented
+ */
+HIDAPI
+NTSTATUS WINAPI
+HidP_GetUsagesEx(IN HIDP_REPORT_TYPE ReportType,
+                 IN USHORT LinkCollection,
+                 OUT PUSAGE_AND_PAGE ButtonList,
+                 IN OUT ULONG *UsageLength,
+                 IN PHIDP_PREPARSED_DATA PreparsedData,
+                 IN PCHAR Report,
+                 IN ULONG ReportLength)
+{
+    return HidP_GetUsages(ReportType, ButtonList->UsagePage, LinkCollection, &ButtonList->Usage, UsageLength, PreparsedData, Report, ReportLength);
+}
+
+
 /* EOF */
index cb4543d..1e37efa 100644 (file)
  */
 #include <precomp.h>
 
-/*
- * @unimplemented
- */
-HIDAPI
-BOOLEAN WINAPI
-HidD_GetConfiguration(IN HANDLE HidDeviceObject,
-                      OUT PHIDD_CONFIGURATION Configuration,
-                      IN ULONG ConfigurationLength)
-{
-  UNIMPLEMENTED;
-  return FALSE;
-}
-
-
-/*
- * @unimplemented
- */
-HIDAPI
-BOOLEAN WINAPI
-HidD_GetIndexedString(IN HANDLE HidDeviceObject,
-                      IN ULONG StringIndex,
-                      OUT PVOID Buffer,
-                      IN ULONG BufferLength)
-{
-  UNIMPLEMENTED;
-  return FALSE;
-}
-
-
-/*
- * @unimplemented
- */
-HIDAPI
-BOOLEAN WINAPI
-HidD_GetMsGenreDescriptor(IN HANDLE HidDeviceObject,
-                          OUT PVOID Buffer,
-                          IN ULONG BufferLength)
-{
-  UNIMPLEMENTED;
-  return FALSE;
-}
-
-
-/*
- * @unimplemented
- */
-HIDAPI
-BOOLEAN WINAPI
-HidD_SetConfiguration(IN HANDLE HidDeviceObject,
-                      IN PHIDD_CONFIGURATION Configuration,
-                      IN ULONG ConfigurationLength)
-{
-  UNIMPLEMENTED;
-  return FALSE;
-}
-
-
 /*
  * @unimplemented
  */
@@ -241,24 +184,6 @@ HidP_GetUsages(IN HIDP_REPORT_TYPE ReportType,
 }
 
 
-/*
- * @unimplemented
- */
-HIDAPI
-NTSTATUS WINAPI
-HidP_GetUsagesEx(IN HIDP_REPORT_TYPE ReportType,
-                 IN USHORT LinkCollection,
-                 OUT PUSAGE_AND_PAGE ButtonList,
-                 IN OUT ULONG *UsageLength,
-                 IN PHIDP_PREPARSED_DATA PreparsedData,
-                 IN PCHAR Report,
-                 IN ULONG ReportLength)
-{
-  UNIMPLEMENTED;
-  return HIDP_STATUS_NOT_IMPLEMENTED;
-}
-
-
 /*
  * @unimplemented
  */
index 291a429..d208ed2 100644 (file)
@@ -1,6 +1,7 @@
-
+add_subdirectory(hidparse)
 add_subdirectory(nt4compat)
 add_subdirectory(usbd)
-#add_subdirectory(usbehci) The USB branch has usbehci_new
-#add_subdirectory(usbhub) Compiles, just skipped in trunk
-#add_subdirectory(usbstor) Compiles, just skipped in trunk
+add_subdirectory(usbehci_new)
+add_subdirectory(usbhub_new)
+add_subdirectory(usbohci)
+add_subdirectory(usbstor)
\ No newline at end of file
diff --git a/drivers/usb/hidparse/CMakeLists.txt b/drivers/usb/hidparse/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a6740cc
--- /dev/null
@@ -0,0 +1,14 @@
+
+spec2def(hidparse.sys hidparse.spec)
+add_definitions(-DDEBUG_MODE)
+
+include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
+
+add_library(hidparse SHARED hidparse.c hidparse.rc ${CMAKE_CURRENT_BINARY_DIR}/hidparse.def)
+
+set_module_type(hidparse kernelmodedriver)
+add_importlibs(hidparse ntoskrnl)
+add_cab_target(hidparse 2)
+
+add_cab_target(hidparse 2)
+add_importlib_target(hidparse.spec)
diff --git a/drivers/usb/hidparse/hidparse.c b/drivers/usb/hidparse/hidparse.c
new file mode 100644 (file)
index 0000000..c3cce18
--- /dev/null
@@ -0,0 +1,499 @@
+/*
+ * PROJECT:     ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/usb/hidparse/hidparse.c
+ * PURPOSE:     HID Parser
+ * PROGRAMMERS:
+ *              Michael Martin (michael.martin@reactos.org)
+ *              Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+#include "hidparse.h"
+
+
+VOID
+HidP_FreeCollectionDescription (
+    IN PHIDP_DEVICE_DESC   DeviceDescription)
+{
+    DPRINT1("HidP_FreeCollectionDescription DeviceDescription %p\n", DeviceDescription);
+
+    //
+    // free collection
+    //
+    ExFreePool(DeviceDescription->CollectionDesc);
+
+    //
+    // free report ids
+    //
+    ExFreePool(DeviceDescription->ReportIDs);
+
+    //
+    // free description itself
+    //
+    ExFreePool(DeviceDescription);
+
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_GetButtonCaps(
+    HIDP_REPORT_TYPE ReportType,
+    PHIDP_BUTTON_CAPS ButtonCaps,
+    PUSHORT ButtonCapsLength,
+    PHIDP_PREPARSED_DATA PreparsedData)
+{
+    return HidP_GetSpecificButtonCaps(ReportType, 0, 0, 0, ButtonCaps, (PULONG)ButtonCapsLength, PreparsedData);
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_GetSpecificButtonCaps(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN USAGE  UsagePage,
+  IN USHORT  LinkCollection,
+  IN USAGE  Usage,
+  OUT PHIDP_BUTTON_CAPS  ButtonCaps,
+  IN OUT PULONG  ButtonCapsLength,
+  IN PHIDP_PREPARSED_DATA  PreparsedData)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_GetCaps(
+    IN PHIDP_PREPARSED_DATA  PreparsedData,
+    OUT PHIDP_CAPS  Capabilities)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+HidP_GetCollectionDescription(
+    IN PHIDP_REPORT_DESCRIPTOR ReportDesc,
+    IN ULONG DescLength,
+    IN POOL_TYPE PoolType,
+    OUT PHIDP_DEVICE_DESC DeviceDescription)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_GetData(
+  IN HIDP_REPORT_TYPE  ReportType,
+  OUT PHIDP_DATA  DataList,
+  IN OUT PULONG  DataLength,
+  IN PHIDP_PREPARSED_DATA  PreparsedData,
+  IN PCHAR  Report,
+  IN ULONG  ReportLength)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_GetExtendedAttributes(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN USHORT  DataIndex,
+  IN PHIDP_PREPARSED_DATA  PreparsedData,
+  OUT PHIDP_EXTENDED_ATTRIBUTES  Attributes,
+  IN OUT PULONG  LengthAttributes)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_GetLinkCollectionNodes(
+    OUT PHIDP_LINK_COLLECTION_NODE  LinkCollectionNodes,
+    IN OUT PULONG  LinkCollectionNodesLength,
+    IN PHIDP_PREPARSED_DATA  PreparsedData)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_GetScaledUsageValue(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN USAGE  UsagePage,
+  IN USHORT  LinkCollection  OPTIONAL,
+  IN USAGE  Usage,
+  OUT PLONG  UsageValue,
+  IN PHIDP_PREPARSED_DATA  PreparsedData,
+  IN PCHAR  Report,
+  IN ULONG  ReportLength)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_GetUsageValue(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN USAGE  UsagePage,
+  IN USHORT  LinkCollection,
+  IN USAGE  Usage,
+  OUT PULONG  UsageValue,
+  IN PHIDP_PREPARSED_DATA  PreparsedData,
+  IN PCHAR  Report,
+  IN ULONG  ReportLength)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_UsageListDifference(
+  IN PUSAGE  PreviousUsageList,
+  IN PUSAGE  CurrentUsageList,
+  OUT PUSAGE  BreakUsageList,
+  OUT PUSAGE  MakeUsageList,
+  IN ULONG  UsageListLength)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_GetSpecificValueCaps(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN USAGE  UsagePage,
+  IN USHORT  LinkCollection,
+  IN USAGE  Usage,
+  OUT PHIDP_VALUE_CAPS  ValueCaps,
+  IN OUT PULONG  ValueCapsLength,
+  IN PHIDP_PREPARSED_DATA  PreparsedData)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+ULONG
+NTAPI
+HidP_MaxUsageListLength(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN USAGE  UsagePage  OPTIONAL,
+  IN PHIDP_PREPARSED_DATA  PreparsedData)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_GetUsages(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN USAGE  UsagePage,
+  IN USHORT  LinkCollection  OPTIONAL,
+  OUT USAGE  *UsageList,
+  IN OUT ULONG  *UsageLength,
+  IN PHIDP_PREPARSED_DATA  PreparsedData,
+  IN PCHAR  Report,
+  IN ULONG  ReportLength)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+HidP_SysPowerEvent (
+    IN PCHAR HidPacket,
+    IN USHORT HidPacketLength,
+    IN PHIDP_PREPARSED_DATA Ppd,
+    OUT PULONG OutputBuffer)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+HidP_SysPowerCaps (
+    IN PHIDP_PREPARSED_DATA Ppd,
+    OUT PULONG OutputBuffer)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_GetUsageValueArray(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN USAGE  UsagePage,
+  IN USHORT  LinkCollection  OPTIONAL,
+  IN USAGE  Usage,
+  OUT PCHAR  UsageValue,
+  IN USHORT  UsageValueByteLength,
+  IN PHIDP_PREPARSED_DATA  PreparsedData,
+  IN PCHAR  Report,
+  IN ULONG  ReportLength)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_GetUsagesEx(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN USHORT  LinkCollection,
+  OUT PUSAGE_AND_PAGE  ButtonList,
+  IN OUT ULONG  *UsageLength,
+  IN PHIDP_PREPARSED_DATA  PreparsedData,
+  IN PCHAR  Report,
+  IN ULONG  ReportLength)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_UsageAndPageListDifference(
+   IN PUSAGE_AND_PAGE  PreviousUsageList,
+   IN PUSAGE_AND_PAGE  CurrentUsageList,
+   OUT PUSAGE_AND_PAGE  BreakUsageList,
+   OUT PUSAGE_AND_PAGE  MakeUsageList,
+   IN ULONG  UsageListLength)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_UnsetUsages(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN USAGE  UsagePage,
+  IN USHORT  LinkCollection,
+  IN PUSAGE  UsageList,
+  IN OUT PULONG  UsageLength,
+  IN PHIDP_PREPARSED_DATA  PreparsedData,
+  IN OUT PCHAR  Report,
+  IN ULONG  ReportLength)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_TranslateUsagesToI8042ScanCodes(
+  IN PUSAGE  ChangedUsageList,
+  IN ULONG  UsageListLength,
+  IN HIDP_KEYBOARD_DIRECTION  KeyAction,
+  IN OUT PHIDP_KEYBOARD_MODIFIER_STATE  ModifierState,
+  IN PHIDP_INSERT_SCANCODES  InsertCodesProcedure,
+  IN PVOID  InsertCodesContext)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_TranslateUsageAndPagesToI8042ScanCodes(
+   IN PUSAGE_AND_PAGE  ChangedUsageList,
+   IN ULONG  UsageListLength,
+   IN HIDP_KEYBOARD_DIRECTION  KeyAction,
+   IN OUT PHIDP_KEYBOARD_MODIFIER_STATE  ModifierState,
+   IN PHIDP_INSERT_SCANCODES  InsertCodesProcedure,
+   IN PVOID  InsertCodesContext)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_SetUsages(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN USAGE  UsagePage,
+  IN USHORT  LinkCollection,
+  IN PUSAGE  UsageList,
+  IN OUT PULONG  UsageLength,
+  IN PHIDP_PREPARSED_DATA  PreparsedData,
+  IN OUT PCHAR  Report,
+  IN ULONG  ReportLength)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_SetUsageValueArray(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN USAGE  UsagePage,
+  IN USHORT  LinkCollection  OPTIONAL,
+  IN USAGE  Usage,
+  IN PCHAR  UsageValue,
+  IN USHORT  UsageValueByteLength,
+  IN PHIDP_PREPARSED_DATA  PreparsedData,
+  OUT PCHAR  Report,
+  IN ULONG  ReportLength)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_SetUsageValue(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN USAGE  UsagePage,
+  IN USHORT  LinkCollection,
+  IN USAGE  Usage,
+  IN ULONG  UsageValue,
+  IN PHIDP_PREPARSED_DATA  PreparsedData,
+  IN OUT PCHAR  Report,
+  IN ULONG  ReportLength)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_SetScaledUsageValue(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN USAGE  UsagePage,
+  IN USHORT  LinkCollection  OPTIONAL,
+  IN USAGE  Usage,
+  IN LONG  UsageValue,
+  IN PHIDP_PREPARSED_DATA  PreparsedData,
+  IN OUT PCHAR  Report,
+  IN ULONG  ReportLength)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_SetData(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN PHIDP_DATA  DataList,
+  IN OUT PULONG  DataLength,
+  IN PHIDP_PREPARSED_DATA  PreparsedData,
+  IN OUT PCHAR  Report,
+  IN ULONG  ReportLength)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+ULONG
+NTAPI
+HidP_MaxDataListLength(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN PHIDP_PREPARSED_DATA  PreparsedData)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_InitializeReportForID(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN UCHAR  ReportID,
+  IN PHIDP_PREPARSED_DATA  PreparsedData,
+  IN OUT PCHAR  Report,
+  IN ULONG  ReportLength)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_GetValueCaps(
+  HIDP_REPORT_TYPE ReportType,
+  PHIDP_VALUE_CAPS ValueCaps,
+  PULONG ValueCapsLength,
+  PHIDP_PREPARSED_DATA PreparsedData)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+DriverEntry(
+    IN PDRIVER_OBJECT DriverObject,
+    IN PUNICODE_STRING RegPath)
+{
+
+    DPRINT1("********* HID PARSE *********\n");
+    return STATUS_SUCCESS;
+}
diff --git a/drivers/usb/hidparse/hidparse.h b/drivers/usb/hidparse/hidparse.h
new file mode 100644 (file)
index 0000000..f0bc0d2
--- /dev/null
@@ -0,0 +1,8 @@
+#pragma once
+
+#define _HIDPI_
+#define _HIDPI_NO_FUNCTION_MACROS_
+#include <ntddk.h>
+#include <hidpddi.h>
+#include <hidpi.h>
+#include <debug.h>
diff --git a/drivers/usb/hidparse/hidparse.rc b/drivers/usb/hidparse/hidparse.rc
new file mode 100644 (file)
index 0000000..3da21c3
--- /dev/null
@@ -0,0 +1,5 @@
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION   "USB HID Parser\0"
+#define REACTOS_STR_INTERNAL_NAME      "hidparse\0"
+#define REACTOS_STR_ORIGINAL_FILENAME  "hidparse.sys\0"
+#include <reactos/version.rc>
diff --git a/drivers/usb/hidparse/hidparse.spec b/drivers/usb/hidparse/hidparse.spec
new file mode 100644 (file)
index 0000000..2a3b1e8
--- /dev/null
@@ -0,0 +1,53 @@
+@ stdcall HidP_FreeCollectionDescription(ptr)
+@ stdcall HidP_GetButtonCaps(long ptr ptr ptr)
+@ stdcall HidP_GetCaps(ptr ptr)
+@ stdcall HidP_GetCollectionDescription(ptr long long ptr)
+@ stdcall HidP_GetData(long ptr ptr ptr ptr long)
+@ stdcall HidP_GetExtendedAttributes(long long ptr ptr long)
+@ stdcall HidP_GetLinkCollectionNodes(ptr ptr ptr)
+@ stdcall HidP_GetScaledUsageValue(long long long long ptr ptr ptr long)
+@ stdcall HidP_GetSpecificButtonCaps(long long long long ptr ptr ptr)
+@ stdcall HidP_GetSpecificValueCaps(long long long long ptr ptr ptr)
+@ stdcall HidP_GetUsageValue(long long long long ptr ptr ptr long)
+@ stdcall HidP_GetUsageValueArray(long long long long ptr long ptr ptr long)
+@ stdcall HidP_GetUsages(long long ptr ptr ptr ptr long)
+@ stdcall HidP_GetUsagesEx(long long ptr ptr ptr ptr long)
+@ stdcall HidP_GetValueCaps(long ptr ptr ptr)
+@ stdcall HidP_InitializeReportForID(long long ptr ptr long)
+@ stdcall HidP_MaxDataListLength(long ptr)
+@ stdcall HidP_MaxUsageListLength(long long ptr)
+@ stdcall HidP_SetData(long ptr ptr ptr ptr long)
+@ stdcall HidP_SetScaledUsageValue(long long long long long ptr ptr long)
+@ stdcall HidP_SetUsageValue(long long long long long ptr ptr long)
+@ stdcall HidP_SetUsageValueArray(long long long long ptr long long ptr long)
+@ stdcall HidP_SetUsages(long long long ptr ptr ptr ptr long)
+@ stdcall HidP_SysPowerCaps(ptr ptr)
+@ stdcall HidP_SysPowerEvent(ptr long ptr ptr)
+@ stdcall HidP_TranslateUsageAndPagesToI8042ScanCodes(ptr long long ptr ptr ptr)
+@ stdcall HidP_TranslateUsagesToI8042ScanCodes(ptr long long ptr ptr ptr)
+@ stdcall HidP_UnsetUsages(long long long ptr ptr ptr ptr long)
+@ stdcall HidP_UsageAndPageListDifference(ptr ptr ptr ptr long)
+@ stdcall HidP_UsageListDifference(ptr ptr ptr ptr long)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drivers/usb/hidusb/CMakeLists.txt b/drivers/usb/hidusb/CMakeLists.txt
new file mode 100644 (file)
index 0000000..87de508
--- /dev/null
@@ -0,0 +1,11 @@
+
+list(APPEND SOURCE
+    hidusb.c
+    usbhub.rc)
+
+add_library(hidusb SHARED ${SOURCE})
+
+set_module_type(hidusb kernelmodedriver)
+add_importlibs(hidusb hidclass ntoskrnl usbd)
+
+add_cab_target(usbhub 2)
diff --git a/drivers/usb/hidusb/hidusb.c b/drivers/usb/hidusb/hidusb.c
new file mode 100644 (file)
index 0000000..56af50a
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * PROJECT:     ReactOS Universal Serial Bus Human Interface Device Driver
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/usb/hidusb/hidusb.c
+ * PURPOSE:     HID USB Interface Driver
+ * PROGRAMMERS:
+ *              Michael Martin (michael.martin@reactos.org)
+ *              Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+#include "hidusb.h"
+
+NTSTATUS
+NTAPI
+HidCreate(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+
+    //
+    // get current irp stack location
+    //
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    //
+    // sanity check for hidclass driver
+    //
+    ASSERT(IoStack->MajorFunction == IRP_MJ_CREATE || IoStack->MajorFunction == IRP_MJ_CLOSE);
+
+    //
+    // complete request
+    //
+    Irp->IoStatus.Information = 0;
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    //
+    // informal debug print
+    //
+    DPRINT1("HIDUSB Request: %x\n", IoStack->MajorFunction);
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+HidInternalDeviceControl(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+HidPower(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+HidSystemControl(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PHID_DEVICE_EXTENSION DeviceExtension;
+
+    //
+    // get hid device extension
+    //
+    DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    //
+    // copy stack location
+    //
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+
+    //
+    // submit request
+    //
+    return IoCallDriver(DeviceExtension->NextDeviceObject);
+}
+
+NTSTATUS
+NTAPI
+HidPnp(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+DriverEntry(
+    IN PDRIVER_OBJECT DriverObject,
+    IN PUNICODE_STRING RegPath)
+{
+    HID_MINIDRIVER_REGISTRATION Registration;
+    NTSTATUS Status;
+
+    //
+    // initialize driver object
+    //
+    DriverObject->MajorFunction[IRP_MJ_CREATE] = HidCreate;
+    DriverObject->MajorFunction[IRP_MJ_CLOSE] = HidCreate;
+    DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = HidInternalDeviceControl;
+    DriverObject->MajorFunction[IRP_MJ_POWER] = HidPower;
+    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HidSystemControl;
+    DriverObject->MajorFunction[IRP_MJ_PNP] = HidPnp;
+
+    //
+    // prepare registration info
+    //
+    RtlZeroMemory(&Registration, sizeof(HID_MINIDRIVER_REGISTRATION));
+
+    //
+    // fill in registration info
+    //
+    Registration.Revision = HID_REVISION;
+    Registration.DriverObject = DriverObject;
+    Registration.RegistryPath = RegPath;
+    Registration.DeviceExtensionSize = sizeof(HID_USB_DEVICE_EXTENSION);
+    Registration.DevicesArePolled = FALSE;
+
+    //
+    // register driver
+    //
+    Status = HidRegisterMinidriver(&Registration);
+
+    //
+    // informal debug
+    //
+    DPRINT1("********* HIDUSB *********\n");
+    DPRINT1("HIDUSB Registration Status %x\n", Status);
+
+    return Status;
+}
diff --git a/drivers/usb/hidusb/hidusb.h b/drivers/usb/hidusb/hidusb.h
new file mode 100644 (file)
index 0000000..e991861
--- /dev/null
@@ -0,0 +1,22 @@
+#pragma once
+
+#define _HIDPI_
+#define _HIDPI_NO_FUNCTION_MACROS_
+#include <ntddk.h>
+#include <hidport.h>
+#include <debug.h>
+
+typedef struct
+{
+    //
+    // event for completion
+    //
+    KEVENT Event;
+
+    //
+    // list for pending requests
+    //
+    LIST_ENTRY PendingRequests;
+
+}HID_USB_DEVICE_EXTENSION, *PHID_USB_DEVICE_EXTENSION;
+
index 7b98b93..7e74db2 100644 (file)
@@ -4,6 +4,7 @@
 @ stdcall USBD_CreateConfigurationRequestEx(ptr ptr)
 @ stdcall USBD_CreateConfigurationRequest(ptr ptr)
 @ stdcall USBD_GetInterfaceLength(ptr ptr)
+@ stdcall USBD_ParseConfigurationDescriptor(ptr long long)
 @ stdcall USBD_ParseConfigurationDescriptorEx(ptr ptr long long long long long)
 @ stdcall USBD_ParseDescriptors(ptr long ptr long)
 ;USBD_GetPdoRegistryParameters
diff --git a/drivers/usb/usbehci_new/CMakeLists.txt b/drivers/usb/usbehci_new/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a552101
--- /dev/null
@@ -0,0 +1,35 @@
+
+set_cpp()
+
+remove_definitions(-D_WIN32_WINNT=0x502)
+add_definitions(-D_WIN32_WINNT=0x600)
+
+add_library(usbehci SHARED
+    usbehci.cpp
+    usb_device.cpp
+    usb_request.cpp
+    usb_queue.cpp
+    hcd_controller.cpp
+    hardware.cpp
+    misc.cpp
+    purecall.cpp
+    hub_controller.cpp
+    memory_manager.cpp
+    usbehci.rc)
+
+target_link_libraries(usbehci
+    libcntpr
+    stlport
+    ${PSEH_LIB})
+
+if(MSVC)
+    set_target_properties(usbehci PROPERTIES COMPILE_FLAGS "/GR-")
+else()
+    target_link_libraries(usbehci -lgcc)
+    set_target_properties(usbehci PROPERTIES COMPILE_FLAGS "-fno-exceptions -fno-rtti")
+endif(MSVC)
+
+set_module_type(usbehci kernelmodedriver)
+add_importlibs(usbehci ntoskrnl ks drmk hal)
+
+add_cab_target(usbehci 2)
\ No newline at end of file
diff --git a/drivers/usb/usbehci_new/hardware.cpp b/drivers/usb/usbehci_new/hardware.cpp
new file mode 100644 (file)
index 0000000..52b764a
--- /dev/null
@@ -0,0 +1,1200 @@
+/*
+ * PROJECT:     ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/usb/usbehci/hcd_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"
+#include "hardware.h"
+
+typedef VOID __stdcall HD_INIT_CALLBACK(IN PVOID CallBackContext);
+
+BOOLEAN
+NTAPI
+InterruptServiceRoutine(
+    IN PKINTERRUPT  Interrupt,
+    IN PVOID  ServiceContext);
+
+VOID
+NTAPI
+EhciDefferedRoutine(
+    IN PKDPC Dpc,
+    IN PVOID DeferredContext,
+    IN PVOID SystemArgument1,
+    IN PVOID SystemArgument2);
+
+VOID
+NTAPI
+StatusChangeWorkItemRoutine(PVOID Context);
+
+class CUSBHardwareDevice : public IUSBHardwareDevice
+{
+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;
+    }
+    // com
+    NTSTATUS Initialize(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT FunctionalDeviceObject, PDEVICE_OBJECT PhysicalDeviceObject, PDEVICE_OBJECT LowerDeviceObject);
+    NTSTATUS PnpStart(PCM_RESOURCE_LIST RawResources, PCM_RESOURCE_LIST TranslatedResources);
+    NTSTATUS PnpStop(void);
+    NTSTATUS HandlePower(PIRP Irp);
+    NTSTATUS GetDeviceDetails(PUSHORT VendorId, PUSHORT DeviceId, PULONG NumberOfPorts, PULONG Speed);
+    NTSTATUS GetDMA(OUT struct IDMAMemoryManager **m_DmaManager);
+    NTSTATUS GetUSBQueue(OUT struct IUSBQueue **OutUsbQueue);
+
+    NTSTATUS StartController();
+    NTSTATUS StopController();
+    NTSTATUS ResetController();
+    NTSTATUS ResetPort(ULONG PortIndex);
+
+    NTSTATUS GetPortStatus(ULONG PortId, OUT USHORT *PortStatus, OUT USHORT *PortChange);
+    NTSTATUS ClearPortStatus(ULONG PortId, ULONG Status);
+    NTSTATUS SetPortFeature(ULONG PortId, ULONG Feature);
+
+    VOID SetAsyncListRegister(ULONG PhysicalAddress);
+    VOID SetPeriodicListRegister(ULONG PhysicalAddress);
+    struct _QUEUE_HEAD * GetAsyncListQueueHead();
+    ULONG GetPeriodicListRegister();
+
+    VOID SetStatusChangeEndpointCallBack(PVOID CallBack, PVOID Context);
+
+    KIRQL AcquireDeviceLock(void);
+    VOID ReleaseDeviceLock(KIRQL OldLevel);
+    // local
+    BOOLEAN InterruptService();
+
+    // friend function
+    friend BOOLEAN NTAPI InterruptServiceRoutine(IN PKINTERRUPT  Interrupt, IN PVOID  ServiceContext);
+    friend VOID NTAPI EhciDefferedRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
+    friend VOID NTAPI StatusChangeWorkItemRoutine(PVOID Context);
+    // constructor / destructor
+    CUSBHardwareDevice(IUnknown *OuterUnknown){}
+    virtual ~CUSBHardwareDevice(){}
+
+protected:
+    LONG m_Ref;                                                                        // reference count
+    PDRIVER_OBJECT m_DriverObject;                                                     // driver object
+    PDEVICE_OBJECT m_PhysicalDeviceObject;                                             // pdo
+    PDEVICE_OBJECT m_FunctionalDeviceObject;                                           // fdo (hcd controller)
+    PDEVICE_OBJECT m_NextDeviceObject;                                                 // lower device object
+    KSPIN_LOCK m_Lock;                                                                 // hardware lock
+    PKINTERRUPT m_Interrupt;                                                           // interrupt object
+    KDPC m_IntDpcObject;                                                               // dpc object for deferred isr processing
+    PVOID VirtualBase;                                                                 // virtual base for memory manager
+    PHYSICAL_ADDRESS PhysicalAddress;                                                  // physical base for memory manager
+    PULONG m_Base;                                                                     // EHCI operational port base registers
+    PDMA_ADAPTER m_Adapter;                                                            // dma adapter object
+    ULONG m_MapRegisters;                                                              // map registers count
+    EHCI_CAPS m_Capabilities;                                                          // EHCI caps
+    USHORT m_VendorID;                                                                 // vendor id
+    USHORT m_DeviceID;                                                                 // device id
+    PQUEUE_HEAD AsyncQueueHead;                                                        // async queue head terminator
+    PUSBQUEUE m_UsbQueue;                                                              // usb request queue
+    PDMAMEMORYMANAGER m_MemoryManager;                                                 // memory manager
+    HD_INIT_CALLBACK* m_SCECallBack;                                                   // status change callback routine
+    PVOID m_SCEContext;                                                                // status change callback routine context
+    BOOLEAN m_DoorBellRingInProgress;                                                  // door bell ring in progress
+    EHCI_PORT_STATUS m_PortStatus[16];                                                 // port status
+    WORK_QUEUE_ITEM m_StatusChangeWorkItem;                                            // work item for status change callback
+    ULONG m_SyncFramePhysAddr;                                                         // periodic frame list physical address
+
+    // set command
+    VOID SetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd);
+
+    // get command
+    VOID GetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd);
+
+    // read register
+    ULONG EHCI_READ_REGISTER_ULONG(ULONG Offset);
+
+    // write register
+    VOID EHCI_WRITE_REGISTER_ULONG(ULONG Offset, ULONG Value);
+};
+
+//=================================================================================================
+// COM
+//
+NTSTATUS
+STDMETHODCALLTYPE
+CUSBHardwareDevice::QueryInterface(
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    if (IsEqualGUIDAligned(refiid, IID_IUnknown))
+    {
+        *Output = PVOID(PUNKNOWN(this));
+        PUNKNOWN(*Output)->AddRef();
+        return STATUS_SUCCESS;
+    }
+
+    return STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS
+CUSBHardwareDevice::Initialize(
+    PDRIVER_OBJECT DriverObject,
+    PDEVICE_OBJECT FunctionalDeviceObject,
+    PDEVICE_OBJECT PhysicalDeviceObject,
+    PDEVICE_OBJECT LowerDeviceObject)
+{
+    BUS_INTERFACE_STANDARD BusInterface;
+    PCI_COMMON_CONFIG PciConfig;
+    NTSTATUS Status;
+    ULONG BytesRead;
+
+    DPRINT1("CUSBHardwareDevice::Initialize\n");
+
+    //
+    // Create DMAMemoryManager for use with QueueHeads and Transfer Descriptors.
+    //
+    Status =  CreateDMAMemoryManager(&m_MemoryManager);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to create DMAMemoryManager Object\n");
+        return Status;
+    }
+
+    //
+    // Create the UsbQueue class that will handle the Asynchronous and Periodic Schedules
+    //
+    Status = CreateUSBQueue(&m_UsbQueue);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to create UsbQueue!\n");
+        return Status;
+    }
+
+    //
+    // store device objects
+    // 
+    m_DriverObject = DriverObject;
+    m_FunctionalDeviceObject = FunctionalDeviceObject;
+    m_PhysicalDeviceObject = PhysicalDeviceObject;
+    m_NextDeviceObject = LowerDeviceObject;
+
+    //
+    // initialize device lock
+    //
+    KeInitializeSpinLock(&m_Lock);
+
+    //
+    // intialize status change work item
+    //
+    ExInitializeWorkItem(&m_StatusChangeWorkItem, StatusChangeWorkItemRoutine, PVOID(this));
+
+    m_VendorID = 0;
+    m_DeviceID = 0;
+
+    Status = GetBusInterface(PhysicalDeviceObject, &BusInterface);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to get BusInteface!\n");
+        return Status;
+    }
+
+    BytesRead = (*BusInterface.GetBusData)(BusInterface.Context,
+                                           PCI_WHICHSPACE_CONFIG,
+                                           &PciConfig,
+                                           0,
+                                           PCI_COMMON_HDR_LENGTH);
+
+    if (BytesRead != PCI_COMMON_HDR_LENGTH)
+    {
+        DPRINT1("Failed to get pci config information!\n");
+        return STATUS_SUCCESS;
+    }
+
+    if (!(PciConfig.Command & PCI_ENABLE_BUS_MASTER))
+    {
+        DPRINT1("PCI Configuration shows this as a non Bus Mastering device!\n");
+    }
+
+    m_VendorID = PciConfig.VendorID;
+    m_DeviceID = PciConfig.DeviceID;
+
+    return STATUS_SUCCESS;
+}
+
+VOID
+CUSBHardwareDevice::SetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd)
+{
+    PULONG Register;
+    Register = (PULONG)UsbCmd;
+    WRITE_REGISTER_ULONG((PULONG)((ULONG)m_Base + EHCI_USBCMD), *Register);
+}
+
+VOID
+CUSBHardwareDevice::GetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd)
+{
+    PULONG Register;
+    Register = (PULONG)UsbCmd;
+    *Register = READ_REGISTER_ULONG((PULONG)((ULONG)m_Base + EHCI_USBCMD));
+}
+
+ULONG
+CUSBHardwareDevice::EHCI_READ_REGISTER_ULONG(ULONG Offset)
+{
+    return READ_REGISTER_ULONG((PULONG)((ULONG)m_Base + Offset));
+}
+
+VOID
+CUSBHardwareDevice::EHCI_WRITE_REGISTER_ULONG(ULONG Offset, ULONG Value)
+{
+    WRITE_REGISTER_ULONG((PULONG)((ULONG)m_Base + Offset), Value);
+}
+
+NTSTATUS
+CUSBHardwareDevice::PnpStart(
+    PCM_RESOURCE_LIST RawResources,
+    PCM_RESOURCE_LIST TranslatedResources)
+{
+    ULONG Index, Count;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
+    DEVICE_DESCRIPTION DeviceDescription;
+    PHYSICAL_ADDRESS AsyncPhysicalAddress;
+    PVOID ResourceBase;
+    NTSTATUS Status;
+
+    DPRINT1("CUSBHardwareDevice::PnpStart\n");
+    for(Index = 0; Index < TranslatedResources->List[0].PartialResourceList.Count; Index++)
+    {
+        //
+        // get resource descriptor
+        //
+        ResourceDescriptor = &TranslatedResources->List[0].PartialResourceList.PartialDescriptors[Index];
+
+        switch(ResourceDescriptor->Type)
+        {
+            case CmResourceTypeInterrupt:
+            {
+                KeInitializeDpc(&m_IntDpcObject,
+                                EhciDefferedRoutine,
+                                this);
+
+                Status = IoConnectInterrupt(&m_Interrupt,
+                                            InterruptServiceRoutine,
+                                            (PVOID)this,
+                                            NULL,
+                                            ResourceDescriptor->u.Interrupt.Vector,
+                                            (KIRQL)ResourceDescriptor->u.Interrupt.Level,
+                                            (KIRQL)ResourceDescriptor->u.Interrupt.Level,
+                                            (KINTERRUPT_MODE)(ResourceDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED),
+                                            (ResourceDescriptor->ShareDisposition != CmResourceShareDeviceExclusive),
+                                            ResourceDescriptor->u.Interrupt.Affinity,
+                                            FALSE);
+
+                if (!NT_SUCCESS(Status))
+                {
+                    //
+                    // failed to register interrupt
+                    //
+                    DPRINT1("IoConnect Interrupt failed with %x\n", Status);
+                    return Status;
+                }
+                break;
+            }
+            case CmResourceTypeMemory:
+            {
+                //
+                // get resource base
+                //
+                ResourceBase = MmMapIoSpace(ResourceDescriptor->u.Memory.Start, ResourceDescriptor->u.Memory.Length, MmNonCached);
+                if (!ResourceBase)
+                {
+                    //
+                    // failed to map registers
+                    //
+                    DPRINT1("MmMapIoSpace failed\n");
+                    return STATUS_INSUFFICIENT_RESOURCES;
+                }
+
+                //
+                // Get controllers capabilities 
+                //
+                m_Capabilities.Length = READ_REGISTER_UCHAR((PUCHAR)ResourceBase);
+                m_Capabilities.HCIVersion = READ_REGISTER_USHORT((PUSHORT)((ULONG)ResourceBase + 2));
+                m_Capabilities.HCSParamsLong = READ_REGISTER_ULONG((PULONG)((ULONG)ResourceBase + 4));
+                m_Capabilities.HCCParamsLong = READ_REGISTER_ULONG((PULONG)((ULONG)ResourceBase + 8));
+
+                DPRINT1("Controller has %d Ports\n", m_Capabilities.HCSParams.PortCount);
+                DPRINT1("Controller EHCI Version %x\n", m_Capabilities.HCIVersion);
+                if (m_Capabilities.HCSParams.PortRouteRules)
+                {
+                    for (Count = 0; Count < m_Capabilities.HCSParams.PortCount; Count++)
+                    {
+                        m_Capabilities.PortRoute[Count] = READ_REGISTER_UCHAR((PUCHAR)(ULONG)ResourceBase + 12 + Count);
+                    }
+                }
+
+                //
+                // Set m_Base to the address of Operational Register Space
+                //
+                m_Base = (PULONG)((ULONG)ResourceBase + m_Capabilities.Length);
+                break;
+            }
+        }
+    }
+
+
+    //
+    // zero device description
+    //
+    RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
+
+    //
+    // initialize device description
+    //
+    DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
+    DeviceDescription.Master = TRUE;
+    DeviceDescription.ScatterGather = TRUE;
+    DeviceDescription.Dma32BitAddresses = TRUE;
+    DeviceDescription.DmaWidth = Width32Bits;
+    DeviceDescription.InterfaceType = PCIBus;
+    DeviceDescription.MaximumLength = MAXULONG;
+
+    //
+    // get dma adapter
+    //
+    m_Adapter = IoGetDmaAdapter(m_PhysicalDeviceObject, &DeviceDescription, &m_MapRegisters);
+    if (!m_Adapter)
+    {
+        //
+        // failed to get dma adapter
+        //
+        DPRINT1("Failed to acquire dma adapter\n");
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // Create Common Buffer
+    //
+    VirtualBase = m_Adapter->DmaOperations->AllocateCommonBuffer(m_Adapter,
+                                                                 PAGE_SIZE * 4,
+                                                                 &PhysicalAddress,
+                                                                 FALSE);
+    if (!VirtualBase)
+    {
+        DPRINT1("Failed to allocate a common buffer\n");
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // Stop the controller before modifying schedules
+    //
+    Status = StopController();
+    if (!NT_SUCCESS(Status))
+        return Status;
+
+    //
+    // Initialize the DMAMemoryManager
+    //
+    Status = m_MemoryManager->Initialize(this, &m_Lock, PAGE_SIZE * 4, VirtualBase, PhysicalAddress, 32);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to initialize the DMAMemoryManager\n");
+        return Status;
+    }
+
+    // 
+    // Create a queuehead for the Async Register
+    //
+    m_MemoryManager->Allocate(sizeof(QUEUE_HEAD), (PVOID*)&AsyncQueueHead, &AsyncPhysicalAddress);
+
+    AsyncQueueHead->AlternateNextPointer = TERMINATE_POINTER;
+    AsyncQueueHead->NextPointer = TERMINATE_POINTER;
+    AsyncQueueHead->PhysicalAddr = AsyncPhysicalAddress.LowPart;
+    AsyncQueueHead->HorizontalLinkPointer = AsyncQueueHead->PhysicalAddr | QH_TYPE_QH;
+    AsyncQueueHead->EndPointCharacteristics.QEDTDataToggleControl = FALSE;
+    AsyncQueueHead->Token.Bits.InterruptOnComplete = FALSE;
+    AsyncQueueHead->EndPointCharacteristics.HeadOfReclamation = TRUE;
+    AsyncQueueHead->Token.Bits.Halted = TRUE;
+    AsyncQueueHead->EndPointCharacteristics.MaximumPacketLength = 64;
+    AsyncQueueHead->EndPointCharacteristics.NakCountReload = 0;
+    AsyncQueueHead->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED;
+    AsyncQueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = 0x03;
+
+    InitializeListHead(&AsyncQueueHead->LinkedQueueHeads);
+
+    //
+    // Initialize the UsbQueue now that we have an AdapterObject.
+    //
+    Status = m_UsbQueue->Initialize(PUSBHARDWAREDEVICE(this), m_Adapter, m_MemoryManager, NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to Initialize the UsbQueue\n");
+        return Status;
+    }
+
+    //
+    // Start the controller
+    //
+    DPRINT1("Starting Controller\n");
+    Status = StartController();
+
+    //
+    // done
+    //
+    return Status;
+}
+
+NTSTATUS
+CUSBHardwareDevice::PnpStop(void)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+CUSBHardwareDevice::HandlePower(
+    PIRP Irp)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+CUSBHardwareDevice::GetDeviceDetails(
+    OUT OPTIONAL PUSHORT VendorId,
+    OUT OPTIONAL PUSHORT DeviceId,
+    OUT OPTIONAL PULONG NumberOfPorts,
+    OUT OPTIONAL PULONG Speed)
+{
+    if (VendorId)
+        *VendorId = m_VendorID;
+    if (DeviceId)
+        *DeviceId = m_DeviceID;
+    if (NumberOfPorts)
+        *NumberOfPorts = m_Capabilities.HCSParams.PortCount;
+    //FIXME: What to returned here?
+    if (Speed)
+        *Speed = 0x200;
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS CUSBHardwareDevice::GetDMA(
+    OUT struct IDMAMemoryManager **OutDMAMemoryManager)
+{
+    if (!m_MemoryManager)
+        return STATUS_UNSUCCESSFUL;
+    *OutDMAMemoryManager = m_MemoryManager;
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CUSBHardwareDevice::GetUSBQueue(
+    OUT struct IUSBQueue **OutUsbQueue)
+{
+    if (!m_UsbQueue)
+        return STATUS_UNSUCCESSFUL;
+    *OutUsbQueue = m_UsbQueue;
+    return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+CUSBHardwareDevice::StartController(void)
+{
+    EHCI_USBCMD_CONTENT UsbCmd;
+    ULONG UsbSts, FailSafe;
+
+    //
+    // Stop the controller if its running
+    //
+    UsbSts = EHCI_READ_REGISTER_ULONG(EHCI_USBSTS);
+    if (!(UsbSts & EHCI_STS_HALT))
+        StopController();
+
+    //
+    // Reset the device. Bit is set to 0 on completion.
+    //
+    GetCommandRegister(&UsbCmd);
+    UsbCmd.HCReset = TRUE;
+    SetCommandRegister(&UsbCmd);
+
+    //
+    // Check that the controller reset
+    //
+    for (FailSafe = 100; FailSafe > 1; FailSafe--)
+    {
+        KeStallExecutionProcessor(10);
+        GetCommandRegister(&UsbCmd);
+        if (!UsbCmd.HCReset)
+        {
+            break;
+        }
+    }
+
+    //
+    // If the controller did not reset then fail
+    //
+    if (UsbCmd.HCReset)
+    {
+        DPRINT1("EHCI ERROR: Controller failed to reset. Hardware problem!\n");
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    //
+    // Disable Interrupts and clear status
+    //
+    EHCI_WRITE_REGISTER_ULONG(EHCI_USBINTR, 0);
+    EHCI_WRITE_REGISTER_ULONG(EHCI_USBSTS, 0x0000001f);
+
+    //
+    // Assign the AsyncList Register
+    //
+    EHCI_WRITE_REGISTER_ULONG(EHCI_ASYNCLISTBASE, AsyncQueueHead->PhysicalAddr);
+
+    //
+    // Assign the SyncList Register
+    //
+    EHCI_WRITE_REGISTER_ULONG(EHCI_PERIODICLISTBASE, m_SyncFramePhysAddr);
+
+    //
+    // Set Schedules to Enable and Interrupt Threshold to 1ms.
+    //
+    GetCommandRegister(&UsbCmd);
+    UsbCmd.PeriodicEnable = TRUE;
+    UsbCmd.AsyncEnable = TRUE;  //FIXME: Need USB Memory Manager
+
+    UsbCmd.IntThreshold = 1;
+    // FIXME: Set framelistsize when periodic is implemented.
+    SetCommandRegister(&UsbCmd);
+
+    //
+    // Enable Interrupts and start execution
+    //
+    EHCI_WRITE_REGISTER_ULONG(EHCI_USBINTR, EHCI_USBINTR_INTE | EHCI_USBINTR_ERR | EHCI_USBINTR_ASYNC | EHCI_USBINTR_HSERR
+        /*| EHCI_USBINTR_FLROVR*/  | EHCI_USBINTR_PC);
+
+    UsbCmd.Run = TRUE;
+    SetCommandRegister(&UsbCmd);
+
+    //
+    // Wait for execution to start
+    //
+    for (FailSafe = 100; FailSafe > 1; FailSafe--)
+    {
+        KeStallExecutionProcessor(10);
+        UsbSts = EHCI_READ_REGISTER_ULONG(EHCI_USBSTS);
+
+        if (!(UsbSts & EHCI_STS_HALT))
+        {
+            break;
+        }
+    }
+
+    if (UsbSts & EHCI_STS_HALT)
+    {
+        DPRINT1("Could not start execution on the controller\n");
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    //
+    // Set port routing to EHCI controller
+    //
+    EHCI_WRITE_REGISTER_ULONG(EHCI_CONFIGFLAG, 1);
+
+    DPRINT1("EHCI Started!\n");
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CUSBHardwareDevice::StopController(void)
+{
+    EHCI_USBCMD_CONTENT UsbCmd;
+    ULONG UsbSts, FailSafe;
+
+    //
+    // Disable Interrupts and stop execution
+    //
+    EHCI_WRITE_REGISTER_ULONG (EHCI_USBINTR, 0);
+
+    GetCommandRegister(&UsbCmd);
+    UsbCmd.Run = FALSE;
+    SetCommandRegister(&UsbCmd);
+
+    for (FailSafe = 100; FailSafe > 1; FailSafe--)
+    {
+        KeStallExecutionProcessor(10);
+        UsbSts = EHCI_READ_REGISTER_ULONG(EHCI_USBSTS);
+        if (UsbSts & EHCI_STS_HALT)
+        {
+            break;
+        }
+    }
+
+    if (!(UsbSts & EHCI_STS_HALT))
+    {
+        DPRINT1("EHCI ERROR: Controller is not responding to Stop request!\n");
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CUSBHardwareDevice::ResetController(void)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+CUSBHardwareDevice::ResetPort(
+    IN ULONG PortIndex)
+{
+    ULONG PortStatus;
+
+    if (PortIndex > m_Capabilities.HCSParams.PortCount)
+        return STATUS_UNSUCCESSFUL;
+
+    PortStatus = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex));
+    if (PortStatus & EHCI_PRT_SLOWSPEEDLINE)
+    {
+        DPRINT1("Non HighSpeed device. Releasing Ownership\n");
+        EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex), EHCI_PRT_RELEASEOWNERSHIP);
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
+
+    //
+    // Reset and clean enable
+    //
+    PortStatus |= EHCI_PRT_RESET;
+    PortStatus &= ~EHCI_PRT_ENABLED;
+    EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex), PortStatus);
+
+    KeStallExecutionProcessor(100);
+
+    //
+    // Clear reset
+    //
+    PortStatus = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex));
+    PortStatus &= ~EHCI_PRT_RESET;
+    EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex), PortStatus);
+
+    KeStallExecutionProcessor(100);
+
+    //
+    // Check that the port reset
+    //
+    PortStatus = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex));
+    if (PortStatus & EHCI_PRT_RESET)
+    {
+        DPRINT1("Port did not reset\n");
+        return STATUS_RETRY;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CUSBHardwareDevice::GetPortStatus(
+    ULONG PortId,
+    OUT USHORT *PortStatus,
+    OUT USHORT *PortChange)
+{
+#if 0
+    ULONG Value;
+    USHORT Status = 0, Change = 0;
+
+    if (PortId > m_Capabilities.HCSParams.PortCount)
+        return STATUS_UNSUCCESSFUL;
+
+    //
+    // Get the value of the Port Status and Control Register
+    //
+    Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
+
+    //
+    // If the PowerPortControl is 0 then host controller does not have power control switches
+    if (!m_Capabilities.HCSParams.PortPowerControl)
+    {
+        Status |= USB_PORT_STATUS_POWER;
+    }
+    else
+    {
+        // Check the value of PortPower
+        if (Value & EHCI_PRT_POWER)
+        {
+            Status |= USB_PORT_STATUS_POWER;
+        }
+    }
+
+    // Get Speed. If SlowSpeedLine flag is there then its a slow speed device
+    if (Value & EHCI_PRT_SLOWSPEEDLINE)
+        Status |= USB_PORT_STATUS_LOW_SPEED;
+    else
+        Status |= USB_PORT_STATUS_HIGH_SPEED;
+
+    // Get Connected Status
+    if (Value & EHCI_PRT_CONNECTED)
+        Status |= USB_PORT_STATUS_CONNECT;
+
+    // Get Enabled Status
+    if (Value & EHCI_PRT_ENABLED)
+        Status |= USB_PORT_STATUS_ENABLE;
+
+    // Is it suspended?
+    if (Value & EHCI_PRT_SUSPEND)
+        Status |= USB_PORT_STATUS_SUSPEND;
+
+    // a overcurrent is active?
+    if (Value & EHCI_PRT_OVERCURRENTACTIVE)
+        Status |= USB_PORT_STATUS_OVER_CURRENT;
+
+    // In a reset state?
+    if (Value & EHCI_PRT_RESET)
+        Status |= USB_PORT_STATUS_RESET;
+
+    //
+    // FIXME: Is the Change here correct?
+    //
+    if (Value & EHCI_PRT_CONNECTSTATUSCHANGE)
+        Change |= USB_PORT_STATUS_CONNECT;
+
+    if (Value & EHCI_PRT_ENABLEDSTATUSCHANGE)
+        Change |= USB_PORT_STATUS_ENABLE;
+
+    *PortStatus = Status;
+    *PortChange = Change;
+#else
+    *PortStatus = m_PortStatus[PortId].PortStatus;
+    *PortChange = m_PortStatus[PortId].PortChange;
+#endif
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CUSBHardwareDevice::ClearPortStatus(
+    ULONG PortId,
+    ULONG Status)
+{
+    ULONG Value;
+
+    DPRINT("CUSBHardwareDevice::ClearPortStatus PortId %x Feature %x\n", PortId, Status);
+
+    if (PortId > m_Capabilities.HCSParams.PortCount)
+        return STATUS_UNSUCCESSFUL;
+
+    Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
+
+    if (Status == C_PORT_RESET)
+    {
+        if (Value & EHCI_PRT_RESET)
+        {
+            Value &= ~EHCI_PRT_RESET;
+            EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value);
+            KeStallExecutionProcessor(100);
+        }
+
+        Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
+        //
+        // update port status
+        //
+        m_PortStatus[PortId].PortChange &= ~USB_PORT_STATUS_RESET;
+        if (Value & EHCI_PRT_ENABLED) 
+            m_PortStatus[PortId].PortStatus |= USB_PORT_STATUS_ENABLE;
+        else
+        {
+            DPRINT1("Port is not enabled.\n");
+        }
+    }
+
+    if (Status == C_PORT_CONNECTION)
+    {
+        // FIXME: Make sure its the Connection and Enable Change status.
+        Value |= EHCI_PRT_CONNECTSTATUSCHANGE;
+        Value |= EHCI_PRT_ENABLEDSTATUSCHANGE;
+        EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value);
+
+        m_PortStatus[PortId].PortChange &= ~USB_PORT_STATUS_CONNECT;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+CUSBHardwareDevice::SetPortFeature(
+    ULONG PortId,
+    ULONG Feature)
+{
+    ULONG Value;
+
+    DPRINT("CUSBHardwareDevice::SetPortFeature\n");
+
+    if (PortId > m_Capabilities.HCSParams.PortCount)
+        return STATUS_UNSUCCESSFUL;
+
+    Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
+
+    if (Feature == PORT_ENABLE)
+    {
+        //
+        // FIXME: EHCI Ports can only be disabled via reset
+        //
+        DPRINT1("PORT_ENABLE not supported for EHCI\n");
+    }
+
+    if (Feature == PORT_RESET)
+    {
+        if (Value & EHCI_PRT_SLOWSPEEDLINE)
+        {
+            DPRINT1("Non HighSpeed device. Releasing Ownership\n");
+        }
+
+        ResetPort(PortId);
+
+        //
+        // update cached settings
+        //
+        m_PortStatus[PortId].PortChange |= USB_PORT_STATUS_RESET;
+        m_PortStatus[PortId].PortStatus &= ~USB_PORT_STATUS_ENABLE;
+
+        //
+        // is there a status change callback
+        //
+        if (m_SCECallBack != NULL)
+        {
+            //
+            // issue callback
+            //
+            m_SCECallBack(m_SCEContext);
+        }
+    }
+
+    if (Feature == PORT_POWER)
+        DPRINT1("PORT_POWER Not implemented\n");
+
+    return STATUS_SUCCESS;
+}
+
+VOID
+CUSBHardwareDevice::SetAsyncListRegister(
+    ULONG PhysicalAddress)
+{
+    EHCI_WRITE_REGISTER_ULONG(EHCI_ASYNCLISTBASE, PhysicalAddress);
+}
+
+VOID
+CUSBHardwareDevice::SetPeriodicListRegister(
+    ULONG PhysicalAddress)
+{
+    //
+    // store physical address
+    //
+    m_SyncFramePhysAddr = PhysicalAddress;
+}
+
+struct _QUEUE_HEAD *
+CUSBHardwareDevice::GetAsyncListQueueHead()
+{
+    return AsyncQueueHead;
+}
+
+ULONG CUSBHardwareDevice::GetPeriodicListRegister()
+{
+    UNIMPLEMENTED
+    return NULL;
+}
+
+VOID CUSBHardwareDevice::SetStatusChangeEndpointCallBack(
+    PVOID CallBack,
+    PVOID Context)
+{
+    m_SCECallBack = (HD_INIT_CALLBACK*)CallBack;
+    m_SCEContext = Context;
+}
+
+KIRQL
+CUSBHardwareDevice::AcquireDeviceLock(void)
+{
+    KIRQL OldLevel;
+
+    //
+    // acquire lock
+    //
+    KeAcquireSpinLock(&m_Lock, &OldLevel);
+
+    //
+    // return old irql
+    //
+    return OldLevel;
+}
+
+
+VOID
+CUSBHardwareDevice::ReleaseDeviceLock(
+    KIRQL OldLevel)
+{
+    KeReleaseSpinLock(&m_Lock, OldLevel);
+}
+
+BOOLEAN
+NTAPI
+InterruptServiceRoutine(
+    IN PKINTERRUPT  Interrupt,
+    IN PVOID  ServiceContext)
+{
+    CUSBHardwareDevice *This;
+    ULONG CStatus;
+
+    This = (CUSBHardwareDevice*) ServiceContext;
+    CStatus = This->EHCI_READ_REGISTER_ULONG(EHCI_USBSTS);
+
+    CStatus &= (EHCI_ERROR_INT | EHCI_STS_INT | EHCI_STS_IAA | EHCI_STS_PCD | EHCI_STS_FLR);
+    //
+    // Check that it belongs to EHCI
+    //
+    if (!CStatus)
+        return FALSE;
+
+    //
+    // Clear the Status
+    //
+    This->EHCI_WRITE_REGISTER_ULONG(EHCI_USBSTS, CStatus);
+
+    if (CStatus & EHCI_STS_FATAL)
+    {
+        This->StopController();
+        DPRINT1("EHCI: Host System Error!\n");
+        return TRUE;
+    }
+
+    if (CStatus & EHCI_ERROR_INT)
+    {
+        DPRINT1("EHCI Status = 0x%x\n", CStatus);
+    }
+
+    if (CStatus & EHCI_STS_HALT)
+    {
+        DPRINT1("Host Error Unexpected Halt\n");
+        // FIXME: Reset controller\n");
+        return TRUE;
+    }
+
+    KeInsertQueueDpc(&This->m_IntDpcObject, This, (PVOID)CStatus);
+    return TRUE;
+}
+
+VOID NTAPI
+EhciDefferedRoutine(
+    IN PKDPC Dpc,
+    IN PVOID DeferredContext,
+    IN PVOID SystemArgument1,
+    IN PVOID SystemArgument2)
+{
+    CUSBHardwareDevice *This;
+    ULONG CStatus, PortStatus, PortCount, i, ShouldRingDoorBell;
+    NTSTATUS Status = STATUS_SUCCESS;
+    EHCI_USBCMD_CONTENT UsbCmd;
+
+    This = (CUSBHardwareDevice*) SystemArgument1;
+    CStatus = (ULONG) SystemArgument2;
+
+
+    //
+    // check for completion of async schedule
+    //
+    if (CStatus & (EHCI_STS_RECL| EHCI_STS_INT | EHCI_ERROR_INT))
+    {
+        //
+        // check if there is a door bell ring in progress
+        //
+        if (This->m_DoorBellRingInProgress == FALSE)
+        {
+            if (CStatus & EHCI_ERROR_INT)
+            {
+                //
+                // controller reported error
+                //
+                Status = STATUS_UNSUCCESSFUL;
+                PC_ASSERT(FALSE);
+            }
+
+            //
+            // inform IUSBQueue of a completed queue head
+            //
+            This->m_UsbQueue->InterruptCallback(Status, &ShouldRingDoorBell);
+
+            //
+            // was a queue head completed?
+            //
+             if (ShouldRingDoorBell)
+             {
+                 //
+                 // set door ring bell in progress status flag
+                 //
+                 This->m_DoorBellRingInProgress = TRUE;
+
+                 //
+                 // get command register
+                 //
+                 This->GetCommandRegister(&UsbCmd);
+
+                 //
+                 // set door rang bell bit
+                 //
+                 UsbCmd.DoorBell = TRUE;
+
+                 //
+                 // update command status
+                 //
+                 This->SetCommandRegister(&UsbCmd);
+             }
+        }
+    }
+
+    //
+    // check if the controller has acknowledged the door bell 
+    //
+    if (CStatus & EHCI_STS_IAA)
+    {
+        //
+        // controller has acknowledged, assert we rang the bell
+        //
+        PC_ASSERT(This->m_DoorBellRingInProgress == TRUE);
+
+        //
+        // now notify IUSBQueue that it can free completed requests
+        //
+        This->m_UsbQueue->CompleteAsyncRequests();
+
+        //
+        // door ring bell completed
+        //
+        This->m_DoorBellRingInProgress = FALSE;
+    }
+
+    This->GetDeviceDetails(NULL, NULL, &PortCount, NULL);
+    if (CStatus & EHCI_STS_PCD)
+    {
+        for (i = 0; i < PortCount; i++)
+        {
+            PortStatus = This->EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * i));
+
+            //
+            // Device connected or removed
+            //
+            if (PortStatus & EHCI_PRT_CONNECTSTATUSCHANGE)
+            {
+                //
+                // Clear the port change status
+                //
+                //This->EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * i), PortStatus | EHCI_PRT_CONNECTSTATUSCHANGE);
+
+                if (PortStatus & EHCI_PRT_CONNECTED)
+                {
+                    DPRINT1("Device connected on port %d\n", i);
+
+                    //
+                    //FIXME: Determine device speed
+                    //
+                    if (This->m_Capabilities.HCSParams.CHCCount)
+                    {
+                        if (PortStatus & EHCI_PRT_ENABLED)
+                        {
+                            DPRINT1("Misbeaving controller. Port should be disabled at this point\n");
+                        }
+
+                        if (PortStatus & EHCI_PRT_SLOWSPEEDLINE)
+                        {
+                            DPRINT1("Non HighSpeed device connected. Release ownership\n");
+                            This->EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * i), EHCI_PRT_RELEASEOWNERSHIP);
+                            continue;
+                        }
+                    }
+
+                    //
+                    // update port status flags
+                    //
+                    This->m_PortStatus[i].PortStatus |= USB_PORT_STATUS_HIGH_SPEED;
+                    This->m_PortStatus[i].PortStatus |= USB_PORT_STATUS_CONNECT;
+                    This->m_PortStatus[i].PortChange |= USB_PORT_STATUS_CONNECT;
+
+                    //
+                    // is there a status change callback
+                    //
+                    if (This->m_SCECallBack != NULL)
+                    {
+                        //
+                        // queue work item for processing
+                        //
+                        ExQueueWorkItem(&This->m_StatusChangeWorkItem, DelayedWorkQueue);
+                    }
+                }
+                else
+                {
+                    DPRINT1("Device disconnected on port %d\n", i);
+                }
+
+                //
+                // FIXME: This needs to be saved somewhere
+                //
+            }
+        }
+    }
+    return;
+}
+
+VOID
+NTAPI
+StatusChangeWorkItemRoutine(
+    PVOID Context)
+{
+    //
+    // cast to hardware object
+    //
+    CUSBHardwareDevice * This = (CUSBHardwareDevice*)Context;
+
+    //
+    // is there a callback
+    //
+    if (This->m_SCECallBack)
+    {
+        //
+        // issue callback
+        //
+        This->m_SCECallBack(This->m_SCEContext);
+    }
+
+}
+
+NTSTATUS
+CreateUSBHardware(
+    PUSBHARDWAREDEVICE *OutHardware)
+{
+    PUSBHARDWAREDEVICE This;
+
+    This = new(NonPagedPool, TAG_USBEHCI) CUSBHardwareDevice(0);
+
+    if (!This)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    This->AddRef();
+
+    // return result
+    *OutHardware = (PUSBHARDWAREDEVICE)This;
+
+    return STATUS_SUCCESS;
+}
diff --git a/drivers/usb/usbehci_new/hardware.h b/drivers/usb/usbehci_new/hardware.h
new file mode 100644 (file)
index 0000000..4c5e01e
--- /dev/null
@@ -0,0 +1,291 @@
+#pragma once
+
+#include <ntddk.h>
+
+//
+// EHCI Operational Registers
+//
+#define EHCI_USBCMD                     0x00
+#define EHCI_USBSTS                     0x04
+#define EHCI_USBINTR                    0x08
+#define EHCI_FRINDEX                    0x0C
+#define EHCI_CTRLDSSEGMENT              0x10
+#define EHCI_PERIODICLISTBASE           0x14
+#define EHCI_ASYNCLISTBASE              0x18
+#define EHCI_CONFIGFLAG                 0x40
+#define EHCI_PORTSC                     0x44
+
+//
+// Interrupt Register Flags
+//
+#define EHCI_USBINTR_INTE               0x01
+#define EHCI_USBINTR_ERR                0x02
+#define EHCI_USBINTR_PC                 0x04
+#define EHCI_USBINTR_FLROVR             0x08
+#define EHCI_USBINTR_HSERR              0x10
+#define EHCI_USBINTR_ASYNC              0x20
+// Bits 6:31 Reserved
+
+//
+// Status Register Flags
+//
+#define EHCI_STS_INT                    0x01
+#define EHCI_STS_ERR                    0x02
+#define EHCI_STS_PCD                    0x04
+#define EHCI_STS_FLR                    0x08
+#define EHCI_STS_FATAL                  0x10
+#define EHCI_STS_IAA                    0x20
+// Bits 11:6 Reserved
+#define EHCI_STS_HALT                   0x1000
+#define EHCI_STS_RECL                   0x2000
+#define EHCI_STS_PSS                    0x4000
+#define EHCI_STS_ASS                    0x8000
+#define EHCI_ERROR_INT                  (EHCI_STS_FATAL | EHCI_STS_ERR)
+
+//
+// Port Register Flags
+//
+#define EHCI_PRT_CONNECTED              0x01
+#define EHCI_PRT_CONNECTSTATUSCHANGE    0x02
+#define EHCI_PRT_ENABLED                0x04
+#define EHCI_PRT_ENABLEDSTATUSCHANGE    0x08
+#define EHCI_PRT_OVERCURRENTACTIVE      0x10
+#define EHCI_PRT_OVERCURRENTCHANGE      0x20
+#define EHCI_PRT_FORCERESUME            0x40
+#define EHCI_PRT_SUSPEND                0x80
+#define EHCI_PRT_RESET                  0x100
+#define EHCI_PRT_SLOWSPEEDLINE          0x400
+#define EHCI_PRT_POWER                  0x1000
+#define EHCI_PRT_RELEASEOWNERSHIP       0x2000
+
+#define EHCI_PORTSC_DATAMASK    0xffffffd1
+//
+// Terminate Pointer used for QueueHeads and Element Transfer Descriptors to mark Pointers as the end
+//
+#define TERMINATE_POINTER       0x01
+
+//
+// QUEUE ELEMENT TRANSFER DESCRIPTOR, defines and structs
+//
+
+//
+// Token Flags
+//
+#define PID_CODE_OUT_TOKEN      0x00
+#define PID_CODE_IN_TOKEN       0x01
+#define PID_CODE_SETUP_TOKEN    0x02
+
+#define DO_START_SPLIT          0x00
+#define DO_COMPLETE_SPLIT       0x01
+
+#define PING_STATE_DO_OUT       0x00
+#define PING_STATE_DO_PING      0x01
+
+typedef struct _PERIODICFRAMELIST
+{
+    PULONG VirtualAddr;
+    PHYSICAL_ADDRESS PhysicalAddr;
+    ULONG Size;
+} PERIODICFRAMELIST, *PPERIODICFRAMELIST;
+
+//
+// QUEUE ELEMENT TRANSFER DESCRIPTOR TOKEN
+//
+typedef struct _QETD_TOKEN_BITS
+{
+    ULONG PingState:1;
+    ULONG SplitTransactionState:1;
+    ULONG MissedMicroFrame:1;
+    ULONG TransactionError:1;
+    ULONG BabbleDetected:1;
+    ULONG DataBufferError:1;
+    ULONG Halted:1;
+    ULONG Active:1;
+    ULONG PIDCode:2;
+    ULONG ErrorCounter:2;
+    ULONG CurrentPage:3;
+    ULONG InterruptOnComplete:1;
+    ULONG TotalBytesToTransfer:15;
+    ULONG DataToggle:1;
+} QETD_TOKEN_BITS, *PQETD_TOKEN_BITS;
+
+//
+// QUEUE ELEMENT TRANSFER DESCRIPTOR
+//
+typedef struct _QUEUE_TRANSFER_DESCRIPTOR
+{
+    //Hardware
+    ULONG NextPointer;
+    ULONG AlternateNextPointer;
+    union
+    {
+        QETD_TOKEN_BITS Bits;
+        ULONG DWord;
+    } Token;
+    ULONG BufferPointer[5];
+    
+    //Software
+    ULONG PhysicalAddr;
+    LIST_ENTRY LinkedDescriptors;
+    ULONG TotalBytesToTransfer;
+} QUEUE_TRANSFER_DESCRIPTOR, *PQUEUE_TRANSFER_DESCRIPTOR;
+
+//
+// EndPointSpeeds Flags and END_POINT_CHARACTERISTICS
+//
+#define QH_ENDPOINT_FULLSPEED       0x00
+#define QH_ENDPOINT_LOWSPEED        0x01
+#define QH_ENDPOINT_HIGHSPEED       0x02
+typedef struct _END_POINT_CHARACTERISTICS
+{
+    ULONG DeviceAddress:7;
+    ULONG InactiveOnNextTransaction:1;
+    ULONG EndPointNumber:4;
+    ULONG EndPointSpeed:2;
+    ULONG QEDTDataToggleControl:1;
+    ULONG HeadOfReclamation:1;
+    ULONG MaximumPacketLength:11;
+    ULONG ControlEndPointFlag:1;
+    ULONG NakCountReload:4;
+} END_POINT_CHARACTERISTICS, *PEND_POINT_CHARACTERISTICS;
+
+//
+// Capabilities
+//
+typedef struct _END_POINT_CAPABILITIES
+{
+    ULONG InterruptScheduleMask:8;
+    ULONG SplitCompletionMask:8;
+    ULONG HubAddr:6;
+    ULONG PortNumber:6;
+    ULONG NumberOfTransactionPerFrame:2;
+} END_POINT_CAPABILITIES, *PEND_POINT_CAPABILITIES;
+
+//
+// QUEUE HEAD Flags and Struct
+//
+#define QH_TYPE_IDT             0x00
+#define QH_TYPE_QH              0x02
+#define QH_TYPE_SITD            0x04
+#define QH_TYPE_FSTN            0x06
+
+typedef struct _QUEUE_HEAD
+{
+    //Hardware
+    ULONG HorizontalLinkPointer;
+    END_POINT_CHARACTERISTICS EndPointCharacteristics;
+    END_POINT_CAPABILITIES EndPointCapabilities;
+    // TERMINATE_POINTER not valid for this member
+    ULONG CurrentLinkPointer;
+    // TERMINATE_POINTER valid
+    ULONG NextPointer;
+    // TERMINATE_POINTER valid, bits 1:4 is NAK_COUNTERd
+    ULONG AlternateNextPointer;
+    // Only DataToggle, InterruptOnComplete, ErrorCounter, PingState valid
+    union
+    {
+        QETD_TOKEN_BITS Bits;
+        ULONG DWord;
+    } Token;
+    ULONG BufferPointer[5];
+
+    //Software
+    ULONG PhysicalAddr;
+    LIST_ENTRY LinkedQueueHeads;
+    PVOID Request;
+} QUEUE_HEAD, *PQUEUE_HEAD;
+
+//
+// Command register content
+//
+typedef struct _EHCI_USBCMD_CONTENT
+{
+    ULONG Run : 1;
+    ULONG HCReset : 1;
+    ULONG FrameListSize : 2;
+    ULONG PeriodicEnable : 1;
+    ULONG AsyncEnable : 1;
+    ULONG DoorBell : 1;
+    ULONG LightReset : 1;
+    ULONG AsyncParkCount : 2;
+    ULONG Reserved : 1;
+    ULONG AsyncParkEnable : 1;
+    ULONG Reserved1 : 4;
+    ULONG IntThreshold : 8;
+    ULONG Reserved2 : 8;
+} EHCI_USBCMD_CONTENT, *PEHCI_USBCMD_CONTENT;
+
+typedef struct _EHCI_HCS_CONTENT
+{
+    ULONG PortCount : 4;
+    ULONG PortPowerControl: 1;
+    ULONG Reserved : 2;
+    ULONG PortRouteRules : 1;
+    ULONG PortPerCHC : 4;
+    ULONG CHCCount : 4;
+    ULONG PortIndicator : 1;
+    ULONG Reserved2 : 3;
+    ULONG DbgPortNum : 4;
+    ULONG Reserved3 : 8;
+
+} EHCI_HCS_CONTENT, *PEHCI_HCS_CONTENT;
+
+typedef struct _EHCI_HCC_CONTENT
+{
+    ULONG CurAddrBits : 1;
+    ULONG VarFrameList : 1;
+    ULONG ParkMode : 1;
+    ULONG Reserved : 1;
+    ULONG IsoSchedThreshold : 4;
+    ULONG EECPCapable : 8;
+    ULONG Reserved2 : 16;
+
+} EHCI_HCC_CONTENT, *PEHCI_HCC_CONTENT;
+
+typedef struct _EHCI_CAPS {
+    UCHAR Length;
+    UCHAR Reserved;
+    USHORT HCIVersion;
+    union
+    {
+        EHCI_HCS_CONTENT HCSParams;
+        ULONG HCSParamsLong;
+    };
+    union
+    {
+        EHCI_HCC_CONTENT HCCParams;
+        ULONG HCCParamsLong;
+    };
+    UCHAR PortRoute [8];
+} EHCI_CAPS, *PEHCI_CAPS;
+
+
+typedef struct
+{
+    PKSPIN_LOCK Lock;
+    RTL_BITMAP Bitmap;
+    PULONG BitmapBuffer;
+    ULONG BlockSize;
+    PVOID VirtualBase;
+    PHYSICAL_ADDRESS PhysicalBase;
+    ULONG Length;
+}DMA_MEMORY_ALLOCATOR, *LPDMA_MEMORY_ALLOCATOR;
+
+typedef struct _EHCI_HOST_CONTROLLER
+{
+    ULONG OpRegisters;
+    EHCI_CAPS ECHICaps;
+    PVOID CommonBufferVA;
+    PHYSICAL_ADDRESS CommonBufferPA;
+    ULONG CommonBufferSize;
+    PQUEUE_HEAD AsyncListQueue;
+    KSPIN_LOCK Lock;
+    LPDMA_MEMORY_ALLOCATOR DmaMemAllocator;
+} EHCI_HOST_CONTROLLER, *PEHCI_HOST_CONTROLLER;
+
+typedef struct
+{
+    ULONG PortStatus;
+    ULONG PortChange;
+}EHCI_PORT_STATUS;
+
diff --git a/drivers/usb/usbehci_new/hcd_controller.cpp b/drivers/usb/usbehci_new/hcd_controller.cpp
new file mode 100644 (file)
index 0000000..5a6318e
--- /dev/null
@@ -0,0 +1,751 @@
+/*
+ * PROJECT:     ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/usb/usbehci/hcd_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 CHCDController : public IHCDController,
+                       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;
+    }
+
+    // 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);
+
+    // local functions
+    NTSTATUS CreateFDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
+    NTSTATUS SetSymbolicLink(BOOLEAN Enable);
+
+    // constructor / destructor
+    CHCDController(IUnknown *OuterUnknown){}
+    virtual ~CHCDController(){}
+
+protected:
+    LONG m_Ref;
+    PROOTHDCCONTROLLER m_RootController;
+    PDRIVER_OBJECT m_DriverObject;
+    PDEVICE_OBJECT m_PhysicalDeviceObject;
+    PDEVICE_OBJECT m_FunctionalDeviceObject;
+    PDEVICE_OBJECT m_NextDeviceObject;
+    PUSBHARDWAREDEVICE m_Hardware;
+    PHUBCONTROLLER m_HubController;
+    ULONG m_FDODeviceNumber;
+};
+
+//=================================================================================================
+// COM
+//
+NTSTATUS
+STDMETHODCALLTYPE
+CHCDController::QueryInterface(
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    return STATUS_UNSUCCESSFUL;
+}
+
+//-------------------------------------------------------------------------------------------------
+NTSTATUS
+CHCDController::Initialize(
+    IN PROOTHDCCONTROLLER RootHCDController,
+    IN PDRIVER_OBJECT DriverObject,
+    IN PDEVICE_OBJECT PhysicalDeviceObject)
+{
+    NTSTATUS Status;
+    PCOMMON_DEVICE_EXTENSION DeviceExtension;
+
+    //
+    // create usb hardware
+    //
+    Status = CreateUSBHardware(&m_Hardware);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to create hardware object
+        //
+        DPRINT1("Failed to create hardware object\n");
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // initialize members
+    //
+    m_DriverObject = DriverObject;
+    m_PhysicalDeviceObject = PhysicalDeviceObject;
+    m_RootController = RootHCDController;
+
+    //
+    // create FDO
+    //
+    Status = CreateFDO(m_DriverObject, &m_FunctionalDeviceObject);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to create PDO
+        //
+        return Status;
+    }
+
+    //
+    // now attach to device stack
+    //
+    m_NextDeviceObject = IoAttachDeviceToDeviceStack(m_FunctionalDeviceObject, m_PhysicalDeviceObject);
+    if (!m_NextDeviceObject)
+    {
+        //
+        // failed to attach to device stack
+        //
+        IoDeleteDevice(m_FunctionalDeviceObject);
+        m_FunctionalDeviceObject = 0;
+
+        return STATUS_NO_SUCH_DEVICE;
+    }
+
+    //
+    // initialize hardware object
+    //
+    Status = m_Hardware->Initialize(m_DriverObject, m_FunctionalDeviceObject, m_PhysicalDeviceObject, m_NextDeviceObject);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to initialize hardware object %x\n", Status);
+
+        //
+        // failed to initialize hardware object, detach from device stack
+        //
+        IoDetachDevice(m_NextDeviceObject);
+
+        //
+        // now delete the device
+        //
+        IoDeleteDevice(m_FunctionalDeviceObject);
+
+        //
+        // nullify pointers :)
+        //
+        m_FunctionalDeviceObject = 0;
+        m_NextDeviceObject = 0;
+
+        return Status;
+    }
+
+
+    //
+    // set device flags
+    //
+    m_FunctionalDeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
+
+
+    //
+    // get device extension
+    //
+    DeviceExtension = (PCOMMON_DEVICE_EXTENSION)m_FunctionalDeviceObject->DeviceExtension;
+    PC_ASSERT(DeviceExtension);
+
+    //
+    // initialize device extension
+    //
+    DeviceExtension->IsFDO = TRUE;
+    DeviceExtension->IsHub = FALSE;
+    DeviceExtension->Dispatcher = PDISPATCHIRP(this);
+
+    //
+    // device is initialized
+    //
+    m_FunctionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+
+
+    //
+    // is there a root controller
+    //
+    if (m_RootController)
+    {
+        //
+        // add reference
+        //
+        m_RootController->AddRef();
+
+        //
+        // register with controller
+        //
+        m_RootController->RegisterHCD(this);
+    }
+
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
+//-------------------------------------------------------------------------------------------------
+NTSTATUS
+CHCDController::HandleDeviceControl(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    PCOMMON_DEVICE_EXTENSION DeviceExtension;
+    NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
+    PUSB_HCD_DRIVERKEY_NAME DriverKey;
+    ULONG ResultLength;
+
+    //
+    // get current stack location
+    //
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    //
+    // get device extension
+    //
+    DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(DeviceExtension->IsFDO);
+
+    DPRINT1("HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu\n",
+        IoStack->Parameters.DeviceIoControl.IoControlCode,
+        IoStack->Parameters.DeviceIoControl.InputBufferLength,
+        IoStack->Parameters.DeviceIoControl.OutputBufferLength);
+
+    //
+    // perform ioctl for FDO
+    //
+    if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_HCD_DRIVERKEY_NAME)
+    {
+        //
+        // check if sizee is at least >= USB_HCD_DRIVERKEY_NAME
+        //
+        if(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(USB_HCD_DRIVERKEY_NAME))
+        {
+            //
+            // get device property size
+            //
+            Status = IoGetDeviceProperty(m_PhysicalDeviceObject, DevicePropertyDriverKeyName, 0, NULL, &ResultLength);
+
+            //
+            // get input buffer
+            //
+            DriverKey = (PUSB_HCD_DRIVERKEY_NAME)Irp->AssociatedIrp.SystemBuffer;
+
+            //
+            // check result
+            //
+            if (Status == STATUS_BUFFER_TOO_SMALL)
+            {
+                //
+                // does the caller provide enough buffer space
+                //
+                if (IoStack->Parameters.DeviceIoControl.OutputBufferLength >= ResultLength)
+                {
+                    //
+                    // it does
+                    //
+                    Status = IoGetDeviceProperty(m_PhysicalDeviceObject, DevicePropertyDriverKeyName, IoStack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(ULONG), DriverKey->DriverKeyName, &ResultLength);
+
+                    if (NT_SUCCESS(Status))
+                    {
+                        //
+                        // informal debug print
+                        //
+                        DPRINT1("Result %S\n", DriverKey->DriverKeyName);
+                    }
+                }
+
+                //
+                // store result
+                //
+                DriverKey->ActualLength = ResultLength + FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + sizeof(WCHAR);
+                Irp->IoStatus.Information = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
+                Status = STATUS_SUCCESS;
+            }
+        }
+        else
+        {
+            //
+            // buffer is certainly too small
+            //
+            Status = STATUS_BUFFER_OVERFLOW;
+            Irp->IoStatus.Information = sizeof(USB_HCD_DRIVERKEY_NAME);
+        }
+    }
+    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USB_GET_ROOT_HUB_NAME)
+    {
+        //
+        // check if sizee is at least >= USB_HCD_DRIVERKEY_NAME
+        //
+        if(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(USB_HCD_DRIVERKEY_NAME))
+        {
+            //
+            // sanity check
+            //
+            PC_ASSERT(m_HubController);
+
+            //
+            // get input buffer
+            //
+            DriverKey = (PUSB_HCD_DRIVERKEY_NAME)Irp->AssociatedIrp.SystemBuffer;
+
+            //
+            // get symbolic link
+            //
+            Status = m_HubController->GetHubControllerSymbolicLink(IoStack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(ULONG), DriverKey->DriverKeyName, &ResultLength);
+
+
+            if (NT_SUCCESS(Status))
+            {
+                //
+                // null terminate it
+                //
+                PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(ULONG) - sizeof(WCHAR) >= ResultLength);
+
+                DriverKey->DriverKeyName[ResultLength / sizeof(WCHAR)] = L'\0';
+                DPRINT1("Result %S\n", DriverKey->DriverKeyName);
+            }
+
+            //
+            // store result
+            //
+            DriverKey->ActualLength = ResultLength + FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + sizeof(WCHAR);
+            Irp->IoStatus.Information = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
+            Status = STATUS_SUCCESS;
+        }
+        else
+        {
+            //
+            // buffer is certainly too small
+            //
+            Status = STATUS_BUFFER_OVERFLOW;
+            Irp->IoStatus.Information = sizeof(USB_HCD_DRIVERKEY_NAME);
+        }
+    }
+
+    //
+    // complete the request
+    //
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    //
+    // done
+    //
+    return Status;
+}
+
+NTSTATUS
+CHCDController::HandlePnp(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    PCOMMON_DEVICE_EXTENSION DeviceExtension;
+    PCM_RESOURCE_LIST RawResourceList;
+    PCM_RESOURCE_LIST TranslatedResourceList;
+    PDEVICE_RELATIONS DeviceRelations;
+    NTSTATUS Status;
+
+    //
+    // get device extension
+    //
+    DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(DeviceExtension->IsFDO);
+
+    //
+    // get current stack location
+    //
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    switch(IoStack->MinorFunction)
+    {
+        case IRP_MN_START_DEVICE:
+        {
+            DPRINT1("CHCDController::HandlePnp IRP_MN_START FDO\n");
+
+            //
+            // first start lower device object
+            //
+            Status = SyncForwardIrp(m_NextDeviceObject, Irp);
+
+            if (NT_SUCCESS(Status))
+            {
+                //
+                // operation succeeded, lets start the device
+                //
+                RawResourceList = IoStack->Parameters.StartDevice.AllocatedResources;
+                TranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
+
+                if (m_Hardware)
+                {
+                    //
+                    // start the hardware
+                    //
+                    Status = m_Hardware->PnpStart(RawResourceList, TranslatedResourceList);
+                }
+
+                //
+                // enable symbolic link
+                //
+                Status = SetSymbolicLink(TRUE);
+            }
+
+            DPRINT1("CHCDController::HandlePnp IRP_MN_START FDO: Status %x\n", Status);
+            break;
+        }
+        case IRP_MN_QUERY_DEVICE_RELATIONS:
+        {
+            DPRINT1("CHCDController::HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %lx\n", IoStack->Parameters.QueryDeviceRelations.Type);
+
+            if (m_HubController == NULL)
+            {
+                //
+                // create hub controller
+                //
+                Status = CreateHubController(&m_HubController);
+                if (!NT_SUCCESS(Status))
+                {
+                    //
+                    // failed to create hub controller
+                    //
+                    break;
+                }
+
+                //
+                // initialize hub controller
+                //
+                Status = m_HubController->Initialize(m_DriverObject, PHCDCONTROLLER(this), m_Hardware, TRUE, 0 /* FIXME*/);
+                if (!NT_SUCCESS(Status))
+                {
+                    //
+                    // failed to initialize hub controller
+                    //
+                    break;
+                }
+
+                //
+                // add reference to prevent it from getting deleting while hub driver adds / removes references
+                //
+                m_HubController->AddRef();
+            }
+
+            if (IoStack->Parameters.QueryDeviceRelations.Type == BusRelations)
+            {
+                //
+                // allocate device relations
+                //
+                DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
+                if (!DeviceRelations)
+                {
+                    //
+                    // no memory
+                    //
+                    Status = STATUS_INSUFFICIENT_RESOURCES;
+                    break;
+                }
+
+                //
+                // init device relations
+                //
+                DeviceRelations->Count = 1;
+                Status = m_HubController->GetHubControllerDeviceObject(&DeviceRelations->Objects [0]);
+
+                //
+                // sanity check
+                //
+                PC_ASSERT(Status == STATUS_SUCCESS);
+
+                ObReferenceObject(DeviceRelations->Objects [0]);
+
+                //
+                // store result
+                //
+                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("CHCDController::HandlePnp IRP_MN_STOP_DEVICE\n");
+
+            if (m_Hardware)
+            {
+                //
+                // stop the hardware
+                //
+                Status = m_Hardware->PnpStop();
+            }
+            else
+            {
+                //
+                // fake success 
+                //
+                Status = STATUS_SUCCESS;
+            }
+
+            if (NT_SUCCESS(Status))
+            {
+                //
+                // stop lower device
+                //
+                Status = SyncForwardIrp(m_NextDeviceObject, Irp);
+            }
+            break;
+        }
+        case IRP_MN_REMOVE_DEVICE:
+        {
+            DPRINT1("CHCDController::HandlePnp IRP_MN_REMOVE_DEVICE FDO\n");
+
+            //
+            // detach device from device stack
+            //
+            IoDetachDevice(m_NextDeviceObject);
+
+            //
+            // delete device
+            //
+            IoDeleteDevice(m_FunctionalDeviceObject);
+
+            Status = STATUS_SUCCESS;
+            break;
+        }
+        default:
+        {
+            //
+            // forward irp to next device object
+            //
+            IoSkipCurrentIrpStackLocation(Irp);
+            return IoCallDriver(m_NextDeviceObject, Irp);
+        }
+    }
+
+    //
+    // store result and complete request
+    //
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return Status;
+}
+
+NTSTATUS
+CHCDController::HandlePower(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    UNIMPLEMENTED
+
+    Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+CHCDController::CreateFDO(
+    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\\USBFDO-%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("CreateFDO: Failed to create %wZ, Status %x\n", &DeviceName, Status);
+            return Status;
+        }
+    }
+
+    //
+    // store FDO number
+    //
+    m_FDODeviceNumber = UsbDeviceNumber;
+
+    DPRINT1("CreateFDO: DeviceName %wZ\n", &DeviceName);
+
+    /* done */
+    return Status;
+}
+
+NTSTATUS
+CHCDController::SetSymbolicLink(
+    BOOLEAN Enable)
+{
+    NTSTATUS Status;
+    WCHAR LinkName[32];
+    WCHAR FDOName[32];
+    UNICODE_STRING Link, FDO;
+
+    if (Enable)
+    {
+        //
+        // create legacy link
+        //
+        swprintf(LinkName, L"\\DosDevices\\HCD%d", m_FDODeviceNumber);
+        swprintf(FDOName, L"\\Device\\USBFDO-%d", m_FDODeviceNumber);
+        RtlInitUnicodeString(&Link, LinkName);
+        RtlInitUnicodeString(&FDO, FDOName);
+
+        //
+        // create symbolic link
+        //
+        Status = IoCreateSymbolicLink(&Link, &FDO);
+
+        if (!NT_SUCCESS(Status))
+        {
+            //
+            // FIXME: handle me
+            //
+            ASSERT(0);
+        }
+    }
+    else
+    {
+        //
+        // create legacy link
+        //
+        swprintf(LinkName, L"\\DosDevices\\HCD%d", m_FDODeviceNumber);
+        RtlInitUnicodeString(&Link, LinkName);
+
+        //
+        // now delete the symbolic link
+        //
+        Status = IoDeleteSymbolicLink(&Link);
+
+        if (!NT_SUCCESS(Status))
+        {
+            //
+            // FIXME: handle me
+            //
+            ASSERT(0);
+        }
+    }
+
+    //
+    // done
+    //
+    return Status;
+}
+
+NTSTATUS
+CreateHCDController(
+    PHCDCONTROLLER *OutHcdController)
+{
+    PHCDCONTROLLER This;
+
+    //
+    // allocate controller
+    //
+    This = new(NonPagedPool, TAG_USBEHCI) CHCDController(0);
+    if (!This)
+    {
+        //
+        // failed to allocate
+        //
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // add reference count
+    //
+    This->AddRef();
+
+    //
+    // return result
+    //
+    *OutHcdController = (PHCDCONTROLLER)This;
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
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..b76a00f
--- /dev/null
@@ -0,0 +1,3217 @@
+/*
+ * 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"
+
+VOID StatusChangeEndpointCallBack(
+    PVOID Context);
+
+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);
+    virtual NTSTATUS GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject);
+    virtual NTSTATUS GetHubControllerSymbolicLink(ULONG BufferLength, PVOID Buffer, PULONG RequiredLength);
+
+    // 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);
+    PUSBHARDWAREDEVICE GetUsbHardware();
+    ULONG AcquireDeviceAddress();
+    VOID ReleaseDeviceAddress(ULONG DeviceAddress);
+    BOOLEAN ValidateUsbDevice(PUSBDEVICE UsbDevice);
+    NTSTATUS AddUsbDevice(PUSBDEVICE UsbDevice);
+    NTSTATUS RemoveUsbDevice(PUSBDEVICE UsbDevice);
+    VOID SetNotification(PVOID CallbackContext, PRH_INIT_CALLBACK CallbackRoutine);
+    // internal ioctl routines
+    NTSTATUS HandleGetDescriptor(IN OUT PIRP Irp, PURB Urb);
+    NTSTATUS HandleClassDevice(IN OUT PIRP Irp, PURB Urb);
+    NTSTATUS HandleGetStatusFromDevice(IN OUT PIRP Irp, PURB Urb);
+    NTSTATUS HandleSelectConfiguration(IN OUT PIRP Irp, PURB Urb);
+    NTSTATUS HandleSelectInterface(IN OUT PIRP Irp, PURB Urb);
+    NTSTATUS HandleClassOther(IN OUT PIRP Irp, PURB Urb);
+    NTSTATUS HandleClassInterface(IN OUT PIRP Irp, PURB Urb);
+    NTSTATUS HandleBulkOrInterruptTransfer(IN OUT PIRP Irp, PURB Urb);
+
+    friend VOID StatusChangeEndpointCallBack(PVOID Context);
+
+    // constructor / destructor
+    CHubController(IUnknown *OuterUnknown){}
+    virtual ~CHubController(){}
+
+protected:
+    LONG m_Ref;
+    PHCDCONTROLLER m_Controller;
+    PUSBHARDWAREDEVICE m_Hardware;
+    BOOLEAN m_IsRootHubDevice;
+    ULONG m_DeviceAddress;
+
+    BOOLEAN m_InterfaceEnabled;
+    UNICODE_STRING m_HubDeviceInterfaceString;
+
+    PDEVICE_OBJECT m_HubControllerDeviceObject;
+    PDRIVER_OBJECT m_DriverObject;
+
+    PVOID m_HubCallbackContext; 
+    PRH_INIT_CALLBACK m_HubCallbackRoutine;
+
+    USB_DEVICE_DESCRIPTOR m_DeviceDescriptor;
+
+    KSPIN_LOCK m_Lock;
+    RTL_BITMAP m_DeviceAddressBitmap;
+    PULONG m_DeviceAddressBitmapBuffer;
+    LIST_ENTRY m_UsbDeviceList;
+    PIRP m_PendingSCEIrp;
+
+    //Internal Functions
+    BOOLEAN QueryStatusChageEndpoint(PIRP Irp);
+};
+
+typedef struct
+{
+    LIST_ENTRY Entry;
+    PUSBDEVICE Device;
+}USBDEVICE_ENTRY, *PUSBDEVICE_ENTRY;
+
+/* Lifted from Linux with slight changes */
+const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR [] =
+{
+    0x12,       /*  bLength; */
+    USB_DEVICE_DESCRIPTOR_TYPE,       /*  bDescriptorType; Device */
+    0x00, 0x20, /*  bcdUSB; v1.1 */
+    USB_DEVICE_CLASS_HUB,       /*  bDeviceClass; HUB_CLASSCODE */
+    0x01,       /*  bDeviceSubClass; */
+    0x00,       /*  bDeviceProtocol; [ low/full speeds only ] */
+    0x08,       /*  bMaxPacketSize0; 8 Bytes */
+    /* Fill Vendor and Product in when init root hub */
+    0x00, 0x00, /*  idVendor; */
+    0x00, 0x00, /*  idProduct; */
+    0x00, 0x00, /*  bcdDevice */
+    0x00,       /*  iManufacturer; */
+    0x00,       /*  iProduct; */
+    0x00,       /*  iSerialNumber; */
+    0x01        /*  bNumConfigurations; */
+
+};
+
+const USB_CONFIGURATION_DESCRIPTOR ROOTHUB2_CONFIGURATION_DESCRIPTOR =
+{
+    sizeof(USB_CONFIGURATION_DESCRIPTOR),
+    USB_CONFIGURATION_DESCRIPTOR_TYPE,
+    sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR),
+    1,
+    1,
+    0,
+    0x40, /* self powered */
+    0x0
+};
+
+const USB_INTERFACE_DESCRIPTOR ROOTHUB2_INTERFACE_DESCRIPTOR =
+{
+    sizeof(USB_INTERFACE_DESCRIPTOR),                            /* bLength */
+    USB_INTERFACE_DESCRIPTOR_TYPE,                               /* bDescriptorType; Interface */
+    0,                                                           /* bInterfaceNumber; */
+    0,                                                           /* bAlternateSetting; */
+    0x1,                                                         /* bNumEndpoints; */
+    0x09,                                                        /* bInterfaceClass; HUB_CLASSCODE */
+    0x01,                                                        /* bInterfaceSubClass; */
+    0x00,                                                        /* bInterfaceProtocol: */
+    0x00,                                                        /* iInterface; */
+};
+
+const USB_ENDPOINT_DESCRIPTOR ROOTHUB2_ENDPOINT_DESCRIPTOR =
+{
+    sizeof(USB_ENDPOINT_DESCRIPTOR),                             /* bLength */
+    USB_ENDPOINT_DESCRIPTOR_TYPE,                                /* bDescriptorType */
+    0x81,                                                        /* bEndPointAddress */
+    USB_ENDPOINT_TYPE_INTERRUPT,                                 /* bmAttributes */
+    0x01,                                                        /* wMaxPacketSize */
+    0xC                                                          /* bInterval */
+};
+
+//----------------------------------------------------------------------------------------
+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;
+    USHORT VendorID, DeviceID;
+    ULONG Dummy1;
+
+    DPRINT1("CHubController::Initialize\n");
+
+    //
+    // initialize members
+    //
+    m_Controller = Controller;
+    m_Hardware = Device;
+    m_IsRootHubDevice = IsRootHubDevice;
+    m_DeviceAddress = DeviceAddress;
+    m_DriverObject = DriverObject;
+    KeInitializeSpinLock(&m_Lock);
+    InitializeListHead(&m_UsbDeviceList);
+
+    //
+    // allocate device address bitmap buffer
+    //
+    m_DeviceAddressBitmapBuffer = (PULONG)ExAllocatePoolWithTag(NonPagedPool, 16, TAG_USBEHCI);
+    if (!m_DeviceAddressBitmapBuffer)
+    {
+        //
+        // no memory
+        //
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // initialize device address bitmap
+    //
+    RtlInitializeBitMap(&m_DeviceAddressBitmap, m_DeviceAddressBitmapBuffer, 128);
+    RtlClearAllBits(&m_DeviceAddressBitmap);
+
+
+    //
+    // 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);
+
+    //
+    // intialize device descriptor
+    //
+    C_ASSERT(sizeof(USB_DEVICE_DESCRIPTOR) == sizeof(ROOTHUB2_DEVICE_DESCRIPTOR));
+    RtlMoveMemory(&m_DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(USB_DEVICE_DESCRIPTOR));
+
+    if (NT_SUCCESS(m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &Dummy1, &Dummy1)))
+    {
+        //
+        // update device descriptor
+        //
+        m_DeviceDescriptor.idVendor = VendorID;
+        m_DeviceDescriptor.idProduct = DeviceID;
+        m_DeviceDescriptor.bcdUSB = 0x200; //FIXME
+    }
+
+    //
+    // Set the SCE Callback that the Hardware Device will call on port status change
+    //
+    Device->SetStatusChangeEndpointCallBack((PVOID)StatusChangeEndpointCallBack, this);
+
+    //
+    // clear init flag
+    //
+    m_HubControllerDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+
+    return STATUS_SUCCESS;
+}
+
+//
+// Queries the ports to see if there has been a device connected or removed.
+//
+BOOLEAN
+CHubController::QueryStatusChageEndpoint(
+    PIRP Irp)
+{
+    ULONG PortCount, PortId;
+    PIO_STACK_LOCATION IoStack;
+    USHORT PortStatus, PortChange;
+    PURB Urb;
+    PUCHAR TransferBuffer;
+    UCHAR Changed = FALSE;
+
+    //
+    // get current stack location
+    //
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    ASSERT(IoStack);
+
+    //
+    // Get the Urb
+    //
+    Urb = (PURB)IoStack->Parameters.Others.Argument1;
+    ASSERT(Urb);
+
+    //
+    // Get the number of ports and check each one for device connected
+    //
+    m_Hardware->GetDeviceDetails(NULL, NULL, &PortCount, NULL);
+    DPRINT1("SCE Request %p TransferBufferLength %lu Flags %x MDL %p\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength, Urb->UrbBulkOrInterruptTransfer.TransferFlags, Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
+
+    TransferBuffer = (PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer;
+
+    //
+    // Loop the ports
+    //
+    for (PortId = 0; PortId < PortCount; PortId++)
+    {
+        m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange);
+
+        DPRINT1("Port %d: Status %x, Change %x\n", PortId, PortStatus, PortChange);
+
+
+        //
+        // If theres a flag in PortChange return TRUE so the SCE Irp will be completed
+        //
+        if (PortChange != 0)
+        {
+            DPRINT1("Change state on port %d\n", PortId);
+            // Set the value for the port number
+             *TransferBuffer = 1 << ((PortId + 1) & 7);
+            Changed = TRUE;
+        }
+    }
+
+    return Changed;
+}
+
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject)
+{
+    //
+    // store controller object
+    //
+    *HubDeviceObject = m_HubControllerDeviceObject;
+
+    return STATUS_SUCCESS;
+}
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::GetHubControllerSymbolicLink(
+    ULONG BufferLength,
+    PVOID Buffer,
+    PULONG RequiredLength)
+{
+    if (!m_InterfaceEnabled)
+    {
+        //
+        // device interface not yet enabled
+        //
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    if (BufferLength < (ULONG)m_HubDeviceInterfaceString.Length - 8)
+    {
+        //
+        // buffer too small
+        // length is without '\??\'
+        //
+        *RequiredLength = m_HubDeviceInterfaceString.Length- 8;
+
+        //
+        // done
+        //
+        return STATUS_BUFFER_OVERFLOW;
+    }
+
+    //
+    // copy symbolic link
+    //
+    RtlCopyMemory(Buffer, &m_HubDeviceInterfaceString.Buffer[4], m_HubDeviceInterfaceString.Length - 8);
+
+    //
+    // store length, length is without '\??\'
+    //
+    *RequiredLength = m_HubDeviceInterfaceString.Length - 8;
+
+    //
+    // done
+    //
+    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;
+    PPNP_BUS_INFORMATION BusInformation;
+    PDEVICE_RELATIONS DeviceRelations;
+    NTSTATUS Status;
+    ULONG Index = 0, Length;
+    USHORT VendorID, DeviceID;
+    ULONG HiSpeed, NumPorts;
+    WCHAR Buffer[300];
+    LPWSTR DeviceName;
+
+    //
+    // 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_ID:
+        {
+            DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_ID Type %x\n", IoStack->Parameters.QueryId.IdType);
+
+            if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID)
+            {
+                if (m_Hardware)
+                {
+                    //
+                    // query device id
+                    //
+                    Status = m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &NumPorts, &HiSpeed);
+
+                    if (HiSpeed == 0x200)
+                    {
+                        //
+                        // USB 2.0 hub
+                        //
+                        swprintf(Buffer, L"USB\\ROOT_HUB20");
+                    }
+                    else
+                    {
+                        //
+                        // USB 1.1 hub
+                        //
+                        swprintf(Buffer, L"USB\\ROOT_HUB");
+                    }
+
+                    DPRINT1("Name %S\n", Buffer);
+
+                    //
+                    // calculate length
+                    //
+                    Length = (wcslen(Buffer) + 1);
+
+                    //
+                    // allocate buffer
+                    //
+                    DeviceName = (LPWSTR)ExAllocatePoolWithTag(PagedPool, Length * sizeof(WCHAR), TAG_USBEHCI);
+
+                    if (!DeviceName)
+                    {
+                        //
+                        // no memory
+                        //
+                        Status = STATUS_INSUFFICIENT_RESOURCES;
+                        break;
+                    }
+
+                    //
+                    // copy device name
+                    //
+                    wcscpy(DeviceName, Buffer);
+
+                    //
+                    // store result
+                    //
+                    Irp->IoStatus.Information = (ULONG_PTR)DeviceName;
+                    Status = STATUS_SUCCESS;
+                    break;
+                 }
+                 Status = STATUS_UNSUCCESSFUL;
+                 PC_ASSERT(0);
+                 break;
+            }
+
+            if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
+            {
+                if (m_Hardware)
+                {
+                    //
+                    // query device id
+                    //
+                    Status = m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &NumPorts, &HiSpeed);
+
+                    if (!NT_SUCCESS(Status))
+                    {
+                         DPRINT1("CHubController::HandlePnp> failed to get hardware id %x\n", Status);
+                         VendorID = 0x8086;
+                         DeviceID = 0x3A37;
+                    }
+
+                    if (HiSpeed == 0x200)
+                    {
+                        //
+                        // USB 2.0 hub
+                        //
+                        Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID%04x&PID%04x&REV0000", VendorID, DeviceID) + 1;
+                        Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID%04x&PID%04x", VendorID, DeviceID) + 1;
+                        Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20") + 1;
+                    }
+                    else
+                    {
+                        //
+                        // USB 1.1 hub
+                        //
+                        Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB&VID%04x&PID%04x&REV0000", VendorID, DeviceID) + 1;
+                        Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB&VID%04x&PID%04x", VendorID, DeviceID) + 1;
+                        Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB") + 1;
+                    }
+
+                   Buffer[Index] = UNICODE_NULL;
+                   Index++;
+
+
+                    DPRINT1("Name %S\n", Buffer);
+
+                    //
+                    // allocate buffer
+                    //
+                    DeviceName = (LPWSTR)ExAllocatePoolWithTag(PagedPool, Index * sizeof(WCHAR), TAG_USBEHCI);
+
+                    if (!DeviceName)
+                    {
+                        //
+                        // no memory
+                        //
+                        Status = STATUS_INSUFFICIENT_RESOURCES;
+                        break;
+                    }
+
+                    //
+                    // copy device name
+                    //
+                    RtlMoveMemory(DeviceName, Buffer, Index * sizeof(WCHAR));
+
+                    //
+                    // store result
+                    //
+                    Irp->IoStatus.Information = (ULONG_PTR)DeviceName;
+                    Status = STATUS_SUCCESS;
+                    break;
+                }
+            }
+            Status = STATUS_SUCCESS;
+            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;
+
+            //
+            // done
+            //
+            return STATUS_SUCCESS;
+        }
+        case IRP_MN_QUERY_DEVICE_RELATIONS:
+        {
+            DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %x\n", IoStack->Parameters.QueryDeviceRelations.Type);
+
+            if (IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation)
+            {
+                //
+                // allocate device relations
+                //
+                DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(PagedPool, sizeof(DEVICE_RELATIONS), TAG_USBEHCI);
+                if (!DeviceRelations)
+                {
+                    //
+                    // no memory
+                    //
+                    Status = STATUS_INSUFFICIENT_RESOURCES;
+                    break;
+                }
+
+                //
+                // initialize device relations
+                //
+                DeviceRelations->Count = 1;
+                DeviceRelations->Objects[0] = DeviceObject;
+                ObReferenceObject(DeviceObject);
+
+                //
+                // done
+                //
+                Status = STATUS_SUCCESS;
+                Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
+            }
+            else
+            {
+                //
+                // not handled
+                //
+                Status = Irp->IoStatus.Status;
+            }
+            break;
+        }
+        case IRP_MN_QUERY_BUS_INFORMATION:
+        {
+            DPRINT1("CHubController::HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n");
+
+            //
+            // allocate buffer for bus information
+            //
+            BusInformation = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
+            if (BusInformation)
+            {
+                //
+                // copy BUS guid
+                //
+                RtlMoveMemory(&BusInformation->BusTypeGuid, &GUID_BUS_TYPE_USB, sizeof(GUID));
+
+                //
+                // set bus type
+                //
+                BusInformation->LegacyBusType = PNPBus;
+                BusInformation->BusNumber = 0;
+
+                Status = STATUS_SUCCESS;
+                Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
+            }
+            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:
+        {
+            //
+            // ignore request with default status
+            //
+            Status = Irp->IoStatus.Status;
+            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
+    Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    return STATUS_NOT_IMPLEMENTED;
+}
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::HandleBulkOrInterruptTransfer(
+    IN OUT PIRP Irp, 
+    PURB Urb)
+{
+    PUSBDEVICE UsbDevice;
+    PUSB_ENDPOINT_DESCRIPTOR EndPointDesc = NULL;
+    //
+    // First check if the request is for the Status Change Endpoint
+    //
+
+    //
+    // Is the Request for the root hub
+    //
+    if (Urb->UrbHeader.UsbdDeviceHandle == 0)
+    {
+        ASSERT(m_PendingSCEIrp == NULL);
+        if (QueryStatusChageEndpoint(Irp))
+        {
+            StatusChangeEndpointCallBack(this);
+            return STATUS_SUCCESS;
+        }
+
+        //
+        // Else pend the IRP, to be completed when a device connects or disconnects.
+        //
+        DPRINT1("Pending SCE Irp\n");;
+        m_PendingSCEIrp = Irp;
+        IoMarkIrpPending(Irp);
+        return STATUS_PENDING;
+    }
+
+    //
+    // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
+    //
+    EndPointDesc = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
+
+    switch(EndPointDesc->bmAttributes & 0x0F)
+    {
+        case USB_ENDPOINT_TYPE_CONTROL:
+            DPRINT1("Control Transfer is not expected!!!\n");
+            return STATUS_INVALID_DEVICE_REQUEST;
+        case USB_ENDPOINT_TYPE_BULK:
+            DPRINT("Initiating Bulk Transfer\n");
+            break;
+        case USB_ENDPOINT_TYPE_ISOCHRONOUS:
+        case USB_ENDPOINT_TYPE_INTERRUPT:
+            DPRINT1("Not Supported\n");
+            break;
+        default:
+            DPRINT1("Unknown EndPoint Type!\n");
+            break;
+    }
+
+    //
+    // check if this is a valid usb device handle
+    //
+    PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
+
+    //
+    // get device
+    //
+    UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
+
+    return UsbDevice->SubmitIrp(Irp);
+}
+
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::HandleClassOther(
+    IN OUT PIRP Irp, 
+    PURB Urb)
+{
+    NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
+    USHORT PortStatus = 0, PortChange = 0;
+    PUSHORT Buffer;
+    ULONG NumPort;
+    ULONG PortId;
+
+    DPRINT("CHubController::HandleClassOther> Request %x Value %x\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value);
+
+    //
+    // get number of ports available
+    //
+    Status = m_Hardware->GetDeviceDetails(NULL, NULL, &NumPort, NULL);
+    PC_ASSERT(Status == STATUS_SUCCESS);
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(Urb->UrbControlVendorClassRequest.Index - 1 < (USHORT)NumPort);
+
+    //
+    // port range reported start from 1 -n
+    // convert back port id so it matches the hardware
+    //
+    PortId = Urb->UrbControlVendorClassRequest.Index - 1;
+
+    //
+    // check request code
+    //
+    switch(Urb->UrbControlVendorClassRequest.Request)
+    {
+        case USB_REQUEST_GET_STATUS:
+        {
+            //
+            // sanity check
+            //
+            PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength == sizeof(USHORT) * 2);
+            PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
+
+            //
+            // get port status
+            //
+            Status = m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange);
+
+            if (NT_SUCCESS(Status))
+            {
+                //
+                // request contains buffer of 2 ushort which are used from submitting port status and port change status
+                //
+                DPRINT("PortId %x PortStatus %x PortChange %x\n", PortId, PortStatus, PortChange);
+                Buffer = (PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer;
+
+                //
+                // store status, then port change
+                //
+                *Buffer = PortStatus;
+                Buffer++;
+                *Buffer = PortChange;
+            }
+
+            //
+            // done
+            //
+            break;
+        }
+        case USB_REQUEST_CLEAR_FEATURE:
+        {
+            switch (Urb->UrbControlVendorClassRequest.Value)
+            {
+                case C_PORT_CONNECTION:
+                    Status = m_Hardware->ClearPortStatus(PortId, C_PORT_CONNECTION);
+                    break;
+                case C_PORT_RESET:
+                    Status= m_Hardware->ClearPortStatus(PortId, C_PORT_RESET);
+                    break;
+                default:
+                    DPRINT("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value);
+                    break;
+           }
+
+            Status = STATUS_SUCCESS;
+            break;
+        }
+        case USB_REQUEST_SET_FEATURE:
+        {
+            //
+            // request set feature
+            //
+            switch(Urb->UrbControlVendorClassRequest.Value)
+            {
+                case PORT_ENABLE:
+                {
+                    //
+                    // port enable is a no-op for EHCI
+                    //
+                    Status = STATUS_SUCCESS;
+                    break;
+                }
+
+                case PORT_SUSPEND:
+                {
+                    //
+                    // set suspend port feature
+                    //
+                    Status = m_Hardware->SetPortFeature(PortId, PORT_SUSPEND);
+                    break;
+                }
+                case PORT_POWER:
+                {
+                    //
+                    // set power feature on port
+                    //
+                    Status = m_Hardware->SetPortFeature(PortId, PORT_POWER);
+                    break;
+                }
+
+                case PORT_RESET:
+                {
+                    //
+                    // reset port feature
+                    //
+                    Status = m_Hardware->SetPortFeature(PortId, PORT_RESET);
+                    PC_ASSERT(Status == STATUS_SUCCESS);
+                    break;
+                }
+                default:
+                    DPRINT1("Unsupported request id %x\n", Urb->UrbControlVendorClassRequest.Value);
+                    PC_ASSERT(FALSE);
+            }
+            break;
+        }
+        default:
+            DPRINT1("CHubController::HandleClassOther Unknown request code %x\n", Urb->UrbControlVendorClassRequest.Request);
+            PC_ASSERT(0);
+            Status = STATUS_INVALID_DEVICE_REQUEST;
+    }
+    return Status;
+}
+
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::HandleSelectConfiguration(
+    IN OUT PIRP Irp, 
+    PURB Urb)
+{
+    PUSBDEVICE UsbDevice;
+    PUSBD_INTERFACE_INFORMATION InterfaceInfo;
+
+    //
+    // is the request for the Root Hub
+    //
+    if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
+    {
+        //
+        // FIXME: support setting device to unconfigured state
+        //
+        PC_ASSERT(Urb->UrbSelectConfiguration.ConfigurationDescriptor);
+
+        //
+        // set device handle
+        //
+        Urb->UrbSelectConfiguration.ConfigurationHandle = (PVOID)&ROOTHUB2_CONFIGURATION_DESCRIPTOR;
+
+        //
+        // copy interface info
+        //
+        InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
+
+        InterfaceInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)&ROOTHUB2_INTERFACE_DESCRIPTOR;
+        InterfaceInfo->Class = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceClass;
+        InterfaceInfo->SubClass = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceSubClass;
+        InterfaceInfo->Protocol = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceProtocol;
+        InterfaceInfo->Reserved = 0;
+
+        //
+        // sanity check
+        //
+        PC_ASSERT(InterfaceInfo->NumberOfPipes == 1);
+
+        //
+        // copy pipe info
+        //
+        InterfaceInfo->Pipes[0].MaximumPacketSize = ROOTHUB2_ENDPOINT_DESCRIPTOR.wMaxPacketSize;
+        InterfaceInfo->Pipes[0].EndpointAddress = ROOTHUB2_ENDPOINT_DESCRIPTOR.bEndpointAddress;
+        InterfaceInfo->Pipes[0].Interval = ROOTHUB2_ENDPOINT_DESCRIPTOR.bInterval;
+        InterfaceInfo->Pipes[0].PipeType = (USBD_PIPE_TYPE)(ROOTHUB2_ENDPOINT_DESCRIPTOR.bmAttributes & USB_ENDPOINT_TYPE_MASK);
+        InterfaceInfo->Pipes[0].PipeHandle = (PVOID)&ROOTHUB2_ENDPOINT_DESCRIPTOR;
+
+        return STATUS_SUCCESS;
+    }
+    else
+    {
+        //
+        // check if this is a valid usb device handle
+        //
+        PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
+
+        //
+        // get device
+        //
+        UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
+
+        //
+        // select configuration
+        //
+        return UsbDevice->SelectConfiguration(Urb->UrbSelectConfiguration.ConfigurationDescriptor, &Urb->UrbSelectConfiguration.Interface, &Urb->UrbSelectConfiguration.ConfigurationHandle);
+    }
+}
+
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::HandleSelectInterface(
+    IN OUT PIRP Irp, 
+    PURB Urb)
+{
+    PUSBDEVICE UsbDevice;
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(Urb->UrbSelectInterface.ConfigurationHandle);
+
+    //
+    // is the request for the Root Hub
+    //
+    if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
+    {
+        //
+        // no op for root hub
+        //
+        return STATUS_SUCCESS;
+    }
+    else
+    {
+        //
+        // check if this is a valid usb device handle
+        //
+        PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
+
+        //
+        // get device
+        //
+        UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
+
+        //
+        // select interface
+        //
+        return UsbDevice->SelectInterface(Urb->UrbSelectInterface.ConfigurationHandle, &Urb->UrbSelectInterface.Interface);
+    }
+}
+
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::HandleGetStatusFromDevice(
+    IN OUT PIRP Irp, 
+    PURB Urb)
+{
+    PUSHORT Status;
+
+    //
+    // sanity checks
+    //
+    PC_ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
+    PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBufferLength >= sizeof(USHORT));
+    PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBuffer);
+    PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle == NULL); 
+
+    //
+    // get status buffer
+    //
+    Status = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer;
+
+    //
+    // FIXME need more flags ?
+    //
+    *Status = USB_PORT_STATUS_CONNECT;
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::HandleClassDevice(
+    IN OUT PIRP Irp,
+    IN OUT PURB Urb)
+{
+    NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
+    PUSB_HUB_DESCRIPTOR UsbHubDescriptor;
+    ULONG PortCount, Dummy2;
+    USHORT Dummy1;
+
+    DPRINT("CHubController::HandleClassDevice Request %x Class %x\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value >> 8);
+
+    //
+    // check class request type
+    //
+    switch(Urb->UrbControlVendorClassRequest.Request)
+    {
+        case USB_REQUEST_GET_DESCRIPTOR:
+        {
+            switch (Urb->UrbControlVendorClassRequest.Value >> 8)
+            {
+                case USB_DEVICE_CLASS_RESERVED: // FALL THROUGH
+                case USB_DEVICE_CLASS_HUB:
+                {
+                    //
+                    // sanity checks
+                    //
+                    PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
+                    PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength >= sizeof(USB_HUB_DESCRIPTOR));
+
+                    //
+                    // get hub descriptor
+                    //
+                    UsbHubDescriptor = (PUSB_HUB_DESCRIPTOR)Urb->UrbControlVendorClassRequest.TransferBuffer;
+
+                    //
+                    // one hub is handled
+                    //
+                    UsbHubDescriptor->bDescriptorLength = sizeof(USB_HUB_DESCRIPTOR);
+                    Urb->UrbControlVendorClassRequest.TransferBufferLength = sizeof(USB_HUB_DESCRIPTOR);
+
+                    //
+                    // type should 0x29 according to msdn
+                    //
+                    UsbHubDescriptor->bDescriptorType = 0x29;
+
+                    //
+                    // get port count
+                    //
+                    Status = m_Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &PortCount, &Dummy2);
+                    PC_ASSERT(Status == STATUS_SUCCESS);
+
+                    //
+                    // FIXME: retrieve values
+                    //
+                    UsbHubDescriptor->bNumberOfPorts = (UCHAR)PortCount;
+                    UsbHubDescriptor->wHubCharacteristics = 0x00;
+                    UsbHubDescriptor->bPowerOnToPowerGood = 0x01;
+                    UsbHubDescriptor->bHubControlCurrent = 0x00;
+
+                    //
+                    // done
+                    //
+                    Status = STATUS_SUCCESS;
+                    break;
+               }
+               default:
+                   DPRINT1("CHubController::HandleClassDevice Class %x not implemented\n", Urb->UrbControlVendorClassRequest.Value >> 8);
+                   break;
+            }
+            break;
+        }
+        default:
+            DPRINT1("CHubController::HandleClassDevice Type %x not implemented\n", Urb->UrbControlVendorClassRequest.Request);
+    }
+
+    return Status;
+}
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::HandleGetDescriptor(
+    IN OUT PIRP Irp,
+    IN OUT PURB Urb)
+{
+    NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
+    PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
+    USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+    PUCHAR Buffer;
+    PUSBDEVICE UsbDevice;
+    ULONG Length;
+
+    DPRINT("CHubController::HandleGetDescriptor\n");
+
+    //
+    // check descriptor type
+    //
+    switch(Urb->UrbControlDescriptorRequest.DescriptorType)
+    {
+        case USB_DEVICE_DESCRIPTOR_TYPE:
+        {
+            //
+            // sanity check
+            //
+            PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR));
+            PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
+
+            if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
+            {
+                //
+                // copy root hub device descriptor
+                //
+                RtlCopyMemory((PUCHAR)Urb->UrbControlDescriptorRequest.TransferBuffer, &m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
+                Status = STATUS_SUCCESS;
+            }
+            else
+            {
+                //
+                // check if this is a valid usb device handle
+                //
+                PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
+
+                //
+                // get device
+                //
+                UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
+
+                //
+                // retrieve device descriptor from device
+                //
+                UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer);
+                Status = STATUS_SUCCESS;
+            }
+            break;
+        }
+       case USB_CONFIGURATION_DESCRIPTOR_TYPE:
+        {
+            //
+            // sanity checks
+            //
+            PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
+            PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
+
+            if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
+            {
+                //
+                // request is for the root bus controller
+                //
+                RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, &ROOTHUB2_CONFIGURATION_DESCRIPTOR, sizeof(USB_CONFIGURATION_DESCRIPTOR));
+
+                //
+                // get configuration descriptor, very retarded!
+                //
+                ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer;
+
+                //
+                // check if buffer can hold interface and endpoint descriptor
+                //
+                if (ConfigurationDescriptor->wTotalLength > Urb->UrbControlDescriptorRequest.TransferBufferLength)
+                {
+                    //
+                    // buffer too small
+                    //
+                    Status = STATUS_SUCCESS;
+                    ASSERT(FALSE);
+                    break;
+                }
+
+                //
+                // copy interface descriptor template
+                //
+                Buffer = (PUCHAR)(ConfigurationDescriptor + 1);
+                RtlCopyMemory(Buffer, &ROOTHUB2_INTERFACE_DESCRIPTOR, sizeof(USB_INTERFACE_DESCRIPTOR));
+
+                //
+                // copy end point descriptor template
+                //
+                Buffer += sizeof(USB_INTERFACE_DESCRIPTOR);
+                RtlCopyMemory(Buffer, &ROOTHUB2_ENDPOINT_DESCRIPTOR, sizeof(USB_ENDPOINT_DESCRIPTOR));
+
+                //
+                // done
+                //
+                Status = STATUS_SUCCESS;
+
+            }
+            else
+            {
+                DPRINT1("Length %u\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
+
+                //
+                // check if this is a valid usb device handle
+                //
+                PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
+
+                //
+                // get device
+                //
+                UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
+
+                if (sizeof(USB_CONFIGURATION_DESCRIPTOR) > Urb->UrbControlDescriptorRequest.TransferBufferLength)
+                {
+                    //
+                    // buffer too small
+                    //
+                    Urb->UrbControlDescriptorRequest.TransferBufferLength = UsbDevice->GetConfigurationDescriptorsLength();
+
+                    //
+                    // bail out
+                    //
+                    Status = STATUS_SUCCESS;
+                    break;
+                }
+
+                //
+                // perform work in IUSBDevice
+                //
+                UsbDevice->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer, Urb->UrbControlDescriptorRequest.TransferBufferLength, &Length);
+
+                //
+                // sanity check
+                //
+                PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >= Length);
+
+                //
+                // store result size
+                //
+                Urb->UrbControlDescriptorRequest.TransferBufferLength = Length;
+                Status = STATUS_SUCCESS;
+            }
+            break;
+        }
+        case USB_STRING_DESCRIPTOR_TYPE:
+        {
+            //
+            // sanity check
+            //
+            PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
+            PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength);
+
+
+            //
+            // check if this is a valid usb device handle
+            //
+            PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
+
+            //
+            // get device
+            //
+            UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
+
+            //
+            // generate setup packet
+            //
+            CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
+            CtrlSetup.wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
+            CtrlSetup.wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
+            CtrlSetup.wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
+            CtrlSetup.wLength = (USHORT)Urb->UrbControlDescriptorRequest.TransferBufferLength;
+            CtrlSetup.bmRequestType.B = 0x80;
+
+            //
+            // submit setup packet
+            //
+            Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
+            break;
+        }
+        default:
+            DPRINT1("CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", Urb->UrbControlDescriptorRequest.DescriptorType);
+            break;
+    }
+
+    //
+    // done
+    //
+    return Status;
+}
+
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::HandleClassInterface(
+    IN OUT PIRP Irp,
+    IN OUT PURB Urb)
+{
+    USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+    NTSTATUS Status;
+    PUSBDEVICE UsbDevice;
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
+    PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
+    PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
+
+    //
+    // check if this is a valid usb device handle
+    //
+    PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
+
+    //
+    // get device
+    //
+    UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
+
+
+    DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
+    DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
+    DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength);
+    DPRINT1("TransferBuffer %x\n", Urb->UrbControlVendorClassRequest.TransferBuffer);
+    DPRINT1("TransferBufferMDL %x\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL);
+    DPRINT1("RequestTypeReservedBits %x\n", Urb->UrbControlVendorClassRequest.RequestTypeReservedBits);
+    DPRINT1("Request %x\n", Urb->UrbControlVendorClassRequest.Request);
+    DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value);
+    DPRINT1("Index %x\n", Urb->UrbControlVendorClassRequest.Index);
+
+    //
+    // initialize setup packet
+    //
+    CtrlSetup.bmRequestType.B = 0xa1; //FIXME: Const.
+    CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
+    CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
+    CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
+    CtrlSetup.wLength = Urb->UrbControlVendorClassRequest.TransferBufferLength;
+
+    //
+    // issue request
+    //
+    Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer);
+
+    //
+    // assert on failure
+    //
+    PC_ASSERT(NT_SUCCESS(Status));
+
+
+    //
+    // done
+    //
+    return Status;
+}
+
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::HandleDeviceControl(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN OUT PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    PCOMMON_DEVICE_EXTENSION DeviceExtension;
+    PURB Urb;
+    NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
+
+    //
+    // get current stack location
+    //
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    //
+    // get device extension
+    //
+    DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    //
+    // determine which request should be performed
+    //
+    switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
+    {
+        case IOCTL_INTERNAL_USB_SUBMIT_URB:
+        {
+            //
+            // get urb
+            //
+            Urb = (PURB)IoStack->Parameters.Others.Argument1;
+            PC_ASSERT(Urb);
+
+            switch (Urb->UrbHeader.Function)
+            {
+                case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
+                    Status = HandleGetDescriptor(Irp, Urb);
+                    break;
+                case URB_FUNCTION_CLASS_DEVICE:
+                    Status = HandleClassDevice(Irp, Urb);
+                    break;
+                case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
+                    Status = HandleGetStatusFromDevice(Irp, Urb);
+                    break;
+                case URB_FUNCTION_SELECT_CONFIGURATION:
+                    Status = HandleSelectConfiguration(Irp, Urb);
+                    break;
+                case URB_FUNCTION_SELECT_INTERFACE:
+                    Status = HandleSelectInterface(Irp, Urb);
+                    break;
+                case URB_FUNCTION_CLASS_OTHER:
+                    Status = HandleClassOther(Irp, Urb);
+                    break;
+                case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
+                    Status = HandleBulkOrInterruptTransfer(Irp, Urb);
+                    break;
+                case URB_FUNCTION_CLASS_INTERFACE:
+                    Status = HandleClassInterface(Irp, Urb);
+                    break;
+                default:
+                    DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function);
+                    break;
+            }
+            //
+            // request completed
+            //
+            break;
+        }
+        case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
+        {
+            DPRINT("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", this);
+
+            if (IoStack->Parameters.Others.Argument1)
+            {
+                //
+                // store object as device handle
+                //
+                *(PVOID *)IoStack->Parameters.Others.Argument1 = (PVOID)this;
+                Status = STATUS_SUCCESS;
+            }
+            else
+            {
+                //
+                // mis-behaving hub driver
+                //
+                Status = STATUS_INVALID_DEVICE_REQUEST;
+            }
+
+            //
+            // request completed
+            //
+            break;
+        }
+        case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
+        {
+            DPRINT("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
+
+            //
+            // this is the first request send, it delivers the PDO to the caller
+            //
+            if (IoStack->Parameters.Others.Argument1)
+            {
+                //
+                // store root hub pdo object
+                //
+                *(PVOID *)IoStack->Parameters.Others.Argument1 = DeviceObject;
+            }
+
+            if (IoStack->Parameters.Others.Argument2)
+            {
+                //
+                // documentation claims to deliver the hcd controller object, although it is wrong
+                //
+                *(PVOID *)IoStack->Parameters.Others.Argument2 = DeviceObject;
+            }
+
+            //
+            // request completed
+            //
+            Status = STATUS_SUCCESS;
+            break;
+        }
+        case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
+        {
+            DPRINT("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
+
+            //
+            // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
+            // requests this ioctl to deliver the number of presents. 
+
+            if (IoStack->Parameters.Others.Argument1)
+            {
+                //
+                // FIXME / verify: there is only one hub
+                //
+                *(PULONG)IoStack->Parameters.Others.Argument1 = 1;
+            }
+
+            //
+            // request completed
+            //
+            Status = STATUS_SUCCESS;
+            Irp->IoStatus.Information = sizeof(ULONG);
+            break;
+        }
+        case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
+        {
+            DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n");
+            Status = STATUS_SUCCESS;
+            break;
+        }
+        default:
+        {
+            DPRINT1("HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n",
+                    IoStack->Parameters.DeviceIoControl.IoControlCode,
+                    IoStack->Parameters.DeviceIoControl.InputBufferLength,
+                    IoStack->Parameters.DeviceIoControl.OutputBufferLength);
+            break;
+        }
+    }
+    if (Status != STATUS_PENDING)
+    {
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    }
+
+    return Status;
+}
+
+//-----------------------------------------------------------------------------------------
+PUSBHARDWAREDEVICE
+CHubController::GetUsbHardware()
+{
+    return m_Hardware;
+}
+
+//-----------------------------------------------------------------------------------------
+ULONG
+CHubController::AcquireDeviceAddress()
+{
+    KIRQL OldLevel;
+    ULONG DeviceAddress;
+
+    //
+    // acquire device lock
+    //
+    KeAcquireSpinLock(&m_Lock, &OldLevel);
+
+    //
+    // find address
+    //
+    DeviceAddress = RtlFindClearBits(&m_DeviceAddressBitmap, 1, 0);
+    if (DeviceAddress != MAXULONG)
+    {
+        //
+        // reserve address
+        //
+        RtlSetBits(&m_DeviceAddressBitmap, DeviceAddress, 1);
+
+        //
+        // device addresses start from 0x1 - 0xFF
+        //
+        DeviceAddress++;
+    }
+
+    //
+    // release spin lock
+    //
+    KeReleaseSpinLock(&m_Lock, OldLevel);
+
+    //
+    // return device address
+    //
+    return DeviceAddress;
+}
+//-----------------------------------------------------------------------------------------
+VOID
+CHubController::ReleaseDeviceAddress(
+    ULONG DeviceAddress)
+{
+    KIRQL OldLevel;
+
+    //
+    // acquire device lock
+    //
+    KeAcquireSpinLock(&m_Lock, &OldLevel);
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(DeviceAddress != 0);
+
+    //
+    // convert back to bit number
+    //
+    DeviceAddress--;
+
+    //
+    // clear bit
+    //
+    RtlClearBits(&m_DeviceAddressBitmap, DeviceAddress, 1);
+
+    //
+    // release lock
+    //
+    KeReleaseSpinLock(&m_Lock, OldLevel);
+}
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::RemoveUsbDevice(
+    PUSBDEVICE UsbDevice)
+{
+    PUSBDEVICE_ENTRY DeviceEntry;
+    PLIST_ENTRY Entry;
+    NTSTATUS Status = STATUS_UNSUCCESSFUL;
+    KIRQL OldLevel;
+
+    //
+    // acquire lock
+    //
+    KeAcquireSpinLock(&m_Lock, &OldLevel);
+
+    //
+    // point to first entry
+    //
+    Entry = m_UsbDeviceList.Flink;
+
+    //
+    // find matching entry
+    //
+    while(Entry != &m_UsbDeviceList)
+    {
+        //
+        // get entry
+        //
+        DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
+
+        //
+        // is it current entry
+        //
+        if (DeviceEntry->Device == UsbDevice)
+        {
+            //
+            // remove entry
+            //
+            RemoveEntryList(Entry);
+
+            //
+            // free entry
+            //
+            ExFreePoolWithTag(DeviceEntry, TAG_USBEHCI);
+
+            //
+            // done
+            //
+            Status = STATUS_SUCCESS;
+            break;
+        }
+
+        //
+        // goto next device
+        //
+        Entry = Entry->Flink;
+    }
+
+    //
+    // release lock
+    //
+    KeReleaseSpinLock(&m_Lock, OldLevel);
+
+    //
+    // return result
+    //
+    return Status;
+}
+//-----------------------------------------------------------------------------------------
+BOOLEAN
+CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice)
+{
+    PUSBDEVICE_ENTRY DeviceEntry;
+    PLIST_ENTRY Entry;
+    KIRQL OldLevel;
+    BOOLEAN Result = FALSE;
+
+    //
+    // acquire lock
+    //
+    KeAcquireSpinLock(&m_Lock, &OldLevel);
+
+    //
+    // point to first entry
+    //
+    Entry = m_UsbDeviceList.Flink;
+
+    //
+    // find matching entry
+    //
+    while(Entry != &m_UsbDeviceList)
+    {
+        //
+        // get entry
+        //
+        DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
+
+        //
+        // is it current entry
+        //
+        if (DeviceEntry->Device == UsbDevice)
+        {
+            //
+            // device is valid
+            //
+            Result = TRUE;
+            break;
+        }
+
+        //
+        // goto next device
+        //
+        Entry = Entry->Flink;
+    }
+
+    //
+    // release lock
+    //
+    KeReleaseSpinLock(&m_Lock, OldLevel);
+
+    //
+    // return result
+    //
+    return Result;
+
+}
+
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::AddUsbDevice(
+    PUSBDEVICE UsbDevice)
+{
+    PUSBDEVICE_ENTRY DeviceEntry;
+    KIRQL OldLevel;
+
+    //
+    // allocate device entry
+    //
+    DeviceEntry = (PUSBDEVICE_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(USBDEVICE_ENTRY), TAG_USBEHCI);
+    if (!DeviceEntry)
+    {
+        //
+        // no memory
+        //
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // initialize entry
+    //
+    DeviceEntry->Device = UsbDevice;
+
+    //
+    // acquire lock
+    //
+    KeAcquireSpinLock(&m_Lock, &OldLevel);
+
+    //
+    // insert entry
+    //
+    InsertTailList(&m_UsbDeviceList, &DeviceEntry->Entry);
+
+    //
+    // release spin lock
+    //
+    KeReleaseSpinLock(&m_Lock, OldLevel);
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
+//-----------------------------------------------------------------------------------------
+VOID
+CHubController::SetNotification(
+    PVOID CallbackContext,
+    PRH_INIT_CALLBACK CallbackRoutine)
+{
+    KIRQL OldLevel;
+
+    //
+    // acquire hub controller lock
+    //
+    KeAcquireSpinLock(&m_Lock, &OldLevel);
+
+    //
+    // now set the callback routine and context of the hub
+    //
+    m_HubCallbackContext = CallbackContext;
+    m_HubCallbackRoutine = CallbackRoutine;
+
+   //
+   // release hub controller lock
+   //
+   KeReleaseSpinLock(&m_Lock, OldLevel);
+}
+
+//=================================================================================================
+//
+// Generic Interface functions
+//
+VOID
+USB_BUSIFFN
+USBI_InterfaceReference(
+    PVOID BusContext)
+{
+    CHubController * Controller = (CHubController*)BusContext;
+
+    DPRINT1("USBH_InterfaceReference\n");
+
+    //
+    // add reference
+    //
+    Controller->AddRef();
+}
+
+VOID
+USB_BUSIFFN
+USBI_InterfaceDereference(
+    PVOID BusContext)
+{
+    CHubController * Controller = (CHubController*)BusContext;
+
+    DPRINT1("USBH_InterfaceDereference\n");
+
+    //
+    // release
+    //
+    Controller->Release();
+}
+//=================================================================================================
+//
+// USB Hub Interface functions
+//
+NTSTATUS
+USB_BUSIFFN
+USBHI_CreateUsbDevice(
+    PVOID BusContext,
+    PUSB_DEVICE_HANDLE *NewDevice,
+    PUSB_DEVICE_HANDLE HubDeviceHandle,
+    USHORT PortStatus,
+    USHORT PortNumber)
+{
+    PUSBDEVICE NewUsbDevice;
+    CHubController * Controller;
+    NTSTATUS Status;
+
+    DPRINT1("USBHI_CreateUsbDevice\n");
+
+    //
+    // first get hub controller
+    //
+    Controller = (CHubController *)BusContext;
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(Controller);
+    PC_ASSERT(BusContext == HubDeviceHandle);
+
+    //
+    // now allocate usb device
+    //
+    Status = CreateUSBDevice(&NewUsbDevice);
+
+    //
+    // check for success
+    //
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // release controller
+        //
+        Controller->Release();
+        DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status);
+        return Status;
+    }
+
+    //
+    // now initialize device
+    //
+    Status = NewUsbDevice->Initialize(PHUBCONTROLLER(Controller), Controller->GetUsbHardware(),PVOID(Controller), PortNumber, PortStatus);
+
+    //
+    // check for success
+    //
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // release usb device
+        //
+        NewUsbDevice->Release();
+        DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status);
+        return Status;
+    }
+
+    //
+    // insert into list
+    //
+    Status = Controller->AddUsbDevice(NewUsbDevice);
+    //
+    // check for success
+    //
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // release usb device
+        //
+        NewUsbDevice->Release();
+
+        DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status);
+        return Status;
+    }
+
+    //
+    // store the handle
+    //
+    *NewDevice = NewUsbDevice;
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_InitializeUsbDevice(
+    PVOID BusContext,
+    PUSB_DEVICE_HANDLE DeviceHandle)
+{
+    PUSBDEVICE UsbDevice;
+    CHubController * Controller;
+    ULONG DeviceAddress;
+    NTSTATUS Status;
+    ULONG Index = 0;
+
+    DPRINT1("USBHI_InitializeUsbDevice\n");
+
+    //
+    // first get controller
+    //
+    Controller = (CHubController *)BusContext;
+    PC_ASSERT(Controller);
+
+    //
+    // get device object
+    //
+    UsbDevice = (PUSBDEVICE)DeviceHandle;
+    PC_ASSERT(UsbDevice);
+
+    //
+    // validate device handle
+    //
+    if (!Controller->ValidateUsbDevice(UsbDevice))
+    {
+        DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle);
+
+        //
+        // invalid device handle
+        //
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
+
+    //
+    // now reserve an address
+    //
+    DeviceAddress = Controller->AcquireDeviceAddress();
+
+    //
+    // is the device address valid
+    //
+    if (DeviceAddress == MAXULONG)
+    {
+        //
+        // failed to get an device address from the device address pool
+        //
+        DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
+        return STATUS_DEVICE_DATA_ERROR;
+    }
+
+    do
+    {
+        //
+        // now set the device address
+        //
+        Status = UsbDevice->SetDeviceAddress((UCHAR)DeviceAddress);
+
+        if (NT_SUCCESS(Status))
+            break;
+
+    }while(Index++ < 3    );
+
+    //
+    // check for failure
+    //
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to set device address
+        //
+        DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status);
+
+        //
+        // release address
+        //
+        Controller->ReleaseDeviceAddress(DeviceAddress);
+
+        //
+        // return error
+        //
+        return STATUS_DEVICE_DATA_ERROR;
+    }
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_GetUsbDescriptors(
+    PVOID BusContext,
+    PUSB_DEVICE_HANDLE DeviceHandle,
+    PUCHAR DeviceDescriptorBuffer,
+    PULONG DeviceDescriptorBufferLength,
+    PUCHAR ConfigDescriptorBuffer,
+    PULONG ConfigDescriptorBufferLength)
+{
+    PUSBDEVICE UsbDevice;
+    CHubController * Controller;
+
+    DPRINT1("USBHI_GetUsbDescriptors\n");
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(DeviceDescriptorBuffer);
+    PC_ASSERT(DeviceDescriptorBufferLength);
+    PC_ASSERT(*DeviceDescriptorBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR));
+    PC_ASSERT(ConfigDescriptorBufferLength);
+    PC_ASSERT(*ConfigDescriptorBufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
+
+    //
+    // first get controller
+    //
+    Controller = (CHubController *)BusContext;
+    PC_ASSERT(Controller);
+
+
+    //
+    // get device object
+    //
+    UsbDevice = (PUSBDEVICE)DeviceHandle;
+    PC_ASSERT(UsbDevice);
+
+    //
+    // validate device handle
+    //
+    if (!Controller->ValidateUsbDevice(UsbDevice))
+    {
+        DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle);
+
+        //
+        // invalid device handle
+        //
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
+
+    //
+    // get device descriptor
+    //
+    UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)DeviceDescriptorBuffer);
+
+    //
+    // store result length
+    //
+    *DeviceDescriptorBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
+
+    //
+    // get configuration descriptor
+    //
+    UsbDevice->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR)ConfigDescriptorBuffer, *ConfigDescriptorBufferLength, ConfigDescriptorBufferLength);
+
+    //
+    // complete the request
+    //
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_RemoveUsbDevice(
+    PVOID BusContext,
+    PUSB_DEVICE_HANDLE DeviceHandle,
+    ULONG Flags)
+{
+    PUSBDEVICE UsbDevice;
+    CHubController * Controller;
+    NTSTATUS Status;
+
+    DPRINT1("USBHI_RemoveUsbDevice\n");
+
+    //
+    // first get controller
+    //
+    Controller = (CHubController *)BusContext;
+    PC_ASSERT(Controller);
+
+    //
+    // get device object
+    //
+    UsbDevice = (PUSBDEVICE)DeviceHandle;
+    PC_ASSERT(UsbDevice);
+
+    //
+    // validate device handle
+    //
+    if (!Controller->ValidateUsbDevice(UsbDevice))
+    {
+        DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle);
+
+        //
+        // invalid device handle
+        //
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
+
+    //
+    // check if there were flags passed
+    //
+    if (Flags & USBD_KEEP_DEVICE_DATA || Flags  & USBD_MARK_DEVICE_BUSY)
+    {
+        //
+        // ignore flags for now
+        //
+        return STATUS_SUCCESS;
+    }
+
+    //
+    // remove device
+    //
+    Status = Controller->RemoveUsbDevice(UsbDevice);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // invalid device handle
+        //
+        DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice);
+        PC_ASSERT(0);
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
+
+    //
+    // release usb device
+    //
+    UsbDevice->Release();
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_RestoreUsbDevice(
+    PVOID BusContext,
+    PUSB_DEVICE_HANDLE OldDeviceHandle,
+    PUSB_DEVICE_HANDLE NewDeviceHandle)
+{
+    PUSBDEVICE OldUsbDevice, NewUsbDevice;
+    CHubController * Controller;
+
+    DPRINT1("USBHI_RestoreUsbDevice\n");
+
+    //
+    // first get controller
+    //
+    Controller = (CHubController *)BusContext;
+    PC_ASSERT(Controller);
+
+    //
+    // get device object
+    //
+    OldUsbDevice = (PUSBDEVICE)OldDeviceHandle;
+    NewUsbDevice = (PUSBDEVICE)NewDeviceHandle;
+    PC_ASSERT(OldUsbDevice);
+    PC_ASSERT(NewDeviceHandle);
+
+    //
+    // validate device handle
+    //
+    PC_ASSERT(Controller->ValidateUsbDevice(NewUsbDevice));
+    PC_ASSERT(Controller->ValidateUsbDevice(OldUsbDevice));
+
+    DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice->GetDeviceAddress());
+
+
+    DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice->GetDeviceAddress());
+
+    PC_ASSERT(FALSE);
+
+    //
+    // remove old device handle
+    //
+    USBHI_RemoveUsbDevice(BusContext, OldDeviceHandle, 0);
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_QueryDeviceInformation(
+    PVOID BusContext,
+    PUSB_DEVICE_HANDLE DeviceHandle,
+    PVOID DeviceInformationBuffer,
+    ULONG DeviceInformationBufferLength,
+    PULONG LengthReturned)
+{
+    PUSB_DEVICE_INFORMATION_0 DeviceInfo;
+    PUSBDEVICE UsbDevice;
+    CHubController * Controller;
+
+    DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext);
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(DeviceInformationBufferLength >= sizeof(USB_DEVICE_INFORMATION_0));
+    PC_ASSERT(DeviceInformationBuffer);
+    PC_ASSERT(LengthReturned);
+
+    //
+    // get controller object
+    //
+    Controller = (CHubController*)BusContext;
+    PC_ASSERT(Controller);
+
+    //
+    // get device object
+    //
+    UsbDevice = (PUSBDEVICE)DeviceHandle;
+    PC_ASSERT(UsbDevice);
+
+    if (BusContext != DeviceHandle)
+    {
+        //
+        // validate device handle
+        //
+        if (!Controller->ValidateUsbDevice(UsbDevice))
+        {
+            DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle);
+
+            //
+            // invalid device handle
+            //
+            return STATUS_DEVICE_NOT_CONNECTED;
+        }
+
+        //
+        // access information buffer
+        //
+        DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
+
+        //
+        // initialize with default values
+        //
+        DeviceInfo->InformationLevel = 0;
+        DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
+        DeviceInfo->PortNumber = UsbDevice->GetPort();
+        DeviceInfo->CurrentConfigurationValue = UsbDevice->GetConfigurationValue();
+        DeviceInfo->DeviceAddress = UsbDevice->GetDeviceAddress();
+        DeviceInfo->HubAddress = 0; //FIXME
+        DeviceInfo->DeviceSpeed = UsbDevice->GetSpeed();
+        DeviceInfo->DeviceType = UsbDevice->GetType();
+        DeviceInfo->NumberOfOpenPipes = 0; //FIXME
+
+        //
+        // get device descriptor
+        //
+        UsbDevice->GetDeviceDescriptor(&DeviceInfo->DeviceDescriptor);
+
+        //
+        // FIXME return pipe information
+        //
+
+        //
+        // store result length
+        //
+        *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0);
+
+        return STATUS_SUCCESS;
+    }
+
+    //
+    // access information buffer
+    //
+    DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
+
+    //
+    // initialize with default values
+    //
+    DeviceInfo->InformationLevel = 0;
+    DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
+    DeviceInfo->PortNumber = 0;
+    DeviceInfo->CurrentConfigurationValue = 0; //FIXME;
+    DeviceInfo->DeviceAddress = 0;
+    DeviceInfo->HubAddress = 0; //FIXME
+    DeviceInfo->DeviceSpeed = UsbHighSpeed; //FIXME
+    DeviceInfo->DeviceType = Usb20Device; //FIXME
+    DeviceInfo->NumberOfOpenPipes = 0; //FIXME
+
+    //
+    // get device descriptor
+    //
+    RtlMoveMemory(&DeviceInfo->DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(USB_DEVICE_DESCRIPTOR));
+
+    //
+    // FIXME return pipe information
+    //
+
+    //
+    // store result length
+    //
+#ifdef _MSC_VER
+    *LengthReturned = FIELD_OFFSET(USB_DEVICE_INFORMATION_0, PipeList[DeviceInfo->NumberOfOpenPipes]);
+#else
+    *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0) + (DeviceInfo->NumberOfOpenPipes > 1 ? (DeviceInfo->NumberOfOpenPipes - 1) * sizeof(USB_PIPE_INFORMATION_0) : 0);
+#endif
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_GetControllerInformation(
+    PVOID BusContext,
+    PVOID ControllerInformationBuffer,
+    ULONG ControllerInformationBufferLength,
+    PULONG LengthReturned)
+{
+    PUSB_CONTROLLER_INFORMATION_0 ControllerInfo;
+
+    DPRINT1("USBHI_GetControllerInformation\n");
+
+    //
+    // sanity checks
+    //
+    PC_ASSERT(ControllerInformationBuffer);
+    PC_ASSERT(ControllerInformationBufferLength >= sizeof(USB_CONTROLLER_INFORMATION_0));
+
+    //
+    // get controller info buffer
+    //
+    ControllerInfo = (PUSB_CONTROLLER_INFORMATION_0)ControllerInformationBuffer;
+
+    //
+    // FIXME only version 0 is supported for now
+    //
+    PC_ASSERT(ControllerInfo->InformationLevel == 0);
+
+    //
+    // fill in information
+    //
+    ControllerInfo->ActualLength = sizeof(USB_CONTROLLER_INFORMATION_0);
+    ControllerInfo->SelectiveSuspendEnabled = FALSE; //FIXME
+    ControllerInfo->IsHighSpeedController = TRUE;
+
+    //
+    // set length returned
+    //
+    *LengthReturned = ControllerInfo->ActualLength;
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_ControllerSelectiveSuspend(
+    PVOID BusContext,
+    BOOLEAN Enable)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_GetExtendedHubInformation(
+    PVOID BusContext,
+    PDEVICE_OBJECT HubPhysicalDeviceObject,
+    PVOID HubInformationBuffer,
+    ULONG HubInformationBufferLength,
+    PULONG LengthReturned)
+{
+    PUSB_EXTHUB_INFORMATION_0 HubInfo;
+    CHubController * Controller;
+    PUSBHARDWAREDEVICE Hardware;
+    ULONG Index;
+    ULONG NumPort, Dummy2;
+    USHORT Dummy1;
+    NTSTATUS Status;
+
+    DPRINT1("USBHI_GetExtendedHubInformation\n");
+
+    //
+    // sanity checks
+    // 
+    PC_ASSERT(HubInformationBuffer);
+    PC_ASSERT(HubInformationBufferLength == sizeof(USB_EXTHUB_INFORMATION_0));
+    PC_ASSERT(LengthReturned);
+
+    //
+    // get hub controller
+    //
+    Controller = (CHubController *)BusContext;
+    PC_ASSERT(Controller);
+
+    //
+    // get usb hardware device
+    //
+    Hardware = Controller->GetUsbHardware();
+
+    //
+    // retrieve number of ports
+    //
+    Status = Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &NumPort, &Dummy2);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to get hardware details, ouch ;)
+        //
+        DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status);
+        return Status;
+    }
+
+    //
+    // get hub information buffer
+    //
+    HubInfo = (PUSB_EXTHUB_INFORMATION_0)HubInformationBuffer;
+
+    //
+    // initialize hub information
+    //
+    HubInfo->InformationLevel = 0;
+
+    //
+    // store port count
+    //
+    HubInfo->NumberOfPorts = NumPort;
+
+    //
+    // initialize port information
+    //
+    for(Index = 0; Index < NumPort; Index++)
+    {
+        HubInfo->Port[Index].PhysicalPortNumber = Index + 1;
+        HubInfo->Port[Index].PortLabelNumber = Index + 1;
+        HubInfo->Port[Index].VidOverride = 0;
+        HubInfo->Port[Index].PidOverride = 0;
+        HubInfo->Port[Index].PortAttributes = USB_PORTATTR_SHARED_USB2; //FIXME
+    }
+
+    //
+    // store result length
+    //
+#ifdef _MSC_VER
+    *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port[HubInfo->NumberOfPorts]);
+#else
+    *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port) + sizeof(USB_EXTPORT_INFORMATION_0) * HubInfo->NumberOfPorts;
+#endif
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_GetRootHubSymbolicName(
+    PVOID BusContext,
+    PVOID HubSymNameBuffer,
+    ULONG HubSymNameBufferLength,
+    PULONG HubSymNameActualLength)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+PVOID
+USB_BUSIFFN
+USBHI_GetDeviceBusContext(
+    PVOID HubBusContext,
+    PVOID DeviceHandle)
+{
+    UNIMPLEMENTED
+    return NULL;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_Initialize20Hub(
+    PVOID BusContext,
+    PUSB_DEVICE_HANDLE HubDeviceHandle,
+    ULONG TtCount)
+{
+    DPRINT("USBHI_Initialize20Hub HubDeviceHandle %p UNIMPLEMENTED TtCount %lu\n", HubDeviceHandle, TtCount);
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_RootHubInitNotification(
+    PVOID BusContext,
+    PVOID CallbackContext,
+    PRH_INIT_CALLBACK CallbackRoutine)
+{
+    CHubController * Controller;
+
+    DPRINT("USBHI_RootHubInitNotification %p \n", CallbackContext);
+
+    //
+    // get controller object
+    //
+    Controller = (CHubController*)BusContext;
+    PC_ASSERT(Controller);
+
+    //
+    // set notification routine
+    //
+    Controller->SetNotification(CallbackContext, CallbackRoutine);
+
+    //
+    // FIXME: determine when to perform callback
+    //
+    CallbackRoutine(CallbackContext);
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
+VOID
+USB_BUSIFFN
+USBHI_FlushTransfers(
+    PVOID BusContext,
+    PVOID DeviceHandle)
+{
+    UNIMPLEMENTED
+}
+
+VOID
+USB_BUSIFFN
+USBHI_SetDeviceHandleData(
+    PVOID BusContext,
+    PVOID DeviceHandle,
+    PDEVICE_OBJECT UsbDevicePdo)
+{
+    PUSBDEVICE UsbDevice;
+    CHubController * Controller;
+
+    //
+    // get controller
+    //
+    Controller = (CHubController *)BusContext;
+    PC_ASSERT(Controller);
+
+    //
+    // get device handle
+    //
+    UsbDevice = (PUSBDEVICE)DeviceHandle;
+
+    //
+    // validate device handle
+    //
+    if (!Controller->ValidateUsbDevice(UsbDevice))
+    {
+        DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle);
+
+        //
+        // invalid handle
+        //
+        return;
+    }
+    else
+    {
+        //
+        // usbhub sends this request as a part of the Pnp startup sequence
+        // looks like we need apply a dragon voodoo to fixup the device stack
+        // otherwise usbhub will cause a bugcheck
+        //
+        DPRINT1("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo);
+
+        //
+        // sanity check
+        //
+        PC_ASSERT(UsbDevicePdo->AttachedDevice);
+
+        //
+        // should be usbstor
+        // fixup device stack voodoo part #2
+        //
+        UsbDevicePdo->AttachedDevice->StackSize++;
+
+        //
+        // set device handle data
+        //
+        UsbDevice->SetDeviceHandleData(UsbDevicePdo);
+    }
+}
+
+//=================================================================================================
+//
+// USB Device Interface functions
+//
+
+VOID
+USB_BUSIFFN
+USBDI_GetUSBDIVersion(
+    PVOID BusContext,
+    PUSBD_VERSION_INFORMATION VersionInformation,
+    PULONG HcdCapabilites)
+{
+    CHubController * Controller;
+    PUSBHARDWAREDEVICE Device;
+    ULONG Speed, Dummy2;
+    USHORT Dummy1;
+
+    DPRINT1("USBDI_GetUSBDIVersion\n");
+
+    //
+    // get controller
+    //
+    Controller = (CHubController*)BusContext;
+
+    //
+    // get usb hardware
+    //
+    Device = Controller->GetUsbHardware();
+    PC_ASSERT(Device);
+
+    if (VersionInformation)
+    {
+        //
+        // windows xp supported
+        //
+        VersionInformation->USBDI_Version = 0x00000500;
+
+        //
+        // get device speed
+        //
+        Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
+
+        //
+        // store speed details
+        //
+        VersionInformation->Supported_USB_Version = Speed;
+    }
+
+    //
+    // no flags supported
+    //
+    *HcdCapabilites = 0;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBDI_QueryBusTime(
+    PVOID BusContext,
+    PULONG CurrentFrame)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBDI_SubmitIsoOutUrb(
+    PVOID BusContext,
+    PURB Urb)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBDI_QueryBusInformation(
+    PVOID BusContext,
+    ULONG Level,
+    PVOID BusInformationBuffer,
+    PULONG BusInformationBufferLength,
+    PULONG BusInformationActualLength)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+BOOLEAN
+USB_BUSIFFN
+USBDI_IsDeviceHighSpeed(
+    PVOID BusContext)
+{
+    CHubController * Controller;
+    PUSBHARDWAREDEVICE Device;
+    ULONG Speed, Dummy2;
+    USHORT Dummy1;
+
+    DPRINT1("USBDI_IsDeviceHighSpeed\n");
+
+    //
+    // get controller
+    //
+    Controller = (CHubController*)BusContext;
+
+    //
+    // get usb hardware
+    //
+    Device = Controller->GetUsbHardware();
+    PC_ASSERT(Device);
+
+    //
+    // get device speed
+    //
+    Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
+
+    //
+    // USB 2.0 equals 0x200
+    //
+    return (Speed == 0x200);
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBDI_EnumLogEntry(
+    PVOID BusContext, 
+    ULONG DriverTag, 
+    ULONG EnumTag,
+    ULONG P1,
+    ULONG P2)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+CHubController::HandleQueryInterface(
+    PIO_STACK_LOCATION IoStack)
+{
+    PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub;
+    PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI;
+    UNICODE_STRING GuidBuffer;
+    NTSTATUS Status;
+
+    if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_HUB_GUID))
+    {
+        //
+        // get request parameters
+        //
+        InterfaceHub = (PUSB_BUS_INTERFACE_HUB_V5)IoStack->Parameters.QueryInterface.Interface;
+        InterfaceHub->Version = IoStack->Parameters.QueryInterface.Version;
+
+        //
+        // check version
+        //
+        if (IoStack->Parameters.QueryInterface.Version >= 6)
+        {
+            DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
+
+            //
+            // version not supported
+            //
+            return STATUS_NOT_SUPPORTED;
+        }
+
+        //
+        // Interface version 0
+        //
+        if (IoStack->Parameters.QueryInterface.Version >= 0)
+        {
+            InterfaceHub->Size = IoStack->Parameters.QueryInterface.Size;
+            InterfaceHub->BusContext = PVOID(this);
+            InterfaceHub->InterfaceReference = USBI_InterfaceReference;
+            InterfaceHub->InterfaceDereference = USBI_InterfaceDereference;
+        }
+
+        //
+        // Interface version 1
+        //
+        if (IoStack->Parameters.QueryInterface.Version >= 1)
+        {
+            InterfaceHub->CreateUsbDevice = USBHI_CreateUsbDevice;
+            InterfaceHub->InitializeUsbDevice = USBHI_InitializeUsbDevice;
+            InterfaceHub->GetUsbDescriptors = USBHI_GetUsbDescriptors;
+            InterfaceHub->RemoveUsbDevice = USBHI_RemoveUsbDevice;
+            InterfaceHub->RestoreUsbDevice = USBHI_RestoreUsbDevice;
+            InterfaceHub->QueryDeviceInformation = USBHI_QueryDeviceInformation;
+        }
+
+        //
+        // Interface version 2
+        //
+        if (IoStack->Parameters.QueryInterface.Version >= 2)
+        {
+            InterfaceHub->GetControllerInformation = USBHI_GetControllerInformation;
+            InterfaceHub->ControllerSelectiveSuspend = USBHI_ControllerSelectiveSuspend;
+            InterfaceHub->GetExtendedHubInformation = USBHI_GetExtendedHubInformation;
+            InterfaceHub->GetRootHubSymbolicName = USBHI_GetRootHubSymbolicName;
+            InterfaceHub->GetDeviceBusContext = USBHI_GetDeviceBusContext;
+            InterfaceHub->Initialize20Hub = USBHI_Initialize20Hub;
+
+        }
+
+        //
+        // Interface version 3
+        //
+        if (IoStack->Parameters.QueryInterface.Version >= 3)
+        {
+            InterfaceHub->RootHubInitNotification = USBHI_RootHubInitNotification;
+        }
+
+        //
+        // Interface version 4
+        //
+        if (IoStack->Parameters.QueryInterface.Version >= 4)
+        {
+            InterfaceHub->FlushTransfers = USBHI_FlushTransfers;
+        }
+
+        //
+        // Interface version 5
+        //
+        if (IoStack->Parameters.QueryInterface.Version >= 5)
+        {
+            InterfaceHub->SetDeviceHandleData = USBHI_SetDeviceHandleData;
+        }
+
+        //
+        // request completed
+        //
+        return STATUS_SUCCESS;
+    }
+    else if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_USBDI_GUID))
+    {
+        //
+        // get request parameters
+        //
+        InterfaceDI = (PUSB_BUS_INTERFACE_USBDI_V2) IoStack->Parameters.QueryInterface.Interface;
+        InterfaceDI->Version = IoStack->Parameters.QueryInterface.Version;
+
+        //
+        // check version
+        //
+        if (IoStack->Parameters.QueryInterface.Version >= 3)
+        {
+            DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version);
+
+            //
+            // version not supported
+            //
+            return STATUS_NOT_SUPPORTED;
+        }
+
+        //
+        // interface version 0
+        //
+        if (IoStack->Parameters.QueryInterface.Version >= 0)
+        {
+            InterfaceDI->Size = IoStack->Parameters.QueryInterface.Size;
+            InterfaceDI->BusContext = PVOID(this);
+            InterfaceDI->InterfaceReference = USBI_InterfaceReference;
+            InterfaceDI->InterfaceDereference = USBI_InterfaceDereference;
+            InterfaceDI->GetUSBDIVersion = USBDI_GetUSBDIVersion;
+            InterfaceDI->QueryBusTime = USBDI_QueryBusTime;
+            InterfaceDI->SubmitIsoOutUrb = USBDI_SubmitIsoOutUrb;
+            InterfaceDI->QueryBusInformation = USBDI_QueryBusInformation;
+        }
+
+        //
+        // interface version 1
+        //
+        if (IoStack->Parameters.QueryInterface.Version >= 1)
+        {
+            InterfaceDI->IsDeviceHighSpeed = USBDI_IsDeviceHighSpeed;
+        }
+
+        //
+        // interface version 2
+        //
+        if (IoStack->Parameters.QueryInterface.Version >= 2)
+        {
+            InterfaceDI->EnumLogEntry = USBDI_EnumLogEntry;
+        }
+
+        //
+        // request completed
+        //
+        return STATUS_SUCCESS;
+    }
+    else
+    {
+        //
+        // convert guid to string
+        //
+        Status = RtlStringFromGUID(*IoStack->Parameters.QueryInterface.InterfaceType, &GuidBuffer);
+        if (NT_SUCCESS(Status))
+        {
+            //
+            // print interface
+            //
+            DPRINT1("HandleQueryInterface UNKNOWN INTERFACE 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;
+        }
+    }
+
+    DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName);
+
+    //
+    // fixup device stack voodoo part #1
+    //
+    (*OutDeviceObject)->StackSize++;
+
+    /* 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;
+}
+
+VOID StatusChangeEndpointCallBack(PVOID Context)
+{
+    CHubController* This;
+    PIRP Irp;
+    This = (CHubController*)Context;
+
+    ASSERT(This);
+
+    Irp = This->m_PendingSCEIrp;
+    if (!Irp)
+    {
+        DPRINT1("There was no pending IRP for SCE. Did the usb hub 2.0 driver (usbhub2) load?\n");
+        return;
+    }
+
+    This->m_PendingSCEIrp = NULL;
+    This->QueryStatusChageEndpoint(Irp);
+
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+    Irp->IoStatus.Information = 0;
+
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+}
diff --git a/drivers/usb/usbehci_new/interfaces.h b/drivers/usb/usbehci_new/interfaces.h
new file mode 100644 (file)
index 0000000..295f11e
--- /dev/null
@@ -0,0 +1,839 @@
+
+#ifndef INTERFACES_HPP
+#define INTERFACES_HPP
+
+//---------------------------------------------------------------------------
+//
+//          Object Hierachy
+//       --------------------------------------------------------------------
+//       |  IRootHCDController                                              |
+//       |    IHCDController Intel USB Universal Host Controller - 3A37     |
+//       |    IHCDController - Intel USB Universal HostController - 3A38    |
+//       |    IHCDController - Intel USB Universal HostController - 3A38    |
+//       |------------------------------------------------------------------|
+//
+//      
+//       IHCDController Intel USB Universal Host Controller - 3A37
+//         IHubController
+//         IUSBHardwareDevice
+//           IDMAMemoryManager
+//           IUSBQueue  <-      interacts with -> IUSBRequest
+//            
+//
+//  Each IHCDController creates an IUSBHardwareDevice class upon initialization. The 
+//  IUSBHardwardeDevice class is used to abstract usb controller specifics. The IHubController
+//  manages all attached devices and handles hub control ioctl requests.
+//
+//  Each IUSBHardwareDevice has one IDMAMemoryManager and one IUSBQueue. The IDMAMemoryManager
+//  is used to handle dma memory allocations. The IUSBQueue manages requests which are send to the
+//  usb hardware. See IUSBRequest class for details.
+//
+
+
+//=========================================================================================
+//
+// class IRootHCDController
+//
+// Description: This class serves as the root host controller. The host controller mantains
+// a list of registered controllers and provides support functions for the host controllers
+
+struct IHCDController;
+
+DECLARE_INTERFACE_(IRootHCDController, IUnknown)
+{
+    DEFINE_ABSTRACT_UNKNOWN()
+
+//-----------------------------------------------------------------------------------------
+//
+// Initialize
+//
+// Description: This function initializes the root host controller. It allocates the resources
+// required to manage the registered controllers
+
+    virtual NTSTATUS Initialize() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// RegisterHCD
+//
+// Description: this function registers a host controller with the root host controller
+
+    virtual NTSTATUS RegisterHCD(struct IHCDController * Controller) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// UnregisterHCD
+//
+// Description: this function unregistes a host controller
+
+    virtual NTSTATUS UnregisterHCD(struct IHCDController * Controller) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetControllerCount
+//
+// Description: returns the number of host controllers registered
+
+    virtual ULONG GetControllerCount() = 0;
+
+};
+
+typedef IRootHCDController *PROOTHDCCONTROLLER;
+
+//=========================================================================================
+//
+// class IHCDController
+//
+// Description: This class is used to manage a single USB host controller
+//
+
+DECLARE_INTERFACE_(IHCDController, IUnknown)
+{
+    DEFINE_ABSTRACT_UNKNOWN()
+
+//-----------------------------------------------------------------------------------------
+//
+// Initialize
+//
+// Description: This function initializes the IHCDController implementation. 
+// It creates an IUSBHardwareDevice object and initializes it. It also registeres itself with
+// the IRootHCDController
+//
+    virtual NTSTATUS Initialize(IN PROOTHDCCONTROLLER RootHCDController,
+                                IN PDRIVER_OBJECT DriverObject,
+                                IN PDEVICE_OBJECT PhysicalDeviceObject) = 0;
+
+};
+
+typedef IHCDController *PHCDCONTROLLER;
+
+
+//=========================================================================================
+//
+// class IUSBHardwareDevice
+//
+// Description: This class provides access to the usb hardware controller
+//
+
+struct IDMAMemoryManager;
+struct IUSBQueue;
+
+DECLARE_INTERFACE_(IUSBHardwareDevice, IUnknown)
+{
+    DEFINE_ABSTRACT_UNKNOWN()
+
+//-----------------------------------------------------------------------------------------
+//
+// Initialize
+//
+// Description: Initializes the usb device controller
+
+    virtual NTSTATUS Initialize(PDRIVER_OBJECT DriverObject,
+                                PDEVICE_OBJECT FunctionalDeviceObject,
+                                PDEVICE_OBJECT PhysicalDeviceObject,
+                                PDEVICE_OBJECT LowerDeviceObject) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// PnpStart
+//
+// Description: handles pnp start request from device. It registeres the interrupt, 
+// sets up the ports and prepares the device. It then starts the controller
+
+   virtual NTSTATUS PnpStart(PCM_RESOURCE_LIST RawResources,
+                             PCM_RESOURCE_LIST TranslatedResources) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// PnpStop
+//
+// Description: handles pnp stop request from device. It unregisteres the interrupt, releases ports and dma object.
+
+    virtual NTSTATUS PnpStop(void) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetDeviceDetails
+//
+// Description: returns the device details such as vendor id, device id, number of ports and speed
+
+    virtual NTSTATUS GetDeviceDetails(OUT OPTIONAL PUSHORT VendorId,
+                                      OUT OPTIONAL PUSHORT DeviceId,
+                                      OUT OPTIONAL PULONG NumberOfPorts,
+                                      OUT OPTIONAL PULONG Speed) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetUSBQueue
+//
+// Description: returns interface to internal IUSBQueue
+// Interface is reference counted, you need to call release method when you are done with it
+// 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;
+
+
+//-----------------------------------------------------------------------------------------
+//
+// ResetController()
+//
+// Description: this function resets the controller
+// Returns STATUS_SUCCESS when the controller was successfully reset
+
+   virtual NTSTATUS ResetController() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// StartController
+//
+// Description: this functions starts controller allowing interrupts for device connects/removal, and execution of
+// Periodic and Asynchronous Schedules. 
+//
+
+    virtual NTSTATUS StartController() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// StopController
+//
+// Description: this functions stops controller disabling interrupts for device connects/removal, and execution of
+// Periodic and Asynchronous Schedules. 
+//
+
+    virtual NTSTATUS StopController() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// ResetPort
+//
+// Description: this functions resets the port on the controller
+//
+
+    virtual NTSTATUS ResetPort(ULONG PortNumber) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetPortStatus
+//
+// Description: this functions return status and change state of port
+//
+    virtual NTSTATUS GetPortStatus(ULONG PortId, OUT USHORT *PortStatus, OUT USHORT *PortChange) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// ClearPortStatus
+//
+// Description: Clears Status of Port, for example Connection, Enable and Reset
+//
+    virtual NTSTATUS ClearPortStatus(ULONG PortId, ULONG Status) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// SetPortFeature
+//
+// Description: this functions Sets Feature on Port, for example Enable, Power and Reset
+//
+    virtual NTSTATUS SetPortFeature(ULONG PortId, ULONG Feature) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// SetAsyncListRegister
+//
+// Description: this functions sets the register to a address that is the physical address of a QueueHead.
+// This is the location at which the controller will start executing the Asynchronous Schedule.
+//
+// FIXME: This is only available for USB 2.0
+    virtual VOID SetAsyncListRegister(ULONG PhysicalAddress) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// SetPeriodicListRegister
+//
+// Description: this functions sets the register to a address that is the physical address of a ???.
+// This is the location at which the controller will start executing the Periodic Schedule.
+//
+    virtual VOID SetPeriodicListRegister(ULONG PhysicalAddress) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetAsyncListRegister
+//
+// Description: Returns the memory address used in the Asynchronous Register
+//
+    virtual struct _QUEUE_HEAD * GetAsyncListQueueHead() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetPeriodicListRegister
+//
+// Description: Returns the the memory address used in the Periodic Register
+//
+    virtual ULONG GetPeriodicListRegister() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// SetStatusChangeEndpointCallBack
+//
+// Description: Used to callback to the hub controller when SCE detected
+//
+    virtual VOID SetStatusChangeEndpointCallBack(PVOID CallBack,PVOID Context) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// AcquireDeviceLock
+//
+// Description: acquires the device lock
+
+    virtual KIRQL AcquireDeviceLock(void) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// ReleaseLock
+//
+// Description: releases the device lock
+
+    virtual void ReleaseDeviceLock(KIRQL OldLevel) = 0;
+};
+
+typedef IUSBHardwareDevice *PUSBHARDWAREDEVICE;
+
+
+//=========================================================================================
+//
+// class IDMAMemoryManager
+//
+// Description: This class provides access to the dma buffer. It provides methods to 
+// allocate and free from the dma buffer
+// 
+
+DECLARE_INTERFACE_(IDMAMemoryManager, IUnknown)
+{
+    DEFINE_ABSTRACT_UNKNOWN()
+
+//-----------------------------------------------------------------------------------------
+//
+// Initialize
+//
+// Description: initializes the memory manager
+
+    virtual NTSTATUS Initialize(IN PUSBHARDWAREDEVICE Device,
+                                IN PKSPIN_LOCK Lock,
+                                IN ULONG DmaBufferSize,
+                                IN PVOID VirtualBase,
+                                IN PHYSICAL_ADDRESS PhysicalAddress,
+                                IN ULONG DefaultBlockSize) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// Allocate
+//
+// Description: allocates block of memory from allocator
+
+    virtual NTSTATUS Allocate(IN ULONG Size,
+                              OUT PVOID *OutVirtualBase,
+                              OUT PPHYSICAL_ADDRESS OutPhysicalAddress) = 0;
+
+
+//-----------------------------------------------------------------------------------------
+//
+// Free
+//
+// Description: releases memory block
+
+    virtual NTSTATUS Release(IN PVOID VirtualBase,
+                             IN ULONG Size) = 0;
+
+};
+
+typedef IDMAMemoryManager *PDMAMEMORYMANAGER;
+
+
+//=========================================================================================
+//
+// class IUSBRequest
+//
+// Description: This class is used to issue request to usb controller. The class is 
+// initialized using InitializeXXX methods. You also need to call SetEndpoint to define the endpoint
+// In addition you can call SetCompletionDetails if you need to wait for the end of
+// the request or want to complete an irp. You call AddUSBRequest to add the request to the queue. 
+// Once the request is completed the CompletionCallback is invoked. The CompletionCallback
+// will take care of any completion details which have been set. If the request is cancelled, the 
+// CancelCallback routine is invoked.
+// 
+
+struct _QUEUE_HEAD;
+
+DECLARE_INTERFACE_(IUSBRequest, IUnknown)
+{
+    DEFINE_ABSTRACT_UNKNOWN()
+
+//-----------------------------------------------------------------------------------------
+//
+// InitializeWithSetupPacket
+//
+// Description: initializes the request packet with an setup packet
+// If there is a TransferBuffer, the TransferBufferLength contains the length of the buffer
+
+
+    virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager,
+                                               IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
+                                               IN UCHAR DeviceAddress,
+                                               IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor,
+                                               IN OUT ULONG TransferBufferLength,
+                                               IN OUT PMDL TransferBuffer) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// InitializeWithIrp
+//
+// Description: initializes the request with an IRP
+// The irp contains an URB block which contains all necessary information
+
+    virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager, 
+                                       IN OUT PIRP Irp) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// CompletionCallback
+//
+// Description: called when request has been completed. It is called when
+// IUSBQueue completes a queue head
+
+    virtual VOID CompletionCallback(IN NTSTATUS NtStatusCode,
+                                    IN ULONG UrbStatusCode,
+                                    IN struct _QUEUE_HEAD *QueueHead) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// CancelCallback
+//
+// 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 which contains all transfer descriptors
+
+    virtual NTSTATUS GetQueueHead(struct _QUEUE_HEAD ** OutHead) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+//  IsRequestComplete
+//
+// 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;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetTransferType
+//
+// Description: returns the type of the request: control, bulk, iso, interrupt
+
+    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;
+
+//----------------------------------------------------------------------------------------
+//
+// FreeQueueHead
+//
+// Description: frees the queue head with the associated transfer descriptors
+
+    virtual VOID FreeQueueHead(struct _QUEUE_HEAD * QueueHead) = 0;
+
+//---------------------------------------------------------------------------------------
+//
+// GetTransferBuffer
+//
+// Description: this function returns the transfer buffer mdl and length
+// Used by IUSBQueue for mapping buffer contents with DMA
+
+    virtual VOID GetTransferBuffer(OUT PMDL * OutMDL,
+                                   OUT PULONG TransferLength) = 0;
+
+//--------------------------------------------------------------------------------------
+//
+// IsQueueHeadComplete
+//
+// Description: returns true when the queue head which was passed as a parameter has been completed
+
+    virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead) = 0;
+};
+
+
+typedef IUSBRequest *PUSBREQUEST;
+
+//=========================================================================================
+//
+// class IUSBQueue
+//
+// Description: This class manages pending requests
+// 
+
+DECLARE_INTERFACE_(IUSBQueue, IUnknown)
+{
+    DEFINE_ABSTRACT_UNKNOWN()
+
+//-----------------------------------------------------------------------------------------
+//
+// Initialize
+//
+// Description: initializes the object
+
+    virtual NTSTATUS Initialize(IN PUSBHARDWAREDEVICE Hardware,
+                                IN PDMA_ADAPTER AdapterObject,
+                                IN PDMAMEMORYMANAGER MemManager,
+                                IN OPTIONAL PKSPIN_LOCK Lock) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetPendingRequestCount
+//
+// Description: returns the number of pending requests true from IsRequestComplete
+
+    virtual ULONG GetPendingRequestCount() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// AddUSBRequest
+//
+// Description: adds an usb request to the queue. 
+// Returns status success when successful
+
+    virtual NTSTATUS AddUSBRequest(IUSBRequest * Request) = 0;
+    virtual NTSTATUS AddUSBRequest(PURB Urb) = 0;
+//-----------------------------------------------------------------------------------------
+//
+// CancelRequests()
+//
+// Description: cancels all requests
+
+    virtual NTSTATUS CancelRequests() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// CreateUSBRequest
+//
+// Description: creates an usb request
+
+    virtual NTSTATUS CreateUSBRequest(IUSBRequest **OutRequest) = 0;
+
+//--------------------------------------------------------------------------------------
+//
+// InterruptCallback
+//
+// Description: callback when the periodic / asynchronous queue has been completed / queue head been completed
+
+    virtual VOID InterruptCallback(IN NTSTATUS Status, OUT PULONG ShouldRingDoorBell) = 0;
+
+//--------------------------------------------------------------------------------------
+//
+// CompleteAsyncRequests
+//
+// Description: once a request has been completed it is moved to pending queue. Since a queue head should only be freed
+// after a door bell ring, this needs some synchronization.
+// This function gets called by IUSBHardware after it the Interrupt on Async Advance bit has been set
+
+    virtual VOID CompleteAsyncRequests() = 0;
+};
+
+typedef IUSBQueue *PUSBQUEUE;
+
+//=========================================================================================
+//
+// class IHubController
+//
+// Description: This class implements a hub controller
+// 
+
+DECLARE_INTERFACE_(IHubController, IUnknown)
+{
+    DEFINE_ABSTRACT_UNKNOWN()
+
+//----------------------------------------------------------------------------------------
+//
+// Initialize
+//
+// Description: Initializes the hub 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;
+
+//----------------------------------------------------------------------------------------
+//
+// GetHubControllerSymbolicLink
+//
+// Description: Returns the symbolic link of the root hub
+
+    virtual NTSTATUS GetHubControllerSymbolicLink(ULONG BufferLength, PVOID Buffer, PULONG RequiredLength) = 0;
+
+
+};
+
+typedef IHubController *PHUBCONTROLLER;
+
+//=========================================================================================
+//
+// class IDispatchIrp
+//
+// Description: This class is used to handle irp dispatch requests
+// 
+
+DECLARE_INTERFACE_(IDispatchIrp, IUnknown)
+{
+    DEFINE_ABSTRACT_UNKNOWN()
+
+//-----------------------------------------------------------------------------------------
+//
+// 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 IDispatchIrp *PDISPATCHIRP;
+
+//=========================================================================================
+//
+// class IUSBDevice
+//
+// Description: This class is used to abstract details of a usb device
+// 
+
+DECLARE_INTERFACE_(IUSBDevice, IUnknown)
+{
+    DEFINE_ABSTRACT_UNKNOWN()
+
+//----------------------------------------------------------------------------------------
+//
+// Initialize
+//
+// Description: Initializes the usb device
+
+    virtual NTSTATUS Initialize(IN PHUBCONTROLLER HubController,
+                                IN PUSBHARDWAREDEVICE Device,
+                                IN PVOID Parent,
+                                IN ULONG Port,
+                                IN ULONG PortStatus) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// IsHub
+//
+// Description: returns true when device is a hub
+
+    virtual BOOLEAN IsHub() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetParent
+//
+// Description: gets the parent device of the this device
+
+    virtual NTSTATUS GetParent(PVOID * Parent) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetDeviceAddress
+//
+// Description: gets the device address of the this device
+
+    virtual UCHAR GetDeviceAddress() = 0;
+
+
+//-----------------------------------------------------------------------------------------
+//
+// GetPort
+//
+// Description: gets the port to which this device is connected
+
+    virtual ULONG GetPort() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetSpeed
+//
+// Description: gets the speed of the device
+
+    virtual USB_DEVICE_SPEED GetSpeed() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetType
+//
+// Description: gets the type of the device, either 1.1 or 2.0 device
+
+    virtual USB_DEVICE_TYPE GetType() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetState
+//
+// Description: gets the device state
+
+    virtual ULONG GetState() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// SetDeviceHandleData
+//
+// Description: sets device handle data
+
+    virtual void SetDeviceHandleData(PVOID Data) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// SetDeviceAddress
+//
+// Description: sets device handle data
+
+    virtual NTSTATUS SetDeviceAddress(UCHAR DeviceAddress) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetDeviceDescriptor
+//
+// Description: sets device handle data
+
+    virtual void GetDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetConfigurationValue
+//
+// Description: gets current selected configuration index
+
+   virtual UCHAR GetConfigurationValue() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// SubmitIrp
+//
+// Description: submits an irp containing an urb
+
+    virtual NTSTATUS SubmitIrp(PIRP Irp) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// GetConfigurationDescriptors
+//
+// Description: returns one or more configuration descriptors
+
+    virtual VOID GetConfigurationDescriptors(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer,
+                                             IN ULONG BufferLength,
+                                             OUT PULONG OutBufferLength) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// Description: returns length of configuration descriptors
+//
+     virtual ULONG GetConfigurationDescriptorsLength() = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// SubmitSetupPacket
+//
+// Description: submits an setup packet. The usb device will then create an usb request from it and submit it to the queue
+
+     virtual NTSTATUS SubmitSetupPacket(IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
+                                        IN OUT ULONG BufferLength,
+                                        OUT PVOID Buffer) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// SelectConfiguration
+//
+// Description: selects a configuration
+
+    virtual NTSTATUS SelectConfiguration(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
+                                         IN PUSBD_INTERFACE_INFORMATION Interface,
+                                         OUT USBD_CONFIGURATION_HANDLE *ConfigurationHandle) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// SelectConfiguration
+//
+// Description: selects a interface of an configuration
+
+    virtual NTSTATUS SelectInterface(IN USBD_CONFIGURATION_HANDLE ConfigurationHandle,
+                                     IN OUT PUSBD_INTERFACE_INFORMATION Interface) = 0;
+};
+
+typedef IUSBDevice *PUSBDEVICE;
+
+#endif
diff --git a/drivers/usb/usbehci_new/memory_manager.cpp b/drivers/usb/usbehci_new/memory_manager.cpp
new file mode 100644 (file)
index 0000000..1cfed3e
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * PROJECT:     ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/usb/usbehci/memory_manager.cpp
+ * PURPOSE:     USB EHCI device driver.
+ * PROGRAMMERS:
+ *              Michael Martin (michael.martin@reactos.org)
+ *              Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+#include "usbehci.h"
+
+class CDMAMemoryManager : public IDMAMemoryManager
+{
+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;
+    }
+
+    // IDMAMemoryManager interface functions
+    virtual NTSTATUS Initialize(IN PUSBHARDWAREDEVICE Device, IN PKSPIN_LOCK Lock, IN ULONG DmaBufferSize, IN PVOID VirtualBase, IN PHYSICAL_ADDRESS PhysicalAddress, IN ULONG DefaultBlockSize);
+    virtual NTSTATUS Allocate(IN ULONG Size, OUT PVOID *OutVirtualBase, OUT PPHYSICAL_ADDRESS OutPhysicalAddress);
+    virtual NTSTATUS Release(IN PVOID VirtualBase, IN ULONG Size);
+
+    // constructor / destructor
+    CDMAMemoryManager(IUnknown *OuterUnknown){}
+    virtual ~CDMAMemoryManager(){}
+
+protected:
+    LONG m_Ref;
+    PUSBHARDWAREDEVICE m_Device;
+    PKSPIN_LOCK m_Lock;
+    LONG m_DmaBufferSize;
+    PVOID m_VirtualBase;
+    PHYSICAL_ADDRESS m_PhysicalAddress;
+    ULONG m_BlockSize;
+
+    PULONG m_BitmapBuffer;
+    RTL_BITMAP m_Bitmap;
+};
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+STDMETHODCALLTYPE
+CDMAMemoryManager::QueryInterface(
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    return STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS
+CDMAMemoryManager::Initialize(
+    IN PUSBHARDWAREDEVICE Device,
+    IN PKSPIN_LOCK Lock,
+    IN ULONG DmaBufferSize,
+    IN PVOID VirtualBase,
+    IN PHYSICAL_ADDRESS PhysicalAddress,
+    IN ULONG DefaultBlockSize)
+{
+    ULONG BitmapLength;
+
+    //
+    // sanity checks
+    //
+    PC_ASSERT(DmaBufferSize >= PAGE_SIZE);
+    PC_ASSERT(DmaBufferSize % PAGE_SIZE == 0);
+    PC_ASSERT(DefaultBlockSize == 32 || DefaultBlockSize == 64 || DefaultBlockSize == 128);
+
+    //
+    // calculate bitmap length
+    //
+    BitmapLength = (DmaBufferSize / DefaultBlockSize) / 8;
+
+    //
+    // allocate bitmap buffer
+    //
+    m_BitmapBuffer = (PULONG)ExAllocatePoolWithTag(NonPagedPool, BitmapLength, TAG_USBEHCI);
+    if (!m_BitmapBuffer)
+    {
+        //
+        // no memory
+        //
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // initialize bitmap
+    //
+    RtlInitializeBitMap(&m_Bitmap, m_BitmapBuffer, BitmapLength * 8);
+
+    //
+    // clear all bits
+    //
+    RtlClearAllBits(&m_Bitmap);
+
+    //
+    // initialize rest of memory allocator
+    //
+    m_PhysicalAddress = PhysicalAddress;
+    m_VirtualBase = VirtualBase;
+    m_DmaBufferSize = DmaBufferSize;
+    m_BitmapBuffer = m_BitmapBuffer;
+    m_Lock = Lock;
+    m_BlockSize = DefaultBlockSize;
+
+    /* done */
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CDMAMemoryManager::Allocate(
+    IN ULONG Size,
+    OUT PVOID *OutVirtualAddress,
+    OUT PPHYSICAL_ADDRESS OutPhysicalAddress)
+{
+    ULONG Length, BlockCount, FreeIndex, StartPage, EndPage;
+    KIRQL OldLevel;
+    ULONG BlocksPerPage;
+
+    //
+    // sanity checks
+    //
+    ASSERT(Size <= PAGE_SIZE);
+    //ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
+
+    //
+    // align request
+    //
+    Length = (Size + m_BlockSize -1) & ~(m_BlockSize -1);
+
+    //
+    // sanity check
+    //
+    ASSERT(Length);
+
+    //
+    // convert to block count
+    //
+    BlockCount = Length / m_BlockSize;
+
+    //
+    // acquire lock
+    //
+    KeAcquireSpinLock(m_Lock, &OldLevel);
+
+    //
+    // helper variable
+    //
+    BlocksPerPage = PAGE_SIZE / m_BlockSize;
+
+    //
+    // start search
+    //
+    FreeIndex = 0;
+    do
+    {
+        //
+        // search for an free index
+        //
+        FreeIndex = RtlFindClearBits(&m_Bitmap, BlockCount, FreeIndex);
+
+        //
+        // check if there was a block found
+        //
+        if (FreeIndex == MAXULONG)
+        {
+           //
+           // no free block found
+           //
+           break;
+        }
+
+        //
+        // check that the allocation does not spawn over page boundaries
+        //
+        StartPage = (FreeIndex * m_BlockSize);
+        StartPage = (StartPage != 0 ? StartPage / PAGE_SIZE : 0);
+        EndPage = ((FreeIndex + BlockCount) * m_BlockSize) / PAGE_SIZE;
+
+        //
+        // does the request start and end on the same page
+        //
+        if (StartPage == EndPage)
+        {
+            //
+            // reserve block
+            //
+            RtlSetBits(&m_Bitmap, FreeIndex, BlockCount);
+
+            //
+            // reserve block
+            //
+            break;
+        }
+        else if ((BlockCount == BlocksPerPage) && (FreeIndex % BlocksPerPage == 0))
+        {
+            //
+            // the request equals PAGE_SIZE and is aligned at page boundary
+            // reserve block
+            //
+            RtlSetBits(&m_Bitmap, FreeIndex, BlockCount);
+
+            //
+            // reserve block
+            //
+            break;
+        }
+        else
+        {
+            //
+            // request spawned over page boundary
+            // restart search on next page
+            //
+            FreeIndex = (EndPage *  PAGE_SIZE) / m_BlockSize;
+        }
+    }
+    while(TRUE);
+
+    //
+    // release lock
+    //
+    KeReleaseSpinLock(m_Lock, OldLevel);
+
+    //
+    // did allocation succeed
+    //
+    if (FreeIndex == MAXULONG)
+    {
+        //
+        // failed to allocate block, requestor must retry
+        //
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    //
+    // return result
+    //
+    *OutVirtualAddress = (PVOID)((ULONG_PTR)m_VirtualBase + FreeIndex * m_BlockSize);
+    OutPhysicalAddress->QuadPart = m_PhysicalAddress.QuadPart + FreeIndex * m_BlockSize;
+
+    //
+    // clear block
+    //
+    RtlZeroMemory(*OutVirtualAddress, Length);
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CDMAMemoryManager::Release(
+    IN PVOID VirtualAddress,
+    IN ULONG Size)
+{
+    KIRQL OldLevel;
+    ULONG BlockOffset = 0, BlockLength;
+
+    //
+    // sanity checks
+    //
+    PC_ASSERT(VirtualAddress);
+    PC_ASSERT((ULONG_PTR)VirtualAddress >= (ULONG_PTR)m_VirtualBase);
+    PC_ASSERT((ULONG_PTR)m_VirtualBase + m_DmaBufferSize > (ULONG_PTR)m_VirtualBase);
+
+    //
+    // calculate block length
+    //
+    BlockLength = ((ULONG_PTR)VirtualAddress - (ULONG_PTR)m_VirtualBase);
+
+    //
+    // check if its the first block
+    //
+    if (BlockLength)
+    {
+        //
+        // divide by base block size
+        //
+        BlockOffset = BlockLength / m_BlockSize;
+    }
+
+    //
+    // align length to block size
+    //
+    Size = (Size + m_BlockSize - 1) & ~(m_BlockSize - 1);
+
+    //
+    // acquire lock
+    //
+    KeAcquireSpinLock(m_Lock, &OldLevel);
+
+    //
+    // release buffer
+    //
+    RtlClearBits(&m_Bitmap, BlockOffset, Size);
+
+    //
+    // release lock
+    //
+    KeReleaseSpinLock(m_Lock, OldLevel);
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CreateDMAMemoryManager(
+    PDMAMEMORYMANAGER *OutMemoryManager)
+{
+    CDMAMemoryManager* This;
+
+    //
+    // allocate controller
+    //
+    This = new(NonPagedPool, TAG_USBEHCI) CDMAMemoryManager(0);
+    if (!This)
+    {
+        //
+        // failed to allocate
+        //
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // add reference count
+    //
+    This->AddRef();
+
+    //
+    // return result
+    //
+    *OutMemoryManager = (PDMAMEMORYMANAGER)This;
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
diff --git a/drivers/usb/usbehci_new/misc.cpp b/drivers/usb/usbehci_new/misc.cpp
new file mode 100644 (file)
index 0000000..56c35cc
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * PROJECT:     ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/usb/usbehci/misc.cpp
+ * PURPOSE:     USB EHCI device driver.
+ * PROGRAMMERS:
+ *              Michael Martin (michael.martin@reactos.org)
+ *              Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+#include "usbehci.h"
+
+//
+// driver verifier
+//
+IO_COMPLETION_ROUTINE SyncForwardIrpCompletionRoutine;
+
+NTSTATUS
+NTAPI
+SyncForwardIrpCompletionRoutine(
+    PDEVICE_OBJECT DeviceObject,
+    PIRP Irp, 
+    PVOID Context)
+{
+    if (Irp->PendingReturned)
+    {
+        KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
+    }
+    return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS
+NTAPI
+SyncForwardIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+    KEVENT Event;
+    NTSTATUS Status;
+
+    //
+    // initialize event
+    //
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+    //
+    // copy irp stack location
+    //
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+
+    //
+    // set completion routine
+    //
+    IoSetCompletionRoutine(Irp, SyncForwardIrpCompletionRoutine, &Event, TRUE, TRUE, TRUE);
+
+
+    //
+    // call driver
+    //
+    Status = IoCallDriver(DeviceObject, Irp);
+
+
+    //
+    // check if pending
+    //
+    if (Status == STATUS_PENDING)
+    {
+        //
+        // wait for the request to finish
+        //
+        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+
+        //
+        // copy status code
+        //
+        Status = Irp->IoStatus.Status;
+    }
+
+    //
+    // done
+    //
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+GetBusInterface(
+    PDEVICE_OBJECT DeviceObject, 
+    PBUS_INTERFACE_STANDARD busInterface)
+{
+    KEVENT Event;
+    NTSTATUS Status;
+    PIRP Irp;
+    IO_STATUS_BLOCK IoStatus;
+    PIO_STACK_LOCATION Stack;
+
+    if ((!DeviceObject) || (!busInterface))
+        return STATUS_UNSUCCESSFUL;
+
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
+                                       DeviceObject,
+                                       NULL,
+                                       0,
+                                       NULL,
+                                       &Event,
+                                       &IoStatus);
+
+    if (Irp == NULL)
+    {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    Stack=IoGetNextIrpStackLocation(Irp);
+    Stack->MajorFunction = IRP_MJ_PNP;
+    Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
+    Stack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
+    Stack->Parameters.QueryInterface.InterfaceType = (LPGUID)&GUID_BUS_INTERFACE_STANDARD;
+    Stack->Parameters.QueryInterface.Version = 1;
+    Stack->Parameters.QueryInterface.Interface = (PINTERFACE)busInterface;
+    Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
+    Irp->IoStatus.Status=STATUS_NOT_SUPPORTED ;
+
+    Status=IoCallDriver(DeviceObject, Irp);
+
+    if (Status == STATUS_PENDING)
+    {
+        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+
+        Status=IoStatus.Status;
+    }
+
+    return Status;
+}
+
diff --git a/drivers/usb/usbehci_new/purecall.cpp b/drivers/usb/usbehci_new/purecall.cpp
new file mode 100644 (file)
index 0000000..c168b79
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * PROJECT:     ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/usb/usbehci_new/purecall.cpp
+ * PURPOSE:     USB EHCI device driver.
+ * PROGRAMMERS:
+ *              Michael Martin (michael.martin@reactos.org)
+ *              Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+#include "usbehci.h"
+
+
+extern "C" {
+  void 
+         __cxa_pure_virtual()
+  {
+    // put error handling here
+
+    DbgBreakPoint();
+
+  }
+}
+
diff --git a/drivers/usb/usbehci_new/usb_device.cpp b/drivers/usb/usbehci_new/usb_device.cpp
new file mode 100644 (file)
index 0000000..7ef98b8
--- /dev/null
@@ -0,0 +1,1286 @@
+/*
+ * PROJECT:     ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/usb/usbehci/usb_device.cpp
+ * PURPOSE:     USB EHCI device driver.
+ * PROGRAMMERS:
+ *              Michael Martin (michael.martin@reactos.org)
+ *              Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+#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:
+    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;
+    }
+
+    // IUSBDevice interface functions
+    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 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(UCHAR DeviceAddress);
+    virtual void GetDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor);
+    virtual UCHAR GetConfigurationValue();
+    virtual NTSTATUS SubmitIrp(PIRP Irp);
+    virtual VOID GetConfigurationDescriptors(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer, IN ULONG BufferLength, OUT PULONG OutBufferLength);
+    virtual ULONG GetConfigurationDescriptorsLength();
+    virtual NTSTATUS SubmitSetupPacket(IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, OUT ULONG BufferLength, OUT PVOID Buffer);
+    virtual NTSTATUS SelectConfiguration(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, IN PUSBD_INTERFACE_INFORMATION Interface, OUT USBD_CONFIGURATION_HANDLE *ConfigurationHandle);
+    virtual NTSTATUS SelectInterface(IN USBD_CONFIGURATION_HANDLE ConfigurationHandle, IN OUT PUSBD_INTERFACE_INFORMATION Interface);
+
+    // local function
+    virtual NTSTATUS CommitIrp(PIRP Irp);
+    virtual NTSTATUS CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG BufferLength, IN OUT PMDL Mdl);
+    virtual NTSTATUS CreateConfigurationDescriptor(ULONG ConfigurationIndex);
+    virtual NTSTATUS CreateDeviceDescriptor();
+    virtual VOID DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor);
+    virtual VOID DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor);
+
+    // constructor / destructor
+    CUSBDevice(IUnknown *OuterUnknown){}
+    virtual ~CUSBDevice(){}
+
+protected:
+    LONG m_Ref;
+    PHUBCONTROLLER m_HubController;
+    PUSBHARDWAREDEVICE m_Device;
+    PVOID m_Parent; 
+    ULONG m_Port;
+    UCHAR m_DeviceAddress;
+    PVOID m_Data;
+    UCHAR m_ConfigurationIndex;
+    KSPIN_LOCK m_Lock;
+    USB_DEVICE_DESCRIPTOR m_DeviceDescriptor;
+    ULONG m_PortStatus;
+    PUSBQUEUE m_Queue;
+    PDMAMEMORYMANAGER m_DmaManager;
+
+    PUSB_CONFIGURATION m_ConfigurationDescriptors;
+};
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+STDMETHODCALLTYPE
+CUSBDevice::QueryInterface(
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    return STATUS_UNSUCCESSFUL;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBDevice::Initialize(
+    IN PHUBCONTROLLER HubController, 
+    IN PUSBHARDWAREDEVICE Device, 
+    IN PVOID Parent, 
+    IN ULONG Port,
+    IN ULONG PortStatus)
+{
+    NTSTATUS Status;
+
+    //
+    // initialize members
+    //
+    m_HubController = HubController;
+    m_Device = Device;
+    m_Parent = Parent;
+    m_Port = Port;
+    m_PortStatus = PortStatus;
+
+    //
+    // initialize device lock
+    //
+    KeInitializeSpinLock(&m_Lock);
+
+    //
+    // no device address has been set yet
+    //
+    m_DeviceAddress = 0;
+
+    //
+    // get usb request queue
+    //
+    Status = m_Device->GetUSBQueue(&m_Queue);
+    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)
+{
+    PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+    NTSTATUS Status;
+    UCHAR OldAddress;
+    ULONG Index;
+
+    DPRINT1("CUSBDevice::SetDeviceAddress Address %d\n", DeviceAddress);
+
+    CtrlSetup = (PUSB_DEFAULT_PIPE_SETUP_PACKET)ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET), TAG_USBEHCI);
+    if (!CtrlSetup)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    //
+    // 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);
+
+    //
+    // free setup packet
+    //
+    ExFreePoolWithTag(CtrlSetup, TAG_USBEHCI);
+
+    //
+    // 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;
+    }
+
+    //
+    // lets have a short nap
+    //
+    KeStallExecutionProcessor(300);
+
+    //
+    // 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 retrieve device descriptor with device address set Error %x\n", 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()
+{
+    //
+    // return configuration index
+    //
+    return m_ConfigurationIndex;
+}
+
+//----------------------------------------------------------------------------------------
+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);
+
+    //
+    // mark irp as pending
+    //
+    IoMarkIrpPending(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_PENDING;
+}
+
+//----------------------------------------------------------------------------------------
+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(
+    IN PUSB_DEFAULT_PIPE_SETUP_PACKET Packet,
+    IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor,
+    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, m_DeviceAddress, EndpointDescriptor, 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
+    //
+    RtlZeroMemory(&m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
+    RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+
+    //
+    // setup request
+    //
+    CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
+    CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
+    CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR);
+    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, 0, sizeof(USB_DEVICE_DESCRIPTOR), Mdl);
+
+    //
+    // now free the mdl
+    //
+    IoFreeMdl(Mdl);
+
+    if (NT_SUCCESS(Status))
+    {
+        //
+        // informal dbg print
+        //
+        DumpDeviceDescriptor(&m_DeviceDescriptor);
+    }
+
+    //
+    // done
+    //
+    return Status;
+
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBDevice::CreateConfigurationDescriptor(
+    ULONG Index)
+{
+    PVOID Buffer;
+    USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+    NTSTATUS Status;
+    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, 0, 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;
+
+    //
+    // informal debug print
+    //
+    DumpConfigurationDescriptor(ConfigurationDescriptor);
+
+    //
+    // 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;
+}
+//----------------------------------------------------------------------------------------
+VOID
+CUSBDevice::GetConfigurationDescriptors(
+    IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer,
+    IN ULONG BufferLength,
+    OUT PULONG OutBufferLength)
+{
+    PVOID Buffer;
+    ULONG InterfaceIndex, EndpointIndex;
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(BufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
+    PC_ASSERT(ConfigDescriptorBuffer);
+    PC_ASSERT(OutBufferLength);
+
+    //
+    // reset copied length
+    //
+    *OutBufferLength = 0;
+
+    //
+    // FIXME: support multiple configurations
+    //
+    PC_ASSERT(m_DeviceDescriptor.bNumConfigurations == 1);
+
+    //
+    // copy first configuration descriptor
+    //
+    RtlCopyMemory(ConfigDescriptorBuffer, &m_ConfigurationDescriptors[0].ConfigurationDescriptor, sizeof(USB_CONFIGURATION_DESCRIPTOR));
+
+    //
+    // subtract length
+    //
+    BufferLength -= sizeof(USB_CONFIGURATION_DESCRIPTOR);
+    *OutBufferLength += sizeof(USB_CONFIGURATION_DESCRIPTOR);
+
+    //
+    // increment offset
+    //
+    Buffer = (PVOID)(ConfigDescriptorBuffer + 1);
+
+    for(InterfaceIndex = 0; InterfaceIndex < m_ConfigurationDescriptors[0].ConfigurationDescriptor.bNumInterfaces; InterfaceIndex++)
+    {
+        if (BufferLength < sizeof(USB_INTERFACE_DESCRIPTOR))
+        {
+            //
+            // no more room in buffer
+            //
+            return;
+        }
+
+        //
+        // copy interface descriptor
+        //
+        RtlCopyMemory(Buffer, &m_ConfigurationDescriptors[0].Interfaces[InterfaceIndex].InterfaceDescriptor, sizeof(USB_INTERFACE_DESCRIPTOR));
+
+        //
+        // increment offset
+        //
+        Buffer = (PVOID)((ULONG_PTR)Buffer + sizeof(USB_INTERFACE_DESCRIPTOR));
+        BufferLength -= sizeof(USB_INTERFACE_DESCRIPTOR);
+        *OutBufferLength += sizeof(USB_INTERFACE_DESCRIPTOR);
+
+        //
+        // does the interface have endpoints
+        //
+        if (m_ConfigurationDescriptors[0].Interfaces[InterfaceIndex].InterfaceDescriptor.bNumEndpoints)
+        {
+            //
+            // is enough space available
+            //
+            if (BufferLength < sizeof(USB_ENDPOINT_DESCRIPTOR) * m_ConfigurationDescriptors[0].Interfaces[InterfaceIndex].InterfaceDescriptor.bNumEndpoints)
+            {
+                //
+                // no buffer
+                //
+                return;
+            }
+
+            //
+            // copy end points
+            //
+            for(EndpointIndex = 0; EndpointIndex < m_ConfigurationDescriptors[0].Interfaces[InterfaceIndex].InterfaceDescriptor.bNumEndpoints; EndpointIndex++)
+            {
+                //
+                // copy endpoint
+                //
+                RtlCopyMemory(Buffer, &m_ConfigurationDescriptors[0].Interfaces[InterfaceIndex].EndPoints[EndpointIndex].EndPointDescriptor, sizeof(USB_ENDPOINT_DESCRIPTOR));
+
+                //
+                // increment buffer offset
+                //
+                Buffer = (PVOID)((ULONG_PTR)Buffer + sizeof(USB_ENDPOINT_DESCRIPTOR));
+                BufferLength -= sizeof(USB_ENDPOINT_DESCRIPTOR);
+                *OutBufferLength += sizeof(USB_ENDPOINT_DESCRIPTOR);
+            }
+        }
+    }
+}
+
+//----------------------------------------------------------------------------------------
+ULONG
+CUSBDevice::GetConfigurationDescriptorsLength()
+{
+    //
+    // FIXME: support multiple configurations
+    //
+    PC_ASSERT(m_DeviceDescriptor.bNumConfigurations == 1);
+
+    return m_ConfigurationDescriptors[0].ConfigurationDescriptor.wTotalLength;
+}
+//----------------------------------------------------------------------------------------
+VOID
+CUSBDevice::DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
+{
+    DPRINT1("Dumping Device Descriptor %x\n", DeviceDescriptor);
+    DPRINT1("bLength %x\n", DeviceDescriptor->bLength);
+    DPRINT1("bDescriptorType %x\n", DeviceDescriptor->bDescriptorType);
+    DPRINT1("bcdUSB %x\n", DeviceDescriptor->bcdUSB);
+    DPRINT1("bDeviceClass %x\n", DeviceDescriptor->bDeviceClass);
+    DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor->bDeviceSubClass);
+    DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor->bDeviceProtocol);
+    DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor->bMaxPacketSize0);
+    DPRINT1("idVendor %x\n", DeviceDescriptor->idVendor);
+    DPRINT1("idProduct %x\n", DeviceDescriptor->idProduct);
+    DPRINT1("bcdDevice %x\n", DeviceDescriptor->bcdDevice);
+    DPRINT1("iManufacturer %x\n", DeviceDescriptor->iManufacturer);
+    DPRINT1("iProduct %x\n", DeviceDescriptor->iProduct);
+    DPRINT1("iSerialNumber %x\n", DeviceDescriptor->iSerialNumber);
+    DPRINT1("bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations);
+}
+
+//----------------------------------------------------------------------------------------
+VOID
+CUSBDevice::DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
+{
+    DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor);
+    DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength);
+    DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
+    DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
+    DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
+    DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
+    DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
+    DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
+    DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
+}
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBDevice::SubmitSetupPacket(
+    IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, 
+    IN OUT ULONG BufferLength, 
+    OUT PVOID Buffer)
+{
+    NTSTATUS Status;
+    PMDL Mdl;
+
+    //
+    // allocate mdl
+    //
+    Mdl = IoAllocateMdl(Buffer, BufferLength, FALSE, FALSE, 0);
+
+    //
+    // HACK HACK HACK: assume the buffer is build from non paged pool
+    //
+    MmBuildMdlForNonPagedPool(Mdl);
+
+    //
+    // commit setup packet
+    //
+    Status = CommitSetupPacket(SetupPacket, 0, BufferLength, Mdl);
+
+    //
+    // free mdl
+    //
+    IoFreeMdl(Mdl);
+
+    //
+    // done
+    //
+    return Status;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBDevice::SelectConfiguration(
+    IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
+    IN PUSBD_INTERFACE_INFORMATION InterfaceInfo,
+    OUT USBD_CONFIGURATION_HANDLE *ConfigurationHandle)
+{
+    ULONG ConfigurationIndex = 0;
+    ULONG InterfaceIndex, PipeIndex;
+    USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+    NTSTATUS Status;
+
+    //
+    // FIXME: support multiple configurations
+    //
+    PC_ASSERT(m_DeviceDescriptor.bNumConfigurations == 1);
+    PC_ASSERT(ConfigurationDescriptor->iConfiguration == m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor.iConfiguration);
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(ConfigurationDescriptor->bNumInterfaces <= m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor.bNumInterfaces);
+
+    //
+    // copy interface info and pipe info
+    //
+    for(InterfaceIndex = 0; InterfaceIndex < ConfigurationDescriptor->bNumInterfaces; InterfaceIndex++)
+    {
+        //
+        // sanity check: is the info pre-layed out
+        //
+        PC_ASSERT(InterfaceInfo->NumberOfPipes == m_ConfigurationDescriptors[ConfigurationIndex].Interfaces[InterfaceIndex].InterfaceDescriptor.bNumEndpoints);
+        PC_ASSERT(InterfaceInfo->Length != 0);
+#ifdef _MSC_VER
+        PC_ASSERT(InterfaceInfo->Length == FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes[InterfaceInfo->NumberOfPipes]));
+#endif
+
+        //
+        // copy interface info
+        //
+        InterfaceInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)&m_ConfigurationDescriptors[ConfigurationIndex].Interfaces[InterfaceIndex];
+        InterfaceInfo->Class = m_ConfigurationDescriptors[ConfigurationIndex].Interfaces[InterfaceIndex].InterfaceDescriptor.bInterfaceClass;
+        InterfaceInfo->SubClass = m_ConfigurationDescriptors[ConfigurationIndex].Interfaces[InterfaceIndex].InterfaceDescriptor.bInterfaceSubClass;
+        InterfaceInfo->Protocol = m_ConfigurationDescriptors[ConfigurationIndex].Interfaces[InterfaceIndex].InterfaceDescriptor.bInterfaceProtocol;
+        InterfaceInfo->Reserved = 0;
+
+        //
+        // copy endpoint info
+        //
+        for(PipeIndex = 0; PipeIndex < InterfaceInfo->NumberOfPipes; PipeIndex++)
+        {
+            //
+            // copy pipe info
+            //
+            InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize = m_ConfigurationDescriptors[ConfigurationIndex].Interfaces[InterfaceIndex].EndPoints[PipeIndex].EndPointDescriptor.wMaxPacketSize;
+            InterfaceInfo->Pipes[PipeIndex].EndpointAddress = m_ConfigurationDescriptors[ConfigurationIndex].Interfaces[InterfaceIndex].EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress;
+            InterfaceInfo->Pipes[PipeIndex].Interval = m_ConfigurationDescriptors[ConfigurationIndex].Interfaces[InterfaceIndex].EndPoints[PipeIndex].EndPointDescriptor.bInterval;
+            InterfaceInfo->Pipes[PipeIndex].PipeType = (USBD_PIPE_TYPE)m_ConfigurationDescriptors[ConfigurationIndex].Interfaces[InterfaceIndex].EndPoints[PipeIndex].EndPointDescriptor.bmAttributes;
+            InterfaceInfo->Pipes[PipeIndex].PipeHandle = (PVOID)&m_ConfigurationDescriptors[ConfigurationIndex].Interfaces[InterfaceIndex].EndPoints[PipeIndex].EndPointDescriptor;
+        }
+
+        //
+        // move offset
+        //
+        InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)PtrToUlong(InterfaceInfo) + InterfaceInfo->Length);
+    }
+
+    //
+    // now build setup packet
+    //
+    RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+    CtrlSetup.bRequest = USB_REQUEST_SET_CONFIGURATION;
+    CtrlSetup.wValue.W = ConfigurationDescriptor->bConfigurationValue;
+
+    //
+    // select configuration
+    //
+    Status = CommitSetupPacket(&CtrlSetup, 0, 0, 0);
+
+    //
+    // informal debug print
+    //
+    DPRINT1("CUsbDevice::SelectConfiguration New Configuration %x Old Configuration %x Result %x\n", ConfigurationDescriptor->iConfiguration, m_ConfigurationIndex, Status);
+
+    if (NT_SUCCESS(Status))
+    {
+        //
+        // store configuration device index
+        //
+        m_ConfigurationIndex = ConfigurationDescriptor->iConfiguration;
+
+        //
+        // store configuration handle
+        //
+        *ConfigurationHandle = &m_ConfigurationDescriptors[ConfigurationIndex];
+    }
+
+    //
+    // done
+    //
+    return Status;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBDevice::SelectInterface(
+    IN USBD_CONFIGURATION_HANDLE ConfigurationHandle,
+    IN OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo)
+{
+    ULONG ConfigurationIndex = 0;
+    PUSB_CONFIGURATION Configuration;
+    ULONG PipeIndex;
+    USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+    NTSTATUS Status;
+
+    //
+    // FIXME support multiple configurations
+    //
+    PC_ASSERT(&m_ConfigurationDescriptors[ConfigurationIndex] == (PUSB_CONFIGURATION)ConfigurationHandle);
+
+    //
+    // get configuration struct
+    //
+    Configuration = (PUSB_CONFIGURATION)ConfigurationHandle;
+
+    //
+    // sanity checks
+    //
+    PC_ASSERT(Configuration->ConfigurationDescriptor.bNumInterfaces > InterfaceInfo->InterfaceNumber);
+    PC_ASSERT(Configuration->Interfaces[InterfaceInfo->InterfaceNumber].InterfaceDescriptor.bNumEndpoints == InterfaceInfo->NumberOfPipes);
+#ifdef _MSC_VER
+    PC_ASSERT(InterfaceInfo->Length == FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes[InterfaceInfo->NumberOfPipes]));
+#endif
+
+    //
+    // copy pipe handles
+    //
+    for(PipeIndex = 0; PipeIndex < InterfaceInfo->NumberOfPipes; PipeIndex++)
+    {
+        //
+        // copy pipe handle
+        //
+        DPRINT1("PipeIndex %lu\n", PipeIndex);
+        DPRINT1("EndpointAddress %x\n", InterfaceInfo->Pipes[PipeIndex].EndpointAddress);
+        DPRINT1("Interval %d\n", InterfaceInfo->Pipes[PipeIndex].Interval);
+        DPRINT1("MaximumPacketSize %d\n", InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize);
+        DPRINT1("MaximumTransferSize %d\n", InterfaceInfo->Pipes[PipeIndex].MaximumTransferSize);
+        DPRINT1("PipeFlags %d\n", InterfaceInfo->Pipes[PipeIndex].PipeFlags);
+        DPRINT1("PipeType %dd\n", InterfaceInfo->Pipes[PipeIndex].PipeType);
+        DPRINT1("UsbEndPoint %x\n", Configuration->Interfaces[InterfaceInfo->InterfaceNumber].EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress);
+        PC_ASSERT(Configuration->Interfaces[InterfaceInfo->InterfaceNumber].EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress == InterfaceInfo->Pipes[PipeIndex].EndpointAddress);
+
+        InterfaceInfo->Pipes[PipeIndex].PipeHandle = &Configuration->Interfaces[InterfaceInfo->InterfaceNumber].EndPoints[PipeIndex].EndPointDescriptor;
+
+        if (Configuration->Interfaces[InterfaceInfo->InterfaceNumber].EndPoints[PipeIndex].EndPointDescriptor.bmAttributes & (USB_ENDPOINT_TYPE_ISOCHRONOUS | USB_ENDPOINT_TYPE_INTERRUPT))
+        {
+            //
+            // FIXME: check if enough bandwidth is available
+            //
+        }
+    }
+
+    //
+    // initialize setup packet
+    //
+    RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+    CtrlSetup.bRequest = USB_REQUEST_SET_INTERFACE;
+    CtrlSetup.wValue.W = Configuration->Interfaces[InterfaceInfo->InterfaceNumber].InterfaceDescriptor.bAlternateSetting;
+    CtrlSetup.wIndex.W = Configuration->Interfaces[InterfaceInfo->InterfaceNumber].InterfaceDescriptor.bInterfaceNumber;
+    CtrlSetup.bmRequestType.B = 0x01;
+
+    //
+    // issue request
+    //
+    Status = CommitSetupPacket(&CtrlSetup, 0, 0, 0);
+
+    //
+    // informal debug print
+    //
+    DPRINT1("CUSBDevice::SelectInterface AlternateSetting %x InterfaceNumber %x Status %x\n", InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber, Status);
+
+    //
+    // done
+    //
+    return Status;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CreateUSBDevice(
+    PUSBDEVICE *OutDevice)
+{
+    CUSBDevice * This;
+
+    //
+    // allocate controller
+    //
+    This = new(NonPagedPool, TAG_USBEHCI) CUSBDevice(0);
+    if (!This)
+    {
+        //
+        // failed to allocate
+        //
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // add reference count
+    //
+    This->AddRef();
+
+    //
+    // return result
+    //
+    *OutDevice = (PUSBDEVICE)This;
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
+
diff --git a/drivers/usb/usbehci_new/usb_queue.cpp b/drivers/usb/usbehci_new/usb_queue.cpp
new file mode 100644 (file)
index 0000000..574ef65
--- /dev/null
@@ -0,0 +1,925 @@
+/*
+ * PROJECT:     ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/usb/usbehci/usb_queue.cpp
+ * PURPOSE:     USB EHCI device driver.
+ * PROGRAMMERS:
+ *              Michael Martin (michael.martin@reactos.org)
+ *              Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+#include "usbehci.h"
+#include "hardware.h"
+
+class CUSBQueue : public IUSBQueue
+{
+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;
+    }
+
+    virtual NTSTATUS Initialize(IN PUSBHARDWAREDEVICE Hardware, PDMA_ADAPTER AdapterObject, IN PDMAMEMORYMANAGER MemManager, IN OPTIONAL PKSPIN_LOCK Lock);
+    virtual ULONG GetPendingRequestCount();
+    virtual NTSTATUS AddUSBRequest(PURB Urb);
+    virtual NTSTATUS AddUSBRequest(IUSBRequest * Request);
+    virtual NTSTATUS CancelRequests();
+    virtual NTSTATUS CreateUSBRequest(IUSBRequest **OutRequest);
+    virtual VOID InterruptCallback(IN NTSTATUS Status, OUT PULONG ShouldRingDoorBell);
+    virtual VOID CompleteAsyncRequests();
+
+    // constructor / destructor
+    CUSBQueue(IUnknown *OuterUnknown){}
+    virtual ~CUSBQueue(){}
+
+protected:
+    LONG m_Ref;                                                                         // reference count
+    KSPIN_LOCK m_Lock;                                                                  // list lock
+    PDMA_ADAPTER m_Adapter;                                                             // dma adapter
+    PUSBHARDWAREDEVICE m_Hardware;                                                      // stores hardware object
+    PQUEUE_HEAD AsyncListQueueHead;                                                     // async queue head
+    LIST_ENTRY m_CompletedRequestAsyncList;                                             // completed async request list
+    LIST_ENTRY m_PendingRequestAsyncList;                                               // pending async request list
+    ULONG m_MaxPeriodicListEntries;                                                     // max perdiodic list entries
+    ULONG m_MaxPollingInterval;                                                         // max polling interval
+    PHYSICAL_ADDRESS m_SyncFrameListAddr;                                               // physical address of sync frame list
+    PULONG m_SyncFrameList;                                                             // virtual address of sync frame list
+    PQUEUE_HEAD * m_SyncFrameListQueueHeads;                                            // stores the frame list of queue head
+
+    // queue head manipulation functions
+    VOID LinkQueueHead(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead);
+    VOID UnlinkQueueHead(PQUEUE_HEAD QueueHead);
+    VOID LinkQueueHeadChain(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead);
+    PQUEUE_HEAD UnlinkQueueHeadChain(PQUEUE_HEAD HeadQueueHead, ULONG Count);
+
+    // processes the async list
+    VOID ProcessAsyncList(IN NTSTATUS Status, OUT PULONG ShouldRingDoorBell);
+
+    // called for each completed queue head
+    VOID QueueHeadCompletion(PQUEUE_HEAD QueueHead, NTSTATUS Status);
+
+    // called when the completion queue is cleaned up
+    VOID QueueHeadCleanup(PQUEUE_HEAD QueueHead);
+
+    // intializes the sync schedule
+    NTSTATUS InitializeSyncSchedule(IN PUSBHARDWAREDEVICE Hardware, IN PDMAMEMORYMANAGER MemManager);
+};
+
+//=================================================================================================
+// COM
+//
+NTSTATUS
+STDMETHODCALLTYPE
+CUSBQueue::QueryInterface(
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    if (IsEqualGUIDAligned(refiid, IID_IUnknown))
+    {
+        *Output = PVOID(PUNKNOWN(this));
+        PUNKNOWN(*Output)->AddRef();
+        return STATUS_SUCCESS;
+    }
+
+    return STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS
+CUSBQueue::Initialize(
+    IN PUSBHARDWAREDEVICE Hardware,
+    IN PDMA_ADAPTER AdapterObject,
+    IN PDMAMEMORYMANAGER MemManager,
+    IN OPTIONAL PKSPIN_LOCK Lock)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    DPRINT("CUSBQueue::Initialize()\n");
+
+    ASSERT(Hardware);
+
+    //
+    // initialize device lock
+    //
+    KeInitializeSpinLock(&m_Lock);
+
+    //
+    // Get the AsyncQueueHead
+    //
+    AsyncListQueueHead = (PQUEUE_HEAD)Hardware->GetAsyncListQueueHead();
+
+    //
+    // Initialize the List Head
+    //
+    InitializeListHead(&AsyncListQueueHead->LinkedQueueHeads);
+
+    //
+    // Initialize completed async list head
+    //
+    InitializeListHead(&m_CompletedRequestAsyncList);
+
+    //
+    // Initialize pending async list head
+    //
+    InitializeListHead(&m_PendingRequestAsyncList);
+
+    //
+    // now initialize sync schedule
+    //
+    Status = InitializeSyncSchedule(Hardware, MemManager);
+
+    return Status;
+}
+
+NTSTATUS
+CUSBQueue::InitializeSyncSchedule(
+    IN PUSBHARDWAREDEVICE Hardware,
+    IN PDMAMEMORYMANAGER MemManager)
+{
+    PHYSICAL_ADDRESS QueueHeadPhysAddr;
+    NTSTATUS Status;
+    ULONG Index;
+    PQUEUE_HEAD QueueHead;
+
+    //
+    // FIXME: check if smaller list sizes are supported
+    //
+    m_MaxPeriodicListEntries = 1024;
+
+    //
+    // use polling scheme of 32ms
+    //
+    m_MaxPollingInterval = 32;
+
+    //
+    // allocate dummy frame list array
+    //
+    m_SyncFrameListQueueHeads = (PQUEUE_HEAD*)ExAllocatePool(NonPagedPool, m_MaxPollingInterval * sizeof(PQUEUE_HEAD));
+    if (!m_SyncFrameListQueueHeads)
+    {
+        //
+        // no memory
+        //
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+  
+    //
+    // first allocate a page to hold the queue array
+    //
+    Status = MemManager->Allocate(m_MaxPeriodicListEntries * sizeof(PVOID), (PVOID*)&m_SyncFrameList, &m_SyncFrameListAddr);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed to allocate sync frame list array
+        //
+        DPRINT1("Failed to allocate sync frame list\n");
+        ExFreePool(m_SyncFrameListQueueHeads);
+        ASSERT(FALSE);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // now allocate queue head descriptors for the polling interval
+    //
+    for(Index = 0; Index < m_MaxPeriodicListEntries; Index++)
+    {
+        //
+        // check if is inside our polling interrupt frequency window
+        //
+        if (Index < m_MaxPollingInterval)
+        {
+            //
+            // allocate queue head
+            //
+            Status = MemManager->Allocate(sizeof(QUEUE_HEAD), (PVOID*)&QueueHead, &QueueHeadPhysAddr);
+
+            //
+            // initialize queue head
+            //
+            QueueHead->HorizontalLinkPointer = TERMINATE_POINTER;
+            QueueHead->AlternateNextPointer = TERMINATE_POINTER;
+            QueueHead->NextPointer = TERMINATE_POINTER;
+
+            //
+            // 1 for non high speed, 0 for high speed device
+            //
+            QueueHead->EndPointCharacteristics.ControlEndPointFlag = 0;
+            QueueHead->EndPointCharacteristics.HeadOfReclamation = FALSE;
+            QueueHead->EndPointCharacteristics.MaximumPacketLength = 64;
+
+            //
+            // Set NakCountReload to max value possible
+            //
+            QueueHead->EndPointCharacteristics.NakCountReload = 0xF;
+
+            //
+            // Get the Initial Data Toggle from the QEDT
+            //
+            QueueHead->EndPointCharacteristics.QEDTDataToggleControl = FALSE;
+
+            //
+            // FIXME: check if High Speed Device
+            //
+            QueueHead->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED;
+            QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = 0x03;
+            QueueHead->Token.DWord = 0;
+            QueueHead->Token.Bits.InterruptOnComplete = FALSE;
+            QueueHead->PhysicalAddr = QueueHeadPhysAddr.LowPart;
+
+
+            //
+            // store in queue head array
+            //
+            m_SyncFrameListQueueHeads[Index] = QueueHead;
+        }
+        else
+        {
+            //
+            // get cached entry
+            //
+            QueueHead = m_SyncFrameListQueueHeads[m_MaxPeriodicListEntries % m_MaxPollingInterval];
+        }
+
+        //
+        // store entry
+        //
+        m_SyncFrameList[Index] = (QueueHead->PhysicalAddr | 0x2);
+    }
+
+    //
+    // now set the sync base
+    //
+    Hardware->SetPeriodicListRegister(m_SyncFrameListAddr.LowPart);
+
+    //
+    // sync frame list initialized
+    //
+    return STATUS_SUCCESS;
+}
+
+ULONG
+CUSBQueue::GetPendingRequestCount()
+{
+    //
+    // Loop through the pending list and iterrate one for each QueueHead that
+    // has a IRP to complete.
+    //
+
+    return 0;
+}
+
+NTSTATUS
+CUSBQueue::AddUSBRequest(
+    IUSBRequest * Request)
+{
+    PQUEUE_HEAD QueueHead;
+    NTSTATUS Status;
+    ULONG Type;
+    KIRQL OldLevel;
+
+    //
+    // sanity check
+    //
+    ASSERT(Request != NULL);
+
+    //
+    // get request type
+    //
+    Type = Request->GetTransferType();
+
+    //
+    // check if supported
+    //
+    switch(Type)
+    {
+        case USB_ENDPOINT_TYPE_ISOCHRONOUS:
+        case USB_ENDPOINT_TYPE_INTERRUPT:
+            /* NOT IMPLEMENTED IN QUEUE */
+            Status = STATUS_NOT_SUPPORTED;
+            break;
+        case USB_ENDPOINT_TYPE_BULK:
+        case USB_ENDPOINT_TYPE_CONTROL:
+            Status = STATUS_SUCCESS;
+            break;
+        default:
+            /* BUG */
+            PC_ASSERT(FALSE);
+            Status = STATUS_NOT_SUPPORTED;
+    }
+
+    //
+    // check for success
+    //
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // request not supported, please try later
+        //
+        return Status;
+    }
+
+    if (Type == USB_ENDPOINT_TYPE_BULK || Type == USB_ENDPOINT_TYPE_CONTROL)
+    {
+        //
+        // get queue head
+        //
+        Status = Request->GetQueueHead(&QueueHead);
+
+        //
+        // check for success
+        //
+        if (!NT_SUCCESS(Status))
+        {
+            //
+            // failed to get queue head
+            //
+           return Status;
+        }
+
+        DPRINT("Request %p QueueHead %p inserted into AsyncQueue\n", Request, QueueHead);
+
+        //
+        // Add it to the pending list
+        //
+        KeAcquireSpinLock(&m_Lock, &OldLevel);
+        LinkQueueHead(AsyncListQueueHead, QueueHead);
+        KeReleaseSpinLock(&m_Lock, OldLevel);
+    }
+
+
+    //
+    // add extra reference which is released when the request is completed
+    //
+    Request->AddRef();
+
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CUSBQueue::AddUSBRequest(
+    PURB Urb)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+CUSBQueue::CancelRequests()
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+CUSBQueue::CreateUSBRequest(
+    IUSBRequest **OutRequest)
+{
+    PUSBREQUEST UsbRequest;
+    NTSTATUS Status;
+
+    *OutRequest = NULL;
+    Status = InternalCreateUSBRequest(&UsbRequest);
+
+    if (NT_SUCCESS(Status))
+    {
+        *OutRequest = UsbRequest;
+    }
+
+    return Status;
+}
+
+//
+// LinkQueueHead - Links one QueueHead to the end of HeadQueueHead list, updating HorizontalLinkPointer.
+//
+VOID
+CUSBQueue::LinkQueueHead(
+    PQUEUE_HEAD HeadQueueHead,
+    PQUEUE_HEAD NewQueueHead)
+{
+    PQUEUE_HEAD LastQueueHead, NextQueueHead;
+    PLIST_ENTRY Entry;
+    ASSERT(HeadQueueHead);
+    ASSERT(NewQueueHead);
+
+    //
+    // Link the LIST_ENTRYs
+    //
+    InsertTailList(&HeadQueueHead->LinkedQueueHeads, &NewQueueHead->LinkedQueueHeads);
+
+    //
+    // Update HLP for Previous QueueHead, which should be the last in list.
+    //
+    Entry = NewQueueHead->LinkedQueueHeads.Blink;
+    LastQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
+    LastQueueHead->HorizontalLinkPointer = (NewQueueHead->PhysicalAddr | QH_TYPE_QH);
+
+    //
+    // Update HLP for NewQueueHead to point to next, which should be the HeadQueueHead
+    //
+    Entry = NewQueueHead->LinkedQueueHeads.Flink;
+    NextQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
+    ASSERT(NextQueueHead == HeadQueueHead);
+    NewQueueHead->HorizontalLinkPointer = (NextQueueHead->PhysicalAddr | QH_TYPE_QH);
+}
+
+//
+// UnlinkQueueHead - Unlinks one QueueHead, updating HorizontalLinkPointer.
+//
+VOID
+CUSBQueue::UnlinkQueueHead(
+    PQUEUE_HEAD QueueHead)
+{
+    PQUEUE_HEAD PreviousQH, NextQH;
+    PLIST_ENTRY Entry;
+
+    //
+    // sanity check: there must be at least one queue head with halted bit set
+    //
+    PC_ASSERT(QueueHead->Token.Bits.Halted == 0);
+
+    //
+    // get previous link
+    //
+    Entry = QueueHead->LinkedQueueHeads.Blink;
+
+    //
+    // get queue head structure
+    //
+    PreviousQH = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
+
+    //
+    // get next link
+    //
+    Entry = QueueHead->LinkedQueueHeads.Flink;
+
+    //
+    // get queue head structure
+    //
+    NextQH = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
+
+    //
+    // sanity check
+    //
+    ASSERT(QueueHead->HorizontalLinkPointer == (NextQH->PhysicalAddr | QH_TYPE_QH));
+
+    //
+    // remove queue head from linked list
+    //
+    PreviousQH->HorizontalLinkPointer = NextQH->PhysicalAddr | QH_TYPE_QH;
+
+    //
+    // remove software link
+    //
+    RemoveEntryList(&QueueHead->LinkedQueueHeads);
+}
+
+//
+// LinkQueueHeadChain - Links a list of QueueHeads to the HeadQueueHead list, updating HorizontalLinkPointer.
+//
+VOID
+CUSBQueue::LinkQueueHeadChain(
+    PQUEUE_HEAD HeadQueueHead,
+    PQUEUE_HEAD NewQueueHead)
+{
+    PQUEUE_HEAD LastQueueHead;
+    PLIST_ENTRY Entry;
+    ASSERT(HeadQueueHead);
+    ASSERT(NewQueueHead);
+
+    //
+    // Find the last QueueHead in NewQueueHead
+    //
+    Entry = NewQueueHead->LinkedQueueHeads.Blink;
+    ASSERT(Entry != NewQueueHead->LinkedQueueHeads.Flink);
+    LastQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
+
+    //
+    // Set the LinkPointer and Flink
+    //
+    LastQueueHead->HorizontalLinkPointer = HeadQueueHead->PhysicalAddr | QH_TYPE_QH;
+    LastQueueHead->LinkedQueueHeads.Flink = &HeadQueueHead->LinkedQueueHeads;
+
+    //
+    // Fine the last QueueHead in HeadQueueHead
+    //
+    Entry = HeadQueueHead->LinkedQueueHeads.Blink;
+    HeadQueueHead->LinkedQueueHeads.Blink = &LastQueueHead->LinkedQueueHeads;
+    LastQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
+    LastQueueHead->LinkedQueueHeads.Flink = &NewQueueHead->LinkedQueueHeads;
+    LastQueueHead->HorizontalLinkPointer = NewQueueHead->PhysicalAddr | QH_TYPE_QH;
+}
+
+//
+// UnlinkQueueHeadChain - Unlinks a list number of QueueHeads from HeadQueueHead list, updating HorizontalLinkPointer.
+// returns the chain of QueueHeads removed from HeadQueueHead.
+//
+PQUEUE_HEAD
+CUSBQueue::UnlinkQueueHeadChain(
+    PQUEUE_HEAD HeadQueueHead,
+    ULONG Count)
+{
+    PQUEUE_HEAD LastQueueHead, FirstQueueHead;
+    PLIST_ENTRY Entry;
+    ULONG Index;
+
+    //
+    // Find the last QueueHead in NewQueueHead
+    //
+    Entry = &HeadQueueHead->LinkedQueueHeads;
+    FirstQueueHead = CONTAINING_RECORD(Entry->Flink, QUEUE_HEAD, LinkedQueueHeads);
+
+    for (Index = 0; Index < Count; Index++)
+    {
+        Entry = Entry->Flink;
+
+        if (Entry == &HeadQueueHead->LinkedQueueHeads)
+        {
+            DPRINT1("Warnnig; Only %d QueueHeads in HeadQueueHead\n", Index);
+            Count = Index + 1;
+            break;
+        }
+    }
+
+    LastQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
+    HeadQueueHead->LinkedQueueHeads.Flink = LastQueueHead->LinkedQueueHeads.Flink;
+    if (Count + 1 == Index)
+    {
+        HeadQueueHead->LinkedQueueHeads.Blink = &HeadQueueHead->LinkedQueueHeads;
+    }
+    else
+        HeadQueueHead->LinkedQueueHeads.Blink = LastQueueHead->LinkedQueueHeads.Flink;
+
+    FirstQueueHead->LinkedQueueHeads.Blink = &LastQueueHead->LinkedQueueHeads;
+    LastQueueHead->LinkedQueueHeads.Flink = &FirstQueueHead->LinkedQueueHeads;
+    LastQueueHead->HorizontalLinkPointer = TERMINATE_POINTER;
+    return FirstQueueHead;
+}
+
+VOID
+CUSBQueue::QueueHeadCompletion(
+    PQUEUE_HEAD CurrentQH,
+    NTSTATUS Status)
+{
+    KIRQL OldLevel;
+
+    //
+    // now unlink the queue head
+    // FIXME: implement chained queue heads
+    //
+
+    KeAcquireSpinLock(&m_Lock, &OldLevel);
+
+    UnlinkQueueHead(CurrentQH);
+
+    InsertTailList(&m_CompletedRequestAsyncList, &CurrentQH->LinkedQueueHeads);
+
+    KeReleaseSpinLock(&m_Lock, OldLevel);
+
+}
+
+VOID
+CUSBQueue::ProcessAsyncList(
+    IN NTSTATUS Status,
+    OUT PULONG ShouldRingDoorBell)
+{
+    KIRQL OldLevel;
+    PLIST_ENTRY Entry;
+    PQUEUE_HEAD QueueHead;
+    IUSBRequest * Request;
+    BOOLEAN IsQueueHeadComplete;
+
+    //
+    // lock completed async list
+    //
+    KeAcquireSpinLock(&m_Lock, &OldLevel);
+
+    //
+    // walk async list 
+    //
+    Entry = AsyncListQueueHead->LinkedQueueHeads.Flink;
+
+    while(Entry != &AsyncListQueueHead->LinkedQueueHeads)
+    {
+        //
+        // get queue head structure
+        //
+        QueueHead = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
+
+        //
+        // sanity check
+        //
+        PC_ASSERT(QueueHead->Request);
+
+        //
+        // get IUSBRequest interface
+        //
+        Request = (IUSBRequest*)QueueHead->Request;
+
+        //
+        // move to next entry
+        //
+        Entry = Entry->Flink;
+
+        //
+        // check if queue head is complete
+        //
+        IsQueueHeadComplete = Request->IsQueueHeadComplete(QueueHead);
+
+        DPRINT("Request %p QueueHead %p Complete %d\n", Request, QueueHead, IsQueueHeadComplete);
+
+        //
+        // check if queue head is complete
+        //
+        if (IsQueueHeadComplete)
+        {
+            //
+            // current queue head is complete
+            //
+            QueueHeadCompletion(QueueHead, Status);
+
+            //
+            // ring door bell is going to be necessary
+            //
+            *ShouldRingDoorBell = TRUE;
+        }
+    }
+
+    //
+    // release lock
+    //
+    KeReleaseSpinLock(&m_Lock, OldLevel);
+}
+
+
+VOID
+CUSBQueue::InterruptCallback(
+    IN NTSTATUS Status, 
+    OUT PULONG ShouldRingDoorBell)
+{
+
+    DPRINT("CUSBQueue::InterruptCallback\n");
+
+    //
+    // iterate asynchronous list
+    //
+    *ShouldRingDoorBell = FALSE;
+    ProcessAsyncList(Status, ShouldRingDoorBell);
+
+    //
+    // TODO: implement periodic schedule processing
+    //
+}
+
+VOID
+CUSBQueue::QueueHeadCleanup(
+    PQUEUE_HEAD CurrentQH)
+{
+    PQUEUE_HEAD NewQueueHead;
+    IUSBRequest * Request;
+    BOOLEAN ShouldReleaseWhenDone;
+    USBD_STATUS UrbStatus;
+
+    //
+    // sanity checks
+    //
+    PC_ASSERT(CurrentQH->Token.Bits.Active == 0);
+    PC_ASSERT(CurrentQH->Request);
+
+
+    //
+    // get request
+    //
+    Request = (IUSBRequest*)CurrentQH->Request;
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(Request);
+
+    //
+    // check if the queue head was completed with errors
+    //
+    if (CurrentQH->Token.Bits.Halted)
+    {
+        if (CurrentQH->Token.Bits.DataBufferError)
+        {
+            //
+            // data buffer error
+            //
+            UrbStatus = USBD_STATUS_DATA_BUFFER_ERROR;
+        }
+        else if (CurrentQH->Token.Bits.BabbleDetected)
+        {
+            //
+            // babble detected
+            //
+            UrbStatus = USBD_STATUS_BABBLE_DETECTED;
+        }
+        else
+        {
+            //
+            // stall pid
+            //
+            UrbStatus = USBD_STATUS_STALL_PID;
+        }
+    }
+    else
+    {
+        //
+        // well done ;)
+        //
+        UrbStatus = USBD_STATUS_SUCCESS;
+    }
+
+    //
+    // Check if the transfer was completed and if UrbStatus is ok
+    //
+    if ((Request->IsRequestComplete() == FALSE) && (UrbStatus == USBD_STATUS_SUCCESS))
+    {
+        //
+        // let IUSBRequest free the queue head
+        //
+        Request->FreeQueueHead(CurrentQH);
+
+        //
+        // request is incomplete, get new queue head
+        //
+        if (Request->GetQueueHead(&NewQueueHead) == STATUS_SUCCESS)
+        {
+            //
+            // add to pending list
+            //
+            InsertTailList(&m_PendingRequestAsyncList, &NewQueueHead->LinkedQueueHeads);
+
+            //
+            // Done for now
+            //
+            return;
+        }
+        DPRINT1("Unable to create a new QueueHead\n");
+        PC_ASSERT(FALSE);
+
+        //
+        // Else there was a problem
+        // FIXME: Find better return
+        UrbStatus = USBD_STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    if (UrbStatus != USBD_STATUS_SUCCESS) PC_ASSERT(FALSE);
+
+    //
+    // notify request that a transfer has completed
+    //
+    Request->CompletionCallback(UrbStatus != USBD_STATUS_SUCCESS ?  STATUS_UNSUCCESSFUL : STATUS_SUCCESS,
+                                UrbStatus,
+                                CurrentQH);
+
+    //
+    // let IUSBRequest free the queue head
+    //
+    Request->FreeQueueHead(CurrentQH);
+
+    //
+    // check if we should release request when done
+    //
+    ShouldReleaseWhenDone = Request->ShouldReleaseRequestAfterCompletion();
+
+    //
+    // release reference when the request was added
+    //
+    Request->Release();
+
+    //
+    // check if the operation was asynchronous
+    //
+    if (ShouldReleaseWhenDone)
+    {
+        //
+        // release outstanding reference count
+        //
+        Request->Release();
+    }
+
+    //
+    // request is now released
+    //
+}
+
+VOID
+CUSBQueue::CompleteAsyncRequests()
+{
+    KIRQL OldLevel;
+    PLIST_ENTRY Entry;
+    PQUEUE_HEAD CurrentQH;
+    IUSBRequest *Request;
+
+    DPRINT("CUSBQueue::CompleteAsyncRequests\n");
+
+    //
+    // first acquire request lock
+    //
+    KeAcquireSpinLock(&m_Lock, &OldLevel);
+
+    //
+    // the list should not be empty
+    //
+    PC_ASSERT(!IsListEmpty(&m_CompletedRequestAsyncList));
+
+    while(!IsListEmpty(&m_CompletedRequestAsyncList))
+    {
+        //
+        // remove first entry
+        //
+        Entry = RemoveHeadList(&m_CompletedRequestAsyncList);
+
+        //
+        // get queue head structure
+        //
+        CurrentQH = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
+
+        //
+        // Get the Request for this QueueHead
+        //
+        Request = (IUSBRequest*) CurrentQH->Request;
+
+        //
+        // complete request now
+        //
+        QueueHeadCleanup(CurrentQH);
+    }
+
+    //
+    // is there a pending async entry
+    //
+    if (!IsListEmpty(&m_PendingRequestAsyncList))
+    {
+        //
+        // remove first entry
+        //
+        Entry = RemoveHeadList(&m_PendingRequestAsyncList);
+
+        //
+        // get queue head structure
+        //
+        CurrentQH = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
+
+        //
+        // Add it to the AsyncList list
+        //
+        LinkQueueHead(AsyncListQueueHead, CurrentQH);
+    }
+
+    //
+    // release lock
+    //
+    KeReleaseSpinLock(&m_Lock, OldLevel);
+}
+
+NTSTATUS
+CreateUSBQueue(
+    PUSBQUEUE *OutUsbQueue)
+{
+    PUSBQUEUE This;
+
+    //
+    // allocate controller
+    //
+    This = new(NonPagedPool, TAG_USBEHCI) CUSBQueue(0);
+    if (!This)
+    {
+        //
+        // failed to allocate
+        //
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // add reference count
+    //
+    This->AddRef();
+
+    //
+    // return result
+    //
+    *OutUsbQueue = (PUSBQUEUE)This;
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+}
diff --git a/drivers/usb/usbehci_new/usb_request.cpp b/drivers/usb/usbehci_new/usb_request.cpp
new file mode 100644 (file)
index 0000000..e48a06c
--- /dev/null
@@ -0,0 +1,1695 @@
+/*
+ * PROJECT:     ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/usb/usbehci/usb_request.cpp
+ * PURPOSE:     USB EHCI device driver.
+ * PROGRAMMERS:
+ *              Michael Martin (michael.martin@reactos.org)
+ *              Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+#define INITGUID
+
+#include "usbehci.h"
+#include "hardware.h"
+
+class CUSBRequest : public IUSBRequest
+{
+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;
+    }
+
+    // IUSBRequest interface functions
+    virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN UCHAR DeviceAddress, IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN OUT ULONG TransferBufferLength, IN OUT PMDL TransferBuffer);
+    virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager, IN OUT PIRP Irp);
+    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();
+    virtual VOID FreeQueueHead(struct _QUEUE_HEAD * QueueHead);
+    virtual VOID GetTransferBuffer(OUT PMDL * OutMDL, OUT PULONG TransferLength);
+    virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead);
+
+
+    // local functions
+    ULONG InternalGetTransferType();
+    UCHAR InternalGetPidDirection();
+    NTSTATUS BuildControlTransferQueueHead(PQUEUE_HEAD * OutHead);
+    NTSTATUS BuildBulkTransferQueueHead(PQUEUE_HEAD * OutHead);
+    NTSTATUS CreateDescriptor(PQUEUE_TRANSFER_DESCRIPTOR *OutDescriptor);
+    NTSTATUS CreateQueueHead(PQUEUE_HEAD *OutQueueHead);
+    UCHAR GetDeviceAddress();
+    NTSTATUS BuildSetupPacket();
+    NTSTATUS BuildSetupPacketFromURB();
+    ULONG InternalCalculateTransferLength();
+
+    // constructor / destructor
+    CUSBRequest(IUnknown *OuterUnknown){}
+    virtual ~CUSBRequest(){}
+
+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;
+
+    //
+    // current transfer length
+    //
+    ULONG m_TransferBufferLengthCompleted;
+
+    //
+    // Total Transfer Length
+    //
+    ULONG m_TotalBytesTransferred;
+
+    //
+    // transfer buffer MDL
+    //
+    PMDL m_TransferBufferMDL;
+
+    //
+    // caller provided setup packet
+    //
+    PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket;
+
+    //
+    // completion event for callers who initialized request with setup packet
+    //
+    PKEVENT m_CompletionEvent;
+
+    //
+    // device address for callers who initialized it with device address
+    //
+    UCHAR m_DeviceAddress;
+
+    //
+    // store end point address
+    //
+    PUSB_ENDPOINT_DESCRIPTOR m_EndpointDescriptor;
+
+    //
+    // 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;
+
+};
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+STDMETHODCALLTYPE
+CUSBRequest::QueryInterface(
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    return STATUS_UNSUCCESSFUL;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBRequest::InitializeWithSetupPacket(
+    IN PDMAMEMORYMANAGER DmaManager,
+    IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
+    IN UCHAR DeviceAddress,
+    IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor,
+    IN OUT ULONG TransferBufferLength,
+    IN OUT PMDL TransferBuffer)
+{
+    //
+    // sanity checks
+    //
+    PC_ASSERT(DmaManager);
+    PC_ASSERT(SetupPacket);
+
+    //
+    // initialize packet
+    //
+    m_DmaManager = DmaManager;
+    m_SetupPacket = SetupPacket;
+    m_TransferBufferLength = TransferBufferLength;
+    m_TransferBufferMDL = TransferBuffer;
+    m_DeviceAddress = DeviceAddress;
+    m_EndpointDescriptor = EndpointDescriptor;
+    m_TotalBytesTransferred = 0;
+
+    //
+    // Set Length Completed to 0
+    //
+    m_TransferBufferLengthCompleted = 0;
+
+    //
+    // 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;
+}
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBRequest::InitializeWithIrp(
+    IN PDMAMEMORYMANAGER DmaManager,
+    IN OUT PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    PURB Urb;
+
+    //
+    // sanity checks
+    //
+    PC_ASSERT(DmaManager);
+    PC_ASSERT(Irp);
+
+    m_DmaManager = DmaManager;
+    m_TotalBytesTransferred = 0;
+
+    //
+    // get current irp stack location
+    //
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(IoStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL);
+    PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB);
+    PC_ASSERT(IoStack->Parameters.Others.Argument1 != 0);
+
+    //
+    // get urb
+    //
+    Urb = (PURB)IoStack->Parameters.Others.Argument1;
+
+    //
+    // store irp
+    //
+    m_Irp = Irp;
+
+    //
+    // check function type
+    //
+    switch (Urb->UrbHeader.Function)
+    {
+        //
+        // luckily those request have the same structure layout
+        //
+        case URB_FUNCTION_CLASS_INTERFACE:
+        case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
+        case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
+        {
+            //
+            // bulk interrupt transfer
+            //
+            if (Urb->UrbBulkOrInterruptTransfer.TransferBufferLength)
+            {
+                //
+                // Check if there is a MDL
+                //
+                if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
+                {
+                    //
+                    // sanity check
+                    //
+                    PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
+
+                    //
+                    // Create one using TransferBuffer
+                    //
+                    DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
+                    m_TransferBufferMDL = IoAllocateMdl(Urb->UrbBulkOrInterruptTransfer.TransferBuffer,
+                                                        Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
+                                                        FALSE,
+                                                        FALSE,
+                                                        NULL);
+
+                    if (!m_TransferBufferMDL)
+                    {
+                        //
+                        // failed to allocate mdl
+                        //
+                        return STATUS_INSUFFICIENT_RESOURCES;
+                    }
+
+                    //
+                    // build mdl for non paged pool
+                    // FIXME: Does hub driver already do this when passing MDL?
+                    //
+                    MmBuildMdlForNonPagedPool(m_TransferBufferMDL);
+
+                    //
+                    // Keep that ehci created the MDL and needs to free it.
+                    //
+                }
+                else
+                {
+                    m_TransferBufferMDL = Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL;
+                }
+
+                //
+                // save buffer length
+                //
+                m_TransferBufferLength = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
+
+                //
+                // Set Length Completed to 0
+                //
+                m_TransferBufferLengthCompleted = 0;
+
+                //
+                // get endpoint descriptor
+                //
+                m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
+
+            }
+            break;
+        }
+        default:
+            DPRINT1("URB Function: not supported %x\n", Urb->UrbHeader.Function);
+            PC_ASSERT(FALSE);
+    }
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
+
+}
+
+//----------------------------------------------------------------------------------------
+VOID
+CUSBRequest::CompletionCallback(
+    IN NTSTATUS NtStatusCode,
+    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)
+    {
+        //
+        // set irp completion status
+        //
+        m_Irp->IoStatus.Status = NtStatusCode;
+
+        //
+        // get current irp stack location
+        //
+        IoStack = IoGetCurrentIrpStackLocation(m_Irp);
+
+        //
+        // get urb
+        //
+        Urb = (PURB)IoStack->Parameters.Others.Argument1;
+
+        //
+        // store urb status
+        //
+        Urb->UrbHeader.Status = UrbStatusCode;
+
+        //
+        // Check if the MDL was created
+        //
+        if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
+        {
+            //
+            // Free Mdl
+            //
+            IoFreeMdl(m_TransferBufferMDL);
+        }
+
+        //
+        // check if the request was successfull
+        //
+        if (!NT_SUCCESS(NtStatusCode))
+        {
+            //
+            // set returned length to zero in case of error
+            //
+            Urb->UrbHeader.Length = 0;
+        }
+        else
+        {
+            //
+            // calculate transfer length
+            //
+            Urb->UrbBulkOrInterruptTransfer.TransferBufferLength = InternalCalculateTransferLength();
+        }
+
+        DPRINT("Request %p Completing Irp %p NtStatusCode %x UrbStatusCode %x Transferred Length %lu\n", this, m_Irp, NtStatusCode, UrbStatusCode, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
+
+        //
+        // FIXME: check if the transfer was split
+        // if yes dont complete irp yet
+        //
+        IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
+    }
+    else
+    {
+        //
+        // signal completion event
+        //
+        PC_ASSERT(m_CompletionEvent);
+        KeSetEvent(m_CompletionEvent, 0, FALSE);
+    }
+}
+//----------------------------------------------------------------------------------------
+VOID
+CUSBRequest::CancelCallback(
+    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)
+    {
+        //
+        // set irp completion status
+        //
+        m_Irp->IoStatus.Status = NtStatusCode;
+
+        //
+        // get current irp stack location
+        //
+        IoStack = IoGetCurrentIrpStackLocation(m_Irp);
+
+        //
+        // get urb
+        //
+        Urb = (PURB)IoStack->Parameters.Others.Argument1;
+
+        //
+        // store urb status
+        //
+        DPRINT1("Request Cancelled\n");
+        Urb->UrbHeader.Status = USBD_STATUS_CANCELED;
+        Urb->UrbHeader.Length = 0;
+
+        //
+        // FIXME: check if the transfer was split
+        // if yes dont complete irp yet
+        //
+        IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
+    }
+    else
+    {
+        //
+        // signal completion event
+        //
+        PC_ASSERT(m_CompletionEvent);
+        KeSetEvent(m_CompletionEvent, 0, FALSE);
+    }
+}
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBRequest::GetQueueHead(
+    struct _QUEUE_HEAD ** OutHead)
+{
+    ULONG TransferType;
+    NTSTATUS Status;
+
+    //
+    // first get transfer type
+    //
+    TransferType = InternalGetTransferType();
+
+    //
+    // build request depending on type
+    //
+    switch(TransferType)
+    {
+        case USB_ENDPOINT_TYPE_CONTROL:
+            Status = BuildControlTransferQueueHead(OutHead);
+            break;
+        case USB_ENDPOINT_TYPE_BULK:
+            Status = BuildBulkTransferQueueHead(OutHead);
+            break;
+        case USB_ENDPOINT_TYPE_INTERRUPT:
+            DPRINT1("USB_ENDPOINT_TYPE_INTERRUPT not implemented\n");
+