[USBPORT] Bring-in the usbport driver created by Vadim Galyant. CR-111 GitHub PR...
authorAmine Khaldi <amine.khaldi@reactos.org>
Fri, 16 Jun 2017 19:20:03 +0000 (19:20 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Fri, 16 Jun 2017 19:20:03 +0000 (19:20 +0000)
svn path=/trunk/; revision=75062

20 files changed:
reactos/drivers/usb/CMakeLists.txt
reactos/drivers/usb/usbport/CMakeLists.txt [new file with mode: 0644]
reactos/drivers/usb/usbport/debug.c [new file with mode: 0644]
reactos/drivers/usb/usbport/device.c [new file with mode: 0644]
reactos/drivers/usb/usbport/endpoint.c [new file with mode: 0644]
reactos/drivers/usb/usbport/guid.c [new file with mode: 0644]
reactos/drivers/usb/usbport/iface.c [new file with mode: 0644]
reactos/drivers/usb/usbport/ioctl.c [new file with mode: 0644]
reactos/drivers/usb/usbport/pnp.c [new file with mode: 0644]
reactos/drivers/usb/usbport/power.c [new file with mode: 0644]
reactos/drivers/usb/usbport/queue.c [new file with mode: 0644]
reactos/drivers/usb/usbport/roothub.c [new file with mode: 0644]
reactos/drivers/usb/usbport/urb.c [new file with mode: 0644]
reactos/drivers/usb/usbport/usb2.c [new file with mode: 0644]
reactos/drivers/usb/usbport/usbdebug.h [new file with mode: 0644]
reactos/drivers/usb/usbport/usbport.c [new file with mode: 0644]
reactos/drivers/usb/usbport/usbport.h [new file with mode: 0644]
reactos/drivers/usb/usbport/usbport.rc [new file with mode: 0644]
reactos/drivers/usb/usbport/usbport.spec [new file with mode: 0644]
reactos/sdk/include/reactos/drivers/usbport/usbmport.h [new file with mode: 0644]

index 36650c8..d8e07f9 100644 (file)
@@ -3,5 +3,6 @@ add_subdirectory(usbd)
 add_subdirectory(usbehci)
 add_subdirectory(usbhub)
 add_subdirectory(usbohci)
+add_subdirectory(usbport)
 add_subdirectory(usbstor)
 add_subdirectory(usbuhci)
diff --git a/reactos/drivers/usb/usbport/CMakeLists.txt b/reactos/drivers/usb/usbport/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e37477e
--- /dev/null
@@ -0,0 +1,28 @@
+
+spec2def(usbport.sys usbport.spec ADD_IMPORTLIB)
+
+list(APPEND SOURCE
+    debug.c
+    device.c
+    endpoint.c
+    iface.c
+    ioctl.c
+    pnp.c
+    power.c
+    queue.c
+    roothub.c
+    urb.c
+    usb2.c
+    usbport.c
+    usbport.h)
+
+add_library(usbport SHARED
+    ${SOURCE}
+    guid.c
+    usbport.rc
+    ${CMAKE_CURRENT_BINARY_DIR}/usbport.def)
+
+add_pch(usbport usbport.h SOURCE)
+set_module_type(usbport kernelmodedriver)
+add_importlibs(usbport ntoskrnl hal)
+add_cd_file(TARGET usbport DESTINATION reactos/system32/drivers NO_CAB FOR all)
diff --git a/reactos/drivers/usb/usbport/debug.c b/reactos/drivers/usb/usbport/debug.c
new file mode 100644 (file)
index 0000000..07d2f44
--- /dev/null
@@ -0,0 +1,270 @@
+#include "usbport.h"
+
+#define NDEBUG
+#include <debug.h>
+
+#define NDEBUG_USBPORT_MINIPORT
+#define NDEBUG_USBPORT_URB
+#include "usbdebug.h"
+
+ULONG
+NTAPI
+USBPORT_DbgPrint(IN PVOID Context,
+                 IN ULONG Level,
+                 IN PCH Format,
+                 ...)
+{
+    DPRINT("USBPORT_DbgPrint: UNIMPLEMENTED. FIXME. \n");
+    return 0;
+}
+
+ULONG
+NTAPI
+USBPORT_TestDebugBreak(IN PVOID Context)
+{
+    DPRINT("USBPORT_TestDebugBreak: UNIMPLEMENTED. FIXME. \n");
+    return 0;
+}
+
+ULONG
+NTAPI
+USBPORT_AssertFailure(PVOID Context,
+                      PVOID FailedAssertion,
+                      PVOID FileName,
+                      ULONG LineNumber,
+                      PCHAR Message)
+{
+    DPRINT("USBPORT_AssertFailure: ... \n");
+    RtlAssert(FailedAssertion, FileName, LineNumber, Message);
+    return 0;
+}
+
+VOID
+NTAPI
+USBPORT_BugCheck(IN PVOID Context)
+{
+    DPRINT1("USBPORT_BugCheck: FIXME \n");
+    //KeBugCheckEx(BUGCODE_USB_DRIVER, ...);
+    ASSERT(FALSE);
+}
+
+ULONG
+NTAPI
+USBPORT_LogEntry(IN PVOID BusContext,
+                 IN ULONG DriverTag,
+                 IN ULONG EnumTag,
+                 IN ULONG P1,
+                 IN ULONG P2,
+                 IN ULONG P3)
+{
+    DPRINT_MINIPORT("USBPORT_LogEntry: BusContext - %p, EnumTag - %lx, P1 - %lx, P2 - %lx, P3 - %lx\n",
+           BusContext,
+           EnumTag,
+           P1,
+           P2,
+           P3);
+
+    return 0;
+}
+
+VOID
+NTAPI
+USBPORT_DumpingDeviceDescriptor(IN PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
+{
+    if (!DeviceDescriptor)
+    {
+        return;
+    }
+
+    DPRINT_URB("Dumping Device Descriptor - %p\n", DeviceDescriptor);
+    DPRINT_URB("bLength             - %x\n", DeviceDescriptor->bLength);
+    DPRINT_URB("bDescriptorType     - %x\n", DeviceDescriptor->bDescriptorType);
+    DPRINT_URB("bcdUSB              - %x\n", DeviceDescriptor->bcdUSB);
+    DPRINT_URB("bDeviceClass        - %x\n", DeviceDescriptor->bDeviceClass);
+    DPRINT_URB("bDeviceSubClass     - %x\n", DeviceDescriptor->bDeviceSubClass);
+    DPRINT_URB("bDeviceProtocol     - %x\n", DeviceDescriptor->bDeviceProtocol);
+    DPRINT_URB("bMaxPacketSize0     - %x\n", DeviceDescriptor->bMaxPacketSize0);
+    DPRINT_URB("idVendor            - %x\n", DeviceDescriptor->idVendor);
+    DPRINT_URB("idProduct           - %x\n", DeviceDescriptor->idProduct);
+    DPRINT_URB("bcdDevice           - %x\n", DeviceDescriptor->bcdDevice);
+    DPRINT_URB("iManufacturer       - %x\n", DeviceDescriptor->iManufacturer);
+    DPRINT_URB("iProduct            - %x\n", DeviceDescriptor->iProduct);
+    DPRINT_URB("iSerialNumber       - %x\n", DeviceDescriptor->iSerialNumber);
+    DPRINT_URB("bNumConfigurations  - %x\n", DeviceDescriptor->bNumConfigurations);
+}
+
+VOID
+NTAPI
+USBPORT_DumpingConfiguration(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor)
+{
+    PUSB_INTERFACE_DESCRIPTOR iDescriptor;
+    PUSB_ENDPOINT_DESCRIPTOR Descriptor;
+    ULONG ix;
+
+    if (!ConfigDescriptor ||
+        ConfigDescriptor->bLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))
+    {
+        return;
+    }
+
+    DPRINT_URB("Dumping ConfigDescriptor - %p\n", ConfigDescriptor);
+    DPRINT_URB("bLength             - %x\n", ConfigDescriptor->bLength);
+    DPRINT_URB("bDescriptorType     - %x\n", ConfigDescriptor->bDescriptorType);
+    DPRINT_URB("wTotalLength        - %x\n", ConfigDescriptor->wTotalLength);
+    DPRINT_URB("bNumInterfaces      - %x\n", ConfigDescriptor->bNumInterfaces);
+    DPRINT_URB("bConfigurationValue - %x\n", ConfigDescriptor->bConfigurationValue);
+    DPRINT_URB("iConfiguration      - %x\n", ConfigDescriptor->iConfiguration);
+    DPRINT_URB("bmAttributes        - %x\n", ConfigDescriptor->bmAttributes);
+    DPRINT_URB("MaxPower            - %x\n", ConfigDescriptor->MaxPower);
+
+    iDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)ConfigDescriptor +
+                                                         ConfigDescriptor->bLength);
+
+    if (iDescriptor->bLength < sizeof(USB_INTERFACE_DESCRIPTOR))
+    {
+        return;
+    }
+
+    DPRINT_URB("Dumping iDescriptor - %p\n", iDescriptor);
+    DPRINT_URB("bLength             - %x\n", iDescriptor->bLength);
+    DPRINT_URB("bDescriptorType     - %x\n", iDescriptor->bDescriptorType);
+    DPRINT_URB("bInterfaceNumber    - %x\n", iDescriptor->bInterfaceNumber);
+    DPRINT_URB("bAlternateSetting   - %x\n", iDescriptor->bAlternateSetting);
+    DPRINT_URB("bNumEndpoints       - %x\n", iDescriptor->bNumEndpoints);
+    DPRINT_URB("bInterfaceClass     - %x\n", iDescriptor->bInterfaceClass);
+    DPRINT_URB("bInterfaceSubClass  - %x\n", iDescriptor->bInterfaceSubClass);
+    DPRINT_URB("bInterfaceProtocol  - %x\n", iDescriptor->bInterfaceProtocol);
+    DPRINT_URB("iInterface          - %x\n", iDescriptor->iInterface);
+
+    Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)iDescriptor +
+                                                       iDescriptor->bLength);
+
+    for (ix = 0; ix < iDescriptor->bNumEndpoints; ix++)
+    {
+        if (Descriptor->bLength < sizeof(USB_ENDPOINT_DESCRIPTOR))
+        {
+            return;
+        }
+
+        DPRINT_URB("Dumping Descriptor  - %p\n", Descriptor);
+        DPRINT_URB("bLength             - %x\n", Descriptor->bLength);
+        DPRINT_URB("bDescriptorType     - %x\n", Descriptor->bDescriptorType);
+        DPRINT_URB("bEndpointAddress    - %x\n", Descriptor->bEndpointAddress);
+        DPRINT_URB("bmAttributes        - %x\n", Descriptor->bmAttributes);
+        DPRINT_URB("wMaxPacketSize      - %x\n", Descriptor->wMaxPacketSize);
+        DPRINT_URB("bInterval           - %x\n", Descriptor->bInterval);
+
+        Descriptor += 1;
+    }
+}
+
+VOID
+NTAPI
+USBPORT_DumpingCapabilities(IN PDEVICE_CAPABILITIES Capabilities)
+{
+    if (!Capabilities)
+    {
+        return;
+    }
+
+    DPRINT("Capabilities->Size              - %x\n", Capabilities->Size);
+    DPRINT("Capabilities->Version           - %x\n", Capabilities->Version);
+
+    DPRINT("Capabilities->DeviceD1          - %x\n", Capabilities->DeviceD1);
+    DPRINT("Capabilities->DeviceD2          - %x\n", Capabilities->DeviceD2);
+    DPRINT("Capabilities->LockSupported     - %x\n", Capabilities->LockSupported);
+    DPRINT("Capabilities->EjectSupported    - %x\n", Capabilities->EjectSupported);
+    DPRINT("Capabilities->Removable         - %x\n", Capabilities->Removable);
+    DPRINT("Capabilities->DockDevice        - %x\n", Capabilities->DockDevice);
+    DPRINT("Capabilities->UniqueID          - %x\n", Capabilities->UniqueID);
+    DPRINT("Capabilities->SilentInstall     - %x\n", Capabilities->SilentInstall);
+    DPRINT("Capabilities->RawDeviceOK       - %x\n", Capabilities->RawDeviceOK);
+    DPRINT("Capabilities->SurpriseRemovalOK - %x\n", Capabilities->SurpriseRemovalOK);
+
+    DPRINT("Capabilities->Address           - %x\n", Capabilities->Address);
+    DPRINT("Capabilities->UINumber          - %x\n", Capabilities->UINumber);
+
+    DPRINT("Capabilities->DeviceState[0]    - %x\n", Capabilities->DeviceState[0]);
+    DPRINT("Capabilities->DeviceState[1]    - %x\n", Capabilities->DeviceState[1]);
+    DPRINT("Capabilities->DeviceState[2]    - %x\n", Capabilities->DeviceState[2]);
+    DPRINT("Capabilities->DeviceState[3]    - %x\n", Capabilities->DeviceState[3]);
+    DPRINT("Capabilities->DeviceState[4]    - %x\n", Capabilities->DeviceState[4]);
+    DPRINT("Capabilities->DeviceState[5]    - %x\n", Capabilities->DeviceState[5]);
+    DPRINT("Capabilities->DeviceState[6]    - %x\n", Capabilities->DeviceState[6]);
+
+    DPRINT("Capabilities->SystemWake        - %x\n", Capabilities->SystemWake);
+    DPRINT("Capabilities->DeviceWake        - %x\n", Capabilities->DeviceWake);
+
+    DPRINT("Capabilities->D1Latency         - %x\n", Capabilities->D1Latency);
+    DPRINT("Capabilities->D2Latency         - %x\n", Capabilities->D2Latency);
+    DPRINT("Capabilities->D3Latency         - %x\n", Capabilities->D3Latency);
+}
+
+VOID
+NTAPI
+USBPORT_DumpingSetupPacket(IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket)
+{
+    DPRINT("SetupPacket->bmRequestType.B - %x\n", SetupPacket->bmRequestType.B);
+    DPRINT("SetupPacket->bRequest        - %x\n", SetupPacket->bRequest);
+    DPRINT("SetupPacket->wValue.LowByte  - %x\n", SetupPacket->wValue.LowByte);
+    DPRINT("SetupPacket->wValue.HiByte   - %x\n", SetupPacket->wValue.HiByte);
+    DPRINT("SetupPacket->wIndex.W        - %x\n", SetupPacket->wIndex.W);
+    DPRINT("SetupPacket->wLength         - %x\n", SetupPacket->wLength);
+}
+
+VOID
+NTAPI
+USBPORT_DumpingURB(IN PURB Urb)
+{
+    PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
+
+    DPRINT_URB("UrbHeader.Length           - %x\n", Urb->UrbHeader.Length);
+    DPRINT_URB("UrbHeader.Function         - %x\n", Urb->UrbHeader.Function);
+    DPRINT_URB("UrbHeader.Status           - %x\n", Urb->UrbHeader.Status);
+    DPRINT_URB("UrbHeader.UsbdDeviceHandle - %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+    DPRINT_URB("UrbHeader.UsbdFlags        - %x\n", Urb->UrbHeader.UsbdFlags);
+
+    if (Urb->UrbHeader.Length < 0x48)
+    {
+        return;
+    }
+
+    DPRINT_URB("PipeHandle                - %p\n", Urb->UrbControlTransfer.PipeHandle);
+    DPRINT_URB("TransferFlags             - %x\n", Urb->UrbControlTransfer.TransferFlags);
+    DPRINT_URB("TransferBufferLength      - %x\n", Urb->UrbControlTransfer.TransferBufferLength);
+    DPRINT_URB("TransferBuffer            - %p\n", Urb->UrbControlTransfer.TransferBuffer);
+    DPRINT_URB("TransferBufferMDL         - %p\n", Urb->UrbControlTransfer.TransferBufferMDL);
+    DPRINT_URB("UrbLink                   - %p\n", Urb->UrbControlTransfer.UrbLink);
+
+    if (Urb->UrbHeader.Length < 0x50)
+    {
+        return;
+    }
+
+    SetupPacket = (PUSB_DEFAULT_PIPE_SETUP_PACKET)&Urb->UrbControlTransfer.SetupPacket;
+    USBPORT_DumpingSetupPacket(SetupPacket);
+}
+
+VOID
+NTAPI
+USBPORT_DumpingIDs(IN PVOID Buffer)
+{
+    PWSTR Ptr;
+    ULONG Length;
+    ULONG TotalLength = 0;
+
+    Ptr = (PWSTR)Buffer;
+
+    while (*Ptr)
+    {
+        DPRINT("  %S\n", Ptr);
+        Length = (ULONG)wcslen(Ptr) + 1;
+
+        Ptr += Length;
+        TotalLength += Length;
+    }
+
+    DPRINT("TotalLength: %hu\n", TotalLength);
+    DPRINT("\n");
+}
+
diff --git a/reactos/drivers/usb/usbport/device.c b/reactos/drivers/usb/usbport/device.c
new file mode 100644 (file)
index 0000000..6bb8de7
--- /dev/null
@@ -0,0 +1,1821 @@
+#include "usbport.h"
+
+#define NDEBUG
+#include <debug.h>
+
+NTSTATUS
+NTAPI
+USBPORT_SendSetupPacket(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+                        IN PDEVICE_OBJECT FdoDevice,
+                        IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
+                        IN PVOID Buffer,
+                        IN ULONG Length,
+                        IN OUT PULONG TransferedLen,
+                        IN OUT PUSBD_STATUS pUSBDStatus)
+{
+    PURB Urb;
+    PMDL Mdl;
+    USBD_STATUS USBDStatus;
+    KEVENT Event;
+    NTSTATUS Status;
+
+    DPRINT("USBPORT_SendSetupPacket: DeviceHandle - %p, FdoDevice - %p, SetupPacket - %p, Buffer - %p, Length - %x, TransferedLen - %x, pUSBDStatus - %x\n",
+           DeviceHandle,
+           FdoDevice,
+           SetupPacket,
+           Buffer,
+           Length,
+           TransferedLen,
+           pUSBDStatus);
+
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+    Urb = ExAllocatePoolWithTag(NonPagedPool,
+                                sizeof(struct _URB_CONTROL_TRANSFER),
+                                USB_PORT_TAG);
+
+    if (Urb)
+    {
+        InterlockedIncrement(&DeviceHandle->DeviceHandleLock);
+
+        RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_TRANSFER));
+
+        RtlCopyMemory(Urb->UrbControlTransfer.SetupPacket,
+                      SetupPacket,
+                      sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+
+        Urb->UrbHeader.Length = sizeof(struct _URB_CONTROL_TRANSFER);
+        Urb->UrbHeader.Function = URB_FUNCTION_CONTROL_TRANSFER;
+        Urb->UrbHeader.UsbdDeviceHandle = DeviceHandle;
+        Urb->UrbHeader.UsbdFlags = 0;
+
+        Urb->UrbControlTransfer.PipeHandle = &DeviceHandle->PipeHandle;
+        Urb->UrbControlTransfer.TransferBufferLength = Length;
+        Urb->UrbControlTransfer.TransferBuffer = Buffer;
+        Urb->UrbControlTransfer.TransferBufferMDL = NULL;
+
+        Urb->UrbControlTransfer.TransferFlags = USBD_SHORT_TRANSFER_OK |
+                                                USBD_TRANSFER_DIRECTION;
+
+        if (SetupPacket->bmRequestType.Dir != BMREQUEST_DEVICE_TO_HOST)
+        {
+            Urb->UrbControlTransfer.TransferFlags &= ~USBD_TRANSFER_DIRECTION_IN;
+        }
+
+        Status = STATUS_SUCCESS;
+
+        if (Length)
+        {
+            Mdl = IoAllocateMdl(Buffer, Length, FALSE, FALSE, NULL);
+
+            Urb->UrbControlTransfer.TransferBufferMDL = Mdl;
+
+            if (Mdl)
+            {
+                Urb->UrbHeader.UsbdFlags |= USBD_FLAG_ALLOCATED_MDL;
+                MmBuildMdlForNonPagedPool(Mdl);
+            }
+            else
+            {
+                Status = USBPORT_USBDStatusToNtStatus(NULL,
+                                                      USBD_STATUS_INSUFFICIENT_RESOURCES);
+            }
+        }
+
+        if (NT_SUCCESS(Status))
+        {
+            USBDStatus = USBPORT_AllocateTransfer(FdoDevice,
+                                                  Urb,
+                                                  NULL,
+                                                  NULL,
+                                                  &Event);
+
+            if (USBD_SUCCESS(USBDStatus))
+            {
+                InterlockedIncrement(&DeviceHandle->DeviceHandleLock);
+
+                USBPORT_QueueTransferUrb(Urb);
+
+                KeWaitForSingleObject(&Event,
+                                      Suspended,
+                                      KernelMode,
+                                      FALSE,
+                                      NULL);
+
+                USBDStatus = Urb->UrbHeader.Status;
+            }
+
+            Status = USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
+
+            if (TransferedLen)
+                *TransferedLen = Urb->UrbControlTransfer.TransferBufferLength;
+
+            if (pUSBDStatus)
+                *pUSBDStatus = USBDStatus;
+        }
+
+        InterlockedDecrement(&DeviceHandle->DeviceHandleLock);
+        ExFreePoolWithTag(Urb, USB_PORT_TAG);
+    }
+    else
+    {
+        if (pUSBDStatus)
+            *pUSBDStatus = USBD_STATUS_INSUFFICIENT_RESOURCES;
+
+        Status = USBPORT_USBDStatusToNtStatus(NULL,
+                                              USBD_STATUS_INSUFFICIENT_RESOURCES);
+    }
+
+    DPRINT("USBPORT_SendSetupPacket: Status - %x\n", Status);
+    return Status;
+}
+
+ULONG
+NTAPI
+USBPORT_GetInterfaceLength(IN PUSB_INTERFACE_DESCRIPTOR iDescriptor,
+                           IN ULONG_PTR EndDescriptors)
+{
+    SIZE_T Length;
+    PUSB_ENDPOINT_DESCRIPTOR Descriptor;
+    ULONG ix;
+
+    DPRINT("USBPORT_GetInterfaceLength ... \n");
+
+    Length = iDescriptor->bLength;
+    Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)iDescriptor + Length);
+
+    if (iDescriptor->bNumEndpoints)
+    {
+        for (ix = 0; ix < iDescriptor->bNumEndpoints; ix++)
+        {
+            while ((Descriptor->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE) &&
+                   (Descriptor->bLength > 0))
+            {
+                Length += Descriptor->bLength;
+                Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)Descriptor +
+                                                        Descriptor->bLength);
+            }
+
+            Length += Descriptor->bLength;
+            Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)Descriptor +
+                                                    Descriptor->bLength);
+        }
+    }
+
+    while (((ULONG_PTR)Descriptor < EndDescriptors) &&
+           (Descriptor->bDescriptorType != USB_INTERFACE_DESCRIPTOR_TYPE) &&
+           (Descriptor->bLength > 0))
+    {
+        Length += Descriptor->bLength;
+        Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)Descriptor +
+                                                Descriptor->bLength);
+    }
+
+    return Length;
+}
+
+PUSB_INTERFACE_DESCRIPTOR
+NTAPI
+USBPORT_ParseConfigurationDescriptor(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor,
+                                     IN UCHAR InterfaceNumber,
+                                     IN UCHAR Alternate,
+                                     OUT PUCHAR OutAlternate)
+{
+    PUSB_CONFIGURATION_DESCRIPTOR TmpDescriptor;
+    PUSB_INTERFACE_DESCRIPTOR iDescriptor;
+    PUSB_INTERFACE_DESCRIPTOR OutDescriptor = NULL;
+    ULONG_PTR Descriptor = (ULONG_PTR)ConfigDescriptor;
+    ULONG_PTR EndDescriptors;
+    ULONG ix;
+
+    DPRINT("USBPORT_ParseConfigurationDescriptor ... \n");
+
+    if (OutAlternate)
+        *OutAlternate = 0;
+
+    for (TmpDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)((ULONG_PTR)ConfigDescriptor + ConfigDescriptor->bLength);
+         TmpDescriptor->bDescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE && TmpDescriptor->bDescriptorType > 0;
+         TmpDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)((ULONG_PTR)TmpDescriptor + TmpDescriptor->bLength))
+    ;
+
+    iDescriptor = (PUSB_INTERFACE_DESCRIPTOR)TmpDescriptor;
+
+    EndDescriptors = (ULONG_PTR)ConfigDescriptor +
+                                ConfigDescriptor->wTotalLength;
+
+    while ((Descriptor < EndDescriptors) &&
+           (iDescriptor->bInterfaceNumber != InterfaceNumber))
+    {
+        Descriptor = (ULONG_PTR)iDescriptor +
+                     USBPORT_GetInterfaceLength(iDescriptor, EndDescriptors);
+
+        iDescriptor = (PUSB_INTERFACE_DESCRIPTOR)Descriptor;
+    }
+
+    ix = 0;
+
+    while (Descriptor < EndDescriptors &&
+           iDescriptor->bInterfaceNumber == InterfaceNumber)
+    {
+        if (iDescriptor->bAlternateSetting == Alternate)
+            OutDescriptor = iDescriptor;
+
+        Descriptor = (ULONG_PTR)iDescriptor +
+                     USBPORT_GetInterfaceLength(iDescriptor, EndDescriptors);
+
+        iDescriptor = (PUSB_INTERFACE_DESCRIPTOR)Descriptor;
+
+        ++ix;
+    }
+
+    if ((ix > 1) && OutAlternate)
+        *OutAlternate = 1;
+
+    return OutDescriptor;
+}
+
+USBD_STATUS
+NTAPI
+USBPORT_OpenInterface(IN PURB Urb,
+                      IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+                      IN PDEVICE_OBJECT FdoDevice,
+                      IN PUSBPORT_CONFIGURATION_HANDLE ConfigHandle,
+                      IN PUSBD_INTERFACE_INFORMATION InterfaceInfo,
+                      IN OUT PUSBPORT_INTERFACE_HANDLE *iHandle,
+                      IN BOOLEAN IsSetInterface)
+{
+    PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+    PUSBPORT_INTERFACE_HANDLE InterfaceHandle = NULL;
+    PUSBPORT_PIPE_HANDLE PipeHandle;
+    PUSB_ENDPOINT_DESCRIPTOR Descriptor;
+    PUSBD_PIPE_INFORMATION PipeInfo;
+    ULONG NumInterfaces;
+    SIZE_T Length;
+    SIZE_T HandleLength;
+    BOOLEAN IsAllocated = FALSE;
+    USHORT MaxPacketSize;
+    USHORT wMaxPacketSize;
+    ULONG ix;
+    USBD_STATUS USBDStatus = USBD_STATUS_SUCCESS;
+    NTSTATUS Status;
+
+    DPRINT("USBPORT_OpenInterface: ...\n");
+
+    InterfaceDescriptor = USBPORT_ParseConfigurationDescriptor(ConfigHandle->ConfigurationDescriptor,
+                                                               InterfaceInfo->InterfaceNumber,
+                                                               InterfaceInfo->AlternateSetting,
+                                                               &InterfaceInfo->AlternateSetting);
+
+    NumInterfaces = InterfaceDescriptor->bNumEndpoints;
+
+    Length = sizeof(USBD_INTERFACE_INFORMATION) +
+             (NumInterfaces - 1) * sizeof(USBD_PIPE_INFORMATION);
+
+    if (InterfaceInfo->AlternateSetting && IsSetInterface)
+    {
+        DPRINT1("USBPORT_OpenInterface: InterfaceInfo->AlternateSetting && IsSetInterface !\n");
+    }
+
+    if (*iHandle)
+    {
+        InterfaceHandle = *iHandle;
+    }
+    else
+    {
+        HandleLength = sizeof(USBPORT_INTERFACE_HANDLE) +
+                       (NumInterfaces - 1) * sizeof(USBPORT_PIPE_HANDLE);
+
+        InterfaceHandle = ExAllocatePoolWithTag(NonPagedPool,
+                                                HandleLength,
+                                                USB_PORT_TAG);
+
+        if (!InterfaceHandle)
+        {
+            USBDStatus = USBD_STATUS_INSUFFICIENT_RESOURCES;
+            goto Exit;
+        }
+
+        RtlZeroMemory(InterfaceHandle, HandleLength);
+
+        if (NumInterfaces > 0)
+        {
+            PipeHandle = &InterfaceHandle->PipeHandle[0];
+
+            for (ix = 0; ix < NumInterfaces; ++ix)
+            {
+                PipeHandle->Flags = PIPE_HANDLE_FLAG_CLOSED;
+                PipeHandle->Endpoint = NULL;
+
+                PipeHandle += 1;
+            }
+        }
+
+        IsAllocated = TRUE;
+    }
+
+    InterfaceHandle->AlternateSetting = InterfaceInfo->AlternateSetting;
+
+    RtlCopyMemory(&InterfaceHandle->InterfaceDescriptor,
+                  InterfaceDescriptor,
+                  sizeof(USB_INTERFACE_DESCRIPTOR));
+
+    InterfaceInfo->Class = InterfaceDescriptor->bInterfaceClass;
+    InterfaceInfo->SubClass = InterfaceDescriptor->bInterfaceSubClass;
+    InterfaceInfo->Protocol = InterfaceDescriptor->bInterfaceProtocol;
+    InterfaceInfo->Reserved = 0;
+    InterfaceInfo->NumberOfPipes = InterfaceDescriptor->bNumEndpoints;
+
+    Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor +
+                                            InterfaceDescriptor->bLength);
+
+    if (NumInterfaces)
+    {
+        PipeHandle = &InterfaceHandle->PipeHandle[0];
+
+        for (ix = 0; ix < NumInterfaces; ++ix)
+        {
+            while (Descriptor->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE)
+            {
+                if (Descriptor->bLength == 0)
+                {
+                    break;
+                }
+                else
+                {
+                    Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)Descriptor +
+                                                            Descriptor->bLength);
+                }
+            }
+
+            if (InterfaceInfo->Pipes[ix].PipeFlags & USBD_PF_CHANGE_MAX_PACKET)
+            {
+                Descriptor->wMaxPacketSize = InterfaceInfo->Pipes[ix].MaximumPacketSize;
+            }
+
+            RtlCopyMemory(&PipeHandle->EndpointDescriptor,
+                          Descriptor,
+                          sizeof(USB_ENDPOINT_DESCRIPTOR));
+
+            PipeHandle->Flags = PIPE_HANDLE_FLAG_CLOSED;
+            PipeHandle->PipeFlags = InterfaceInfo->Pipes[ix].PipeFlags;
+            PipeHandle->Endpoint = NULL;
+
+            wMaxPacketSize = Descriptor->wMaxPacketSize;
+
+            /* USB 2.0 Specification, 5.9 High-Speed, High Bandwidth Endpoints */
+            MaxPacketSize = (wMaxPacketSize & 0x7FF) * (((wMaxPacketSize >> 11) & 3) + 1);
+
+            InterfaceInfo->Pipes[ix].EndpointAddress = Descriptor->bEndpointAddress;
+            InterfaceInfo->Pipes[ix].PipeType = Descriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK;
+            InterfaceInfo->Pipes[ix].MaximumPacketSize = MaxPacketSize;
+            InterfaceInfo->Pipes[ix].PipeHandle = (USBD_PIPE_HANDLE)-1;
+            InterfaceInfo->Pipes[ix].Interval = Descriptor->bInterval;
+
+            Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)Descriptor +
+                                                    Descriptor->bLength);
+
+            PipeHandle += 1;
+        }
+    }
+
+    if (USBD_SUCCESS(USBDStatus))
+    {
+        if (NumInterfaces)
+        {
+            PipeInfo = &InterfaceInfo->Pipes[0];
+            PipeHandle = &InterfaceHandle->PipeHandle[0];
+
+            for (ix = 0; ix < NumInterfaces; ++ix)
+            {
+                Status = USBPORT_OpenPipe(FdoDevice,
+                                          DeviceHandle,
+                                          PipeHandle,
+                                          &USBDStatus);
+
+                if (!NT_SUCCESS(Status))
+                    break;
+
+                PipeInfo->PipeHandle = PipeHandle;
+
+                PipeHandle += 1;
+                PipeInfo += 1;
+            }
+
+            USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
+        }
+    }
+
+Exit:
+
+    if (USBD_SUCCESS(USBDStatus))
+    {
+        InterfaceInfo->InterfaceHandle = InterfaceHandle;
+        *iHandle = InterfaceHandle;
+        InterfaceInfo->Length = Length;
+    }
+    else
+    {
+        if (InterfaceHandle)
+        {
+            if (NumInterfaces)
+            {
+                DPRINT1("USBPORT_OpenInterface: USBDStatus - %lx\n", USBDStatus);
+            }
+
+            if (IsAllocated)
+                ExFreePoolWithTag(InterfaceHandle, USB_PORT_TAG);
+        }
+    }
+
+    return USBDStatus;
+}
+
+VOID
+NTAPI
+USBPORT_CloseConfiguration(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+                           IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_CONFIGURATION_HANDLE ConfigHandle;
+    PLIST_ENTRY iHandleList;
+    PUSBPORT_INTERFACE_HANDLE iHandle;
+    ULONG NumEndpoints;
+    PUSBPORT_PIPE_HANDLE PipeHandle;
+
+    DPRINT("USBPORT_CloseConfiguration: ... \n");
+
+    ConfigHandle = DeviceHandle->ConfigHandle;
+
+    if (ConfigHandle)
+    {
+        iHandleList = &ConfigHandle->InterfaceHandleList;
+
+        while (!IsListEmpty(iHandleList))
+        {
+            iHandle = CONTAINING_RECORD(iHandleList->Flink,
+                                        USBPORT_INTERFACE_HANDLE,
+                                        InterfaceLink);
+
+            DPRINT("USBPORT_CloseConfiguration: iHandle - %p\n", iHandle);
+
+            RemoveHeadList(iHandleList);
+
+            NumEndpoints = iHandle->InterfaceDescriptor.bNumEndpoints;
+
+            PipeHandle = &iHandle->PipeHandle[0];
+
+            while (NumEndpoints > 0)
+            {
+                USBPORT_ClosePipe(DeviceHandle, FdoDevice, PipeHandle);
+                PipeHandle += 1;
+                --NumEndpoints;
+            }
+
+            ExFreePoolWithTag(iHandle, USB_PORT_TAG);
+        }
+
+        ExFreePoolWithTag(ConfigHandle, USB_PORT_TAG);
+        DeviceHandle->ConfigHandle = NULL;
+    }
+}
+
+NTSTATUS
+NTAPI
+USBPORT_InitInterfaceInfo(IN PUSBD_INTERFACE_INFORMATION InterfaceInfo,
+                          IN PUSBPORT_CONFIGURATION_HANDLE ConfigHandle)
+{
+    PUSB_INTERFACE_DESCRIPTOR Descriptor;
+    PUSBD_PIPE_INFORMATION Pipe;
+    USHORT Length;
+    ULONG PipeFlags;
+    ULONG NumberOfPipes;
+    USBD_STATUS USBDStatus = USBD_STATUS_SUCCESS;
+
+    DPRINT("USBPORT_InitInterfaceInfo: InterfaceInfo - %p, ConfigHandle - %p\n",
+           InterfaceInfo,
+           ConfigHandle);
+
+    Descriptor = USBPORT_ParseConfigurationDescriptor(ConfigHandle->ConfigurationDescriptor,
+                                                      InterfaceInfo->InterfaceNumber,
+                                                      InterfaceInfo->AlternateSetting,
+                                                      &InterfaceInfo->AlternateSetting);
+
+    Length = sizeof(USBD_INTERFACE_INFORMATION) +
+             sizeof(USBD_PIPE_INFORMATION);
+
+    if (Descriptor)
+    {
+        NumberOfPipes = Descriptor->bNumEndpoints;
+
+        Length = sizeof(USBD_INTERFACE_INFORMATION) +
+                 (NumberOfPipes - 1) * sizeof(USBD_PIPE_INFORMATION);
+
+        if (InterfaceInfo->Length >= Length)
+        {
+            InterfaceInfo->Class = 0;
+            InterfaceInfo->SubClass = 0;
+            InterfaceInfo->Protocol = 0;
+            InterfaceInfo->Reserved = 0;
+            InterfaceInfo->InterfaceHandle = 0;
+            InterfaceInfo->NumberOfPipes = NumberOfPipes;
+
+            Pipe = InterfaceInfo->Pipes;
+
+            while (NumberOfPipes > 0)
+            {
+                Pipe->EndpointAddress = 0;
+                Pipe->Interval = 0;
+                Pipe->PipeType = 0;
+                Pipe->PipeHandle = 0;
+
+                PipeFlags = Pipe->PipeFlags;
+
+                if (PipeFlags & ~USBD_PF_VALID_MASK)
+                    USBDStatus = USBD_STATUS_INVALID_PIPE_FLAGS;
+
+                if (!(PipeFlags & USBD_PF_CHANGE_MAX_PACKET))
+                    Pipe->MaximumPacketSize = 0;
+
+                Pipe += 1;
+                --NumberOfPipes;
+            }
+        }
+        else
+        {
+            USBDStatus = USBD_STATUS_BUFFER_TOO_SMALL;
+        }
+    }
+    else
+    {
+        USBDStatus = USBD_STATUS_INTERFACE_NOT_FOUND;
+    }
+
+    InterfaceInfo->Length = Length;
+    return USBDStatus;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_HandleSelectConfiguration(IN PDEVICE_OBJECT FdoDevice,
+                                  IN PIRP Irp,
+                                  IN PURB Urb)
+{
+    PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor;
+    PUSBPORT_DEVICE_HANDLE DeviceHandle;
+    PUSBPORT_CONFIGURATION_HANDLE ConfigHandle = NULL;
+    PUSBD_INTERFACE_INFORMATION InterfaceInfo;
+    PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
+    ULONG iNumber;
+    ULONG ix;
+    USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
+    NTSTATUS Status;
+    USBD_STATUS USBDStatus;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT("USBPORT_HandleSelectConfiguration: ConfigDescriptor %p\n",
+           Urb->UrbSelectConfiguration.ConfigurationDescriptor);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
+                          Executive,
+                          KernelMode,
+                          FALSE,
+                          NULL);
+
+    DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
+    ConfigDescriptor = Urb->UrbSelectConfiguration.ConfigurationDescriptor;
+
+    if (!ConfigDescriptor)
+    {
+        DPRINT("USBPORT_HandleSelectConfiguration: ConfigDescriptor == NULL\n");
+
+        RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+
+        SetupPacket.bmRequestType.B = 0;
+        SetupPacket.bRequest = USB_REQUEST_SET_CONFIGURATION;
+        SetupPacket.wValue.W = 0;
+        SetupPacket.wIndex.W = 0;
+        SetupPacket.wLength = 0;
+
+        USBPORT_SendSetupPacket(DeviceHandle,
+                                FdoDevice,
+                                &SetupPacket,
+                                NULL,
+                                0,
+                                NULL,
+                                NULL);
+
+        Status = USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_SUCCESS);
+        goto Exit;
+    }
+
+    USBPORT_DumpingConfiguration(ConfigDescriptor);
+
+    InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
+
+    iNumber = 0;
+
+    do
+    {
+        ++iNumber;
+        InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)
+                        ((ULONG_PTR)InterfaceInfo +
+                         InterfaceInfo->Length);
+    }
+    while ((ULONG_PTR)InterfaceInfo < (ULONG_PTR)Urb + Urb->UrbHeader.Length);
+
+    if ((iNumber <= 0) || (iNumber != ConfigDescriptor->bNumInterfaces))
+    {
+        Status = USBPORT_USBDStatusToNtStatus(Urb,
+                                              USBD_STATUS_INVALID_CONFIGURATION_DESCRIPTOR);
+        goto Exit;
+    }
+
+    ConfigHandle = ExAllocatePoolWithTag(NonPagedPool,
+                                         ConfigDescriptor->wTotalLength + sizeof(USBPORT_CONFIGURATION_HANDLE),
+                                         USB_PORT_TAG);
+
+    if (!ConfigHandle)
+    {
+        Status = USBPORT_USBDStatusToNtStatus(Urb,
+                                              USBD_STATUS_INSUFFICIENT_RESOURCES);
+        goto Exit;
+    }
+
+    RtlZeroMemory(ConfigHandle,
+                  ConfigDescriptor->wTotalLength + sizeof(USBPORT_CONFIGURATION_HANDLE));
+
+    InitializeListHead(&ConfigHandle->InterfaceHandleList);
+
+    ConfigHandle->ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)(ConfigHandle + 1);
+
+    RtlCopyMemory(ConfigHandle->ConfigurationDescriptor,
+                  ConfigDescriptor,
+                  ConfigDescriptor->wTotalLength);
+
+    RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+
+    SetupPacket.bmRequestType.B = 0;
+    SetupPacket.bRequest = USB_REQUEST_SET_CONFIGURATION;
+    SetupPacket.wValue.W = ConfigDescriptor->bConfigurationValue;
+    SetupPacket.wIndex.W = 0;
+    SetupPacket.wLength = 0;
+
+    USBPORT_SendSetupPacket(DeviceHandle,
+                            FdoDevice,
+                            &SetupPacket,
+                            NULL,
+                            0,
+                            NULL,
+                            &USBDStatus);
+
+    if (USBD_ERROR(USBDStatus))
+    {
+        Status = USBPORT_USBDStatusToNtStatus(Urb,
+                                              USBD_STATUS_SET_CONFIG_FAILED);
+        goto Exit;
+    }
+
+    if (iNumber <= 0)
+    {
+        Status = USBPORT_USBDStatusToNtStatus(Urb,
+                                              USBD_STATUS_SUCCESS);
+
+        goto Exit;
+    }
+
+    InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
+
+    for (ix = 0; ix < iNumber; ++ix)
+    {
+        USBDStatus = USBPORT_InitInterfaceInfo(InterfaceInfo,
+                                               ConfigHandle);
+
+        InterfaceHandle = NULL;
+
+        if (USBD_SUCCESS(USBDStatus))
+        {
+            USBDStatus = USBPORT_OpenInterface(Urb,
+                                               DeviceHandle,
+                                               FdoDevice,
+                                               ConfigHandle,
+                                               InterfaceInfo,
+                                               &InterfaceHandle,
+                                               TRUE);
+        }
+
+        if (InterfaceHandle)
+        {
+            InsertTailList(&ConfigHandle->InterfaceHandleList,
+                           &InterfaceHandle->InterfaceLink);
+        }
+
+        if (USBD_ERROR(USBDStatus))
+            break;
+
+        InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)
+                         ((ULONG_PTR)InterfaceInfo +
+                          InterfaceInfo->Length);
+    }
+
+    if (ix >= iNumber)
+    {
+        Status = USBPORT_USBDStatusToNtStatus(Urb,
+                                              USBD_STATUS_SUCCESS);
+    }
+    else
+    {
+        Status = USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
+    }
+
+Exit:
+
+    if (NT_SUCCESS(Status))
+    {
+        Urb->UrbSelectConfiguration.ConfigurationHandle = ConfigHandle;
+        DeviceHandle->ConfigHandle = ConfigHandle;
+    }
+    else
+    {
+        DPRINT1("USBPORT_HandleSelectConfiguration: Status %x\n", Status);
+    }
+
+    KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
+                       LOW_REALTIME_PRIORITY,
+                       1,
+                       FALSE);
+
+    return Status;
+}
+
+VOID
+NTAPI
+USBPORT_AddDeviceHandle(IN PDEVICE_OBJECT FdoDevice,
+                        IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT("USBPORT_AddDeviceHandle: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    InsertTailList(&FdoExtension->DeviceHandleList,
+                   &DeviceHandle->DeviceHandleLink);
+}
+
+VOID
+NTAPI
+USBPORT_RemoveDeviceHandle(IN PDEVICE_OBJECT FdoDevice,
+                           IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    KIRQL OldIrql;
+
+    DPRINT("USBPORT_RemoveDeviceHandle \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    KeAcquireSpinLock(&FdoExtension->DeviceHandleSpinLock, &OldIrql);
+    RemoveEntryList(&DeviceHandle->DeviceHandleLink);
+    KeReleaseSpinLock(&FdoExtension->DeviceHandleSpinLock, OldIrql);
+}
+
+BOOLEAN
+NTAPI
+USBPORT_ValidateDeviceHandle(IN PDEVICE_OBJECT FdoDevice,
+                             IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    KIRQL OldIrql;
+    PLIST_ENTRY HandleList;
+    PUSBPORT_DEVICE_HANDLE CurrentHandle;
+    BOOLEAN Result = FALSE;
+
+    //DPRINT("USBPORT_ValidateDeviceHandle: DeviceHandle - %p\n", DeviceHandle \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    KeAcquireSpinLock(&FdoExtension->DeviceHandleSpinLock, &OldIrql);
+    if (DeviceHandle)
+    {
+        HandleList = FdoExtension->DeviceHandleList.Flink;
+
+        while (HandleList != &FdoExtension->DeviceHandleList)
+        {
+            CurrentHandle = CONTAINING_RECORD(HandleList,
+                                              USBPORT_DEVICE_HANDLE,
+                                              DeviceHandleLink);
+
+            if (CurrentHandle == DeviceHandle)
+            {
+                Result = TRUE;
+                break;
+            }
+
+            HandleList = HandleList->Flink;
+        }
+    }
+    KeReleaseSpinLock(&FdoExtension->DeviceHandleSpinLock, OldIrql);
+
+    return Result;
+}
+
+BOOLEAN
+NTAPI
+USBPORT_DeviceHasTransfers(IN PDEVICE_OBJECT FdoDevice,
+                           IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
+{
+    PLIST_ENTRY PipeHandleList;
+    PUSBPORT_PIPE_HANDLE PipeHandle;
+
+    DPRINT("USBPORT_DeviceHasTransfers: ... \n");
+
+    PipeHandleList = DeviceHandle->PipeHandleList.Flink;
+
+    while (PipeHandleList != &DeviceHandle->PipeHandleList)
+    {
+        PipeHandle = CONTAINING_RECORD(PipeHandleList,
+                                       USBPORT_PIPE_HANDLE,
+                                       PipeLink);
+
+        PipeHandleList = PipeHandleList->Flink;
+
+        if (!(PipeHandle->Flags & PIPE_HANDLE_FLAG_NULL_PACKET_SIZE) && 
+            USBPORT_EndpointHasQueuedTransfers(FdoDevice, PipeHandle->Endpoint, NULL))
+        {
+            return TRUE;
+        }
+    }
+
+    return FALSE;
+}
+
+VOID
+NTAPI
+USBPORT_AbortTransfers(IN PDEVICE_OBJECT FdoDevice,
+                       IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
+{
+    PLIST_ENTRY HandleList;
+    PUSBPORT_PIPE_HANDLE PipeHandle;
+    BOOLEAN Result;
+
+    DPRINT("USBPORT_AbortAllTransfers: ... \n");
+
+    HandleList = DeviceHandle->PipeHandleList.Flink;
+
+    while (HandleList != &DeviceHandle->PipeHandleList)
+    {
+        PipeHandle = CONTAINING_RECORD(HandleList,
+                                       USBPORT_PIPE_HANDLE,
+                                       PipeLink);
+
+        HandleList = HandleList->Flink;
+
+        if (!(PipeHandle->Flags & DEVICE_HANDLE_FLAG_ROOTHUB))
+        {
+            PipeHandle->Endpoint->Flags |= ENDPOINT_FLAG_ABORTING;
+
+            USBPORT_AbortEndpoint(FdoDevice, PipeHandle->Endpoint, NULL);
+            USBPORT_FlushMapTransfers(FdoDevice);
+        }
+    }
+
+    while (TRUE)
+    {
+        Result = USBPORT_DeviceHasTransfers(FdoDevice, DeviceHandle);
+
+        if (!Result)
+            break;
+
+        USBPORT_Wait(FdoDevice, 100);
+    }
+}
+
+NTSTATUS
+NTAPI
+USBPORT_CreateDevice(IN OUT PUSB_DEVICE_HANDLE *pUsbdDeviceHandle,
+                     IN PDEVICE_OBJECT FdoDevice,
+                     IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
+                     IN USHORT PortStatus,
+                     IN USHORT Port)
+{
+    PUSBPORT_DEVICE_HANDLE DeviceHandle;
+    PUSBPORT_PIPE_HANDLE PipeHandle;
+    BOOL IsOpenedPipe;
+    PVOID DeviceDescriptor;
+    USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
+    SIZE_T TransferedLen;
+    SIZE_T DescriptorMinSize;
+    UCHAR MaxPacketSize;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    NTSTATUS Status;
+
+    DPRINT("USBPORT_CreateDevice: PortStatus - %p, Port - %x\n",
+           PortStatus,
+           Port);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
+                          Executive,
+                          KernelMode,
+                          FALSE,
+                          NULL);
+
+    if (!USBPORT_ValidateDeviceHandle(FdoDevice, HubDeviceHandle))
+    {
+        KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
+                           LOW_REALTIME_PRIORITY,
+                           1,
+                           FALSE);
+
+        DPRINT1("USBPORT_CreateDevice: Not valid hub DeviceHandle\n");
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
+
+    if (FdoExtension->MiniPortInterface->Packet.MiniPortFlags & USB_MINIPORT_FLAGS_USB2 &&
+        !(PortStatus & USB_PORT_STATUS_HIGH_SPEED))
+    {
+        DPRINT1("USBPORT_CreateDevice: USB1 device connected to USB2 port. FIXME: Transaction Translator.\n");
+        DbgBreakPoint();
+    }
+
+    KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
+                       LOW_REALTIME_PRIORITY,
+                       1,
+                       FALSE);
+
+    DeviceHandle = ExAllocatePoolWithTag(NonPagedPool,
+                                         sizeof(USBPORT_DEVICE_HANDLE),
+                                         USB_PORT_TAG);
+
+    if (!DeviceHandle)
+    {
+        DPRINT1("USBPORT_CreateDevice: Not allocated DeviceHandle\n");
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    RtlZeroMemory(DeviceHandle, sizeof(USBPORT_DEVICE_HANDLE));
+
+    *pUsbdDeviceHandle = NULL;
+
+    DeviceHandle->PortNumber = Port;
+    DeviceHandle->HubDeviceHandle = HubDeviceHandle;
+
+    if (PortStatus & USB_PORT_STATUS_LOW_SPEED)
+    {
+        DeviceHandle->DeviceSpeed = UsbLowSpeed;
+    }
+    else if (PortStatus & USB_PORT_STATUS_HIGH_SPEED)
+    {
+        DeviceHandle->DeviceSpeed = UsbHighSpeed;
+    }
+    else
+    {
+        DeviceHandle->DeviceSpeed = UsbFullSpeed;
+    }
+
+    KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
+                          Executive,
+                          KernelMode,
+                          FALSE,
+                          NULL);
+
+    PipeHandle = &DeviceHandle->PipeHandle;
+
+    PipeHandle->Flags = PIPE_HANDLE_FLAG_CLOSED;
+
+    PipeHandle->EndpointDescriptor.bLength = sizeof(PipeHandle->EndpointDescriptor);
+    PipeHandle->EndpointDescriptor.bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE;
+
+    if (DeviceHandle->DeviceSpeed == UsbLowSpeed)
+    {
+        PipeHandle->EndpointDescriptor.wMaxPacketSize = 8;
+    }
+    else
+    {
+        PipeHandle->EndpointDescriptor.wMaxPacketSize = USB_DEFAULT_MAX_PACKET;
+    }
+
+    InitializeListHead(&DeviceHandle->PipeHandleList);
+
+    Status = USBPORT_OpenPipe(FdoDevice,
+                              DeviceHandle,
+                              PipeHandle,
+                              NULL);
+
+    IsOpenedPipe = NT_SUCCESS(Status);
+
+    if (NT_ERROR(Status))
+    {
+        DPRINT1("USBPORT_CreateDevice: USBPORT_OpenPipe return - %lx\n", Status);
+
+        KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
+                           LOW_REALTIME_PRIORITY,
+                           1,
+                           FALSE);
+
+        ExFreePoolWithTag(DeviceHandle, USB_PORT_TAG);
+
+        return Status;
+    }
+
+    DeviceDescriptor = ExAllocatePoolWithTag(NonPagedPool,
+                                             USB_DEFAULT_MAX_PACKET,
+                                             USB_PORT_TAG);
+
+    if (!DeviceDescriptor)
+    {
+        DPRINT1("USBPORT_CreateDevice: Not allocated DeviceDescriptor\n");
+        goto ErrorExit;
+    }
+
+    RtlZeroMemory(DeviceDescriptor, USB_DEFAULT_MAX_PACKET);
+    RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+
+    SetupPacket.bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
+    SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
+    SetupPacket.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
+    SetupPacket.wLength = USB_DEFAULT_MAX_PACKET;
+
+    TransferedLen = 0;
+
+    Status = USBPORT_SendSetupPacket(DeviceHandle,
+                                     FdoDevice,
+                                     &SetupPacket,
+                                     DeviceDescriptor,
+                                     USB_DEFAULT_MAX_PACKET,
+                                     &TransferedLen,
+                                     NULL);
+
+    RtlCopyMemory(&DeviceHandle->DeviceDescriptor,
+                  DeviceDescriptor,
+                  sizeof(USB_DEVICE_DESCRIPTOR));
+
+    ExFreePoolWithTag(DeviceDescriptor, USB_PORT_TAG);
+
+    DescriptorMinSize = RTL_SIZEOF_THROUGH_FIELD(USB_DEVICE_DESCRIPTOR,
+                                                 bMaxPacketSize0);
+
+    if ((TransferedLen == DescriptorMinSize) && !NT_SUCCESS(Status))
+    {
+        Status = STATUS_SUCCESS;
+    }
+
+    if (NT_SUCCESS(Status) && (TransferedLen >= DescriptorMinSize))
+    {
+        if ((DeviceHandle->DeviceDescriptor.bLength >= sizeof(USB_DEVICE_DESCRIPTOR)) &&
+            (DeviceHandle->DeviceDescriptor.bDescriptorType == USB_DEVICE_DESCRIPTOR_TYPE))
+        {
+            MaxPacketSize = DeviceHandle->DeviceDescriptor.bMaxPacketSize0;
+
+            if (MaxPacketSize == 8 ||
+                MaxPacketSize == 16 ||
+                MaxPacketSize == 32 ||
+                MaxPacketSize == 64)
+            {
+                USBPORT_AddDeviceHandle(FdoDevice, DeviceHandle);
+
+                *pUsbdDeviceHandle = DeviceHandle;
+
+                KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
+                                   LOW_REALTIME_PRIORITY,
+                                   1,
+                                   FALSE);
+
+                return Status;
+            }
+        }
+    }
+
+    DPRINT1("USBPORT_CreateDevice: ERROR!!! TransferedLen - %x, Status - %lx\n",
+            TransferedLen,
+            Status);
+
+ErrorExit:
+
+    // FIXME: if Transaction Translator
+
+    Status = STATUS_DEVICE_DATA_ERROR;
+
+    if (IsOpenedPipe)
+    {
+        USBPORT_ClosePipe(DeviceHandle, FdoDevice, PipeHandle);
+    }
+
+    KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
+                       LOW_REALTIME_PRIORITY,
+                       1,
+                       FALSE);
+
+    ExFreePoolWithTag(DeviceHandle, USB_PORT_TAG);
+
+    return Status;
+}
+
+ULONG
+NTAPI
+USBPORT_AllocateUsbAddress(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    ULONG BitMapIdx;
+    ULONG BitNumber;
+    ULONG ix;
+
+    DPRINT("USBPORT_AllocateUsbAddress \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    for (ix = 0; ix < 4; ++ix)
+    {
+        BitMapIdx = 1;
+
+        for (BitNumber = 0; BitNumber < 32; ++BitNumber)
+        {
+            if (!(FdoExtension->UsbAddressBitMap[ix] & BitMapIdx))
+            {
+                FdoExtension->UsbAddressBitMap[ix] |= BitMapIdx;
+                return 32 * ix + BitNumber;
+            }
+
+            BitMapIdx <<= 2;
+        }
+    }
+
+    return 0;
+}
+
+VOID
+NTAPI
+USBPORT_FreeUsbAddress(IN PDEVICE_OBJECT FdoDevice,
+                       IN USHORT DeviceAddress)
+{
+    PUSBPORT_DEVICE_EXTENSION  FdoExtension;
+    ULONG ix;
+    ULONG BitMapIdx;
+    ULONG BitNumber;
+    USHORT CurrentAddress;
+
+    DPRINT("USBPORT_FreeUsbAddress: DeviceAddress - %x\n", DeviceAddress);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    for (ix = 0; ix < 4; ++ix)
+    {
+        BitMapIdx = 1;
+        CurrentAddress = 32 * ix;
+
+        for (BitNumber = 0; BitNumber < 32; ++BitNumber)
+        {
+            if (CurrentAddress == DeviceAddress)
+            {
+                FdoExtension->UsbAddressBitMap[ix] &= ~BitMapIdx;
+                return;
+            }
+
+            BitMapIdx <<= 2;
+            CurrentAddress++;
+        }
+    }
+}
+
+NTSTATUS
+NTAPI
+USBPORT_InitializeDevice(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+                         IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_ENDPOINT Endpoint;
+    USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+    ULONG TransferedLen;
+    USHORT DeviceAddress = 0;
+    UCHAR MaxPacketSize;
+    NTSTATUS Status;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT("USBPORT_InitializeDevice: ... \n");
+
+    ASSERT(DeviceHandle != NULL);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
+                          Executive,
+                          KernelMode,
+                          FALSE,
+                          NULL);
+
+    DeviceAddress = USBPORT_AllocateUsbAddress(FdoDevice);
+    ASSERT(DeviceHandle->DeviceAddress == USB_DEFAULT_DEVICE_ADDRESS);
+
+    RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+
+    CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS;
+    CtrlSetup.wValue.W = DeviceAddress;
+
+    Status = USBPORT_SendSetupPacket(DeviceHandle,
+                                     FdoDevice,
+                                     &CtrlSetup,
+                                     NULL,
+                                     0,
+                                     NULL,
+                                     NULL);
+
+    DPRINT("USBPORT_InitializeDevice: DeviceAddress - %x. SendSetupPacket Status - %x\n",
+           DeviceAddress,
+           Status);
+
+    if (!NT_SUCCESS(Status))
+        goto ExitError;
+
+    DeviceHandle->DeviceAddress = DeviceAddress;
+    Endpoint = DeviceHandle->PipeHandle.Endpoint;
+
+    Endpoint->EndpointProperties.TotalMaxPacketSize = DeviceHandle->DeviceDescriptor.bMaxPacketSize0;
+    Endpoint->EndpointProperties.DeviceAddress = DeviceAddress;
+
+    Status = USBPORT_ReopenPipe(FdoDevice, Endpoint);
+
+    if (!NT_SUCCESS(Status))
+        goto ExitError;
+
+    USBPORT_Wait(FdoDevice, 10);
+
+    RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+
+    CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
+    CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
+    CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR);
+    CtrlSetup.bmRequestType.B = 0x80;
+
+    Status = USBPORT_SendSetupPacket(DeviceHandle,
+                                     FdoDevice,
+                                     &CtrlSetup,
+                                     &DeviceHandle->DeviceDescriptor,
+                                     sizeof(USB_DEVICE_DESCRIPTOR),
+                                     &TransferedLen,
+                                     NULL);
+
+    if (NT_SUCCESS(Status))
+    {
+        ASSERT(TransferedLen == sizeof(USB_DEVICE_DESCRIPTOR));
+        ASSERT(DeviceHandle->DeviceDescriptor.bLength >= sizeof(USB_DEVICE_DESCRIPTOR));
+        ASSERT(DeviceHandle->DeviceDescriptor.bDescriptorType == USB_DEVICE_DESCRIPTOR_TYPE);
+
+        MaxPacketSize = DeviceHandle->DeviceDescriptor.bMaxPacketSize0;
+
+        ASSERT((MaxPacketSize == 8) ||
+               (MaxPacketSize == 16) ||
+               (MaxPacketSize == 32) ||
+               (MaxPacketSize == 64));
+    }
+    else
+    {
+ExitError:
+        DPRINT1("USBPORT_InitializeDevice: ExitError. Status - %x\n", Status);
+    }
+
+    KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
+                       LOW_REALTIME_PRIORITY,
+                       1,
+                       FALSE);
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_GetUsbDescriptor(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+                         IN PDEVICE_OBJECT FdoDevice,
+                         IN UCHAR Type,
+                         IN PUCHAR ConfigDesc,
+                         IN PULONG ConfigDescSize)
+{
+    USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
+
+    DPRINT("USBPORT_GetUsbDescriptor: Type - %x\n");
+
+    RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+
+    SetupPacket.bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
+    SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
+    SetupPacket.wValue.HiByte = Type;
+    SetupPacket.wLength = (USHORT)*ConfigDescSize;
+
+    return USBPORT_SendSetupPacket(DeviceHandle,
+                                   FdoDevice,
+                                   &SetupPacket,
+                                   ConfigDesc,
+                                   *ConfigDescSize,
+                                   ConfigDescSize,
+                                   NULL);
+}
+
+PUSBPORT_INTERFACE_HANDLE
+NTAPI
+USBPORT_GetInterfaceHandle(IN PUSBPORT_CONFIGURATION_HANDLE ConfigurationHandle,
+                           IN UCHAR InterfaceNumber)
+{
+    PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
+    PLIST_ENTRY iHandleList;
+    UCHAR InterfaceNum;
+
+    DPRINT("USBPORT_GetInterfaceHandle: ConfigurationHandle - %p, InterfaceNumber - %p\n",
+           ConfigurationHandle,
+           InterfaceNumber);
+
+    iHandleList = ConfigurationHandle->InterfaceHandleList.Flink;
+
+    while (iHandleList &&
+           (iHandleList != &ConfigurationHandle->InterfaceHandleList))
+    {
+        InterfaceHandle = CONTAINING_RECORD(iHandleList,
+                                            USBPORT_INTERFACE_HANDLE,
+                                            InterfaceLink);
+
+        InterfaceNum = InterfaceHandle->InterfaceDescriptor.bInterfaceNumber;
+
+        if (InterfaceNum == InterfaceNumber)
+            return InterfaceHandle;
+
+        iHandleList = InterfaceHandle->InterfaceLink.Flink;
+    }
+
+    return NULL;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_HandleSelectInterface(IN PDEVICE_OBJECT FdoDevice,
+                              IN PIRP Irp,
+                              IN PURB Urb)
+{
+    PUSBPORT_DEVICE_HANDLE DeviceHandle;
+    PUSBPORT_CONFIGURATION_HANDLE ConfigurationHandle;
+    PUSBD_INTERFACE_INFORMATION Interface;
+    PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
+    PUSBPORT_INTERFACE_HANDLE iHandle;
+    PUSBPORT_PIPE_HANDLE PipeHandle;
+    USBD_STATUS USBDStatus;
+    USHORT Length;
+    ULONG ix;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT("USBPORT_HandleSelectInterface: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
+                          Executive,
+                          KernelMode,
+                          FALSE,
+                          NULL);
+
+    ConfigurationHandle = Urb->UrbSelectInterface.ConfigurationHandle;
+
+    Interface = &Urb->UrbSelectInterface.Interface;
+
+    Length = Interface->Length + sizeof(USBD_PIPE_INFORMATION);
+    Urb->UrbHeader.Length = Length;
+
+    USBDStatus = USBPORT_InitInterfaceInfo(Interface, ConfigurationHandle);
+
+    if (USBDStatus)
+    {
+        Interface->InterfaceHandle = (USBD_INTERFACE_HANDLE)-1;
+        return USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
+    }
+
+    DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
+
+    InterfaceHandle = USBPORT_GetInterfaceHandle(ConfigurationHandle,
+                                                 Interface->InterfaceNumber);
+
+    if (InterfaceHandle)
+    {
+        RemoveEntryList(&InterfaceHandle->InterfaceLink);
+
+        if (InterfaceHandle->InterfaceDescriptor.bNumEndpoints)
+        {
+            PipeHandle = &InterfaceHandle->PipeHandle[0];
+
+            for (ix = 0;
+                 ix < InterfaceHandle->InterfaceDescriptor.bNumEndpoints;
+                 ix++)
+            {
+                USBPORT_ClosePipe(DeviceHandle, FdoDevice, PipeHandle);
+                PipeHandle += 1;
+            }
+        }
+    }
+
+    iHandle = 0;
+
+    USBDStatus = USBPORT_OpenInterface(Urb,
+                                       DeviceHandle,
+                                       FdoDevice,
+                                       ConfigurationHandle,
+                                       Interface,
+                                       &iHandle,
+                                       1);
+
+    if (USBDStatus)
+    {
+        Interface->InterfaceHandle = (USBD_INTERFACE_HANDLE)-1;
+    }
+    else
+    {
+        if (InterfaceHandle)
+            ExFreePoolWithTag(InterfaceHandle, USB_PORT_TAG);
+
+        Interface->InterfaceHandle = iHandle;
+
+        InsertTailList(&ConfigurationHandle->InterfaceHandleList,
+                       &iHandle->InterfaceLink);
+    }
+
+    KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
+                       LOW_REALTIME_PRIORITY,
+                       1,
+                       FALSE);
+
+    return USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
+}
+
+NTSTATUS
+NTAPI
+USBPORT_RemoveDevice(IN PDEVICE_OBJECT FdoDevice,
+                     IN OUT PUSBPORT_DEVICE_HANDLE DeviceHandle,
+                     IN ULONG Flags)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT("USBPORT_RemoveDevice: DeviceHandle - %p, Flags - %x\n",
+           DeviceHandle,
+           Flags);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    if ((Flags & USBD_KEEP_DEVICE_DATA) ||
+        (Flags & USBD_MARK_DEVICE_BUSY))
+    {
+        return STATUS_SUCCESS;
+    }
+
+    KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
+                          Executive,
+                          KernelMode,
+                          FALSE,
+                          NULL);
+
+    if (!USBPORT_ValidateDeviceHandle(FdoDevice, DeviceHandle))
+    {
+        KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
+                           LOW_REALTIME_PRIORITY,
+                           1,
+                           FALSE);
+
+        DPRINT1("USBPORT_RemoveDevice: Not valid device handle\n");
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
+
+    USBPORT_RemoveDeviceHandle(FdoDevice, DeviceHandle);
+
+    DeviceHandle->Flags |= DEVICE_HANDLE_FLAG_REMOVED;
+
+    USBPORT_AbortTransfers(FdoDevice, DeviceHandle);
+
+    DPRINT("USBPORT_RemoveDevice: DeviceHandleLock - %x\n",
+           DeviceHandle->DeviceHandleLock);
+
+    while (InterlockedDecrement(&DeviceHandle->DeviceHandleLock) >= 0)
+    {
+        InterlockedIncrement(&DeviceHandle->DeviceHandleLock);
+        USBPORT_Wait(FdoDevice, 100);
+    }
+
+    DPRINT("USBPORT_RemoveDevice: DeviceHandleLock ok\n");
+
+    if (DeviceHandle->ConfigHandle)
+    {
+        USBPORT_CloseConfiguration(DeviceHandle, FdoDevice);
+    }
+
+    USBPORT_ClosePipe(DeviceHandle, FdoDevice, &DeviceHandle->PipeHandle);
+
+    if (DeviceHandle->DeviceAddress)
+    {
+        USBPORT_FreeUsbAddress(FdoDevice, DeviceHandle->DeviceAddress);
+    }
+
+    KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
+                       LOW_REALTIME_PRIORITY,
+                       1,
+                       FALSE);
+
+    if (!(DeviceHandle->Flags & DEVICE_HANDLE_FLAG_ROOTHUB))
+    {
+        ExFreePoolWithTag(DeviceHandle, USB_PORT_TAG);
+    }
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_RestoreDevice(IN PDEVICE_OBJECT FdoDevice,
+                      IN OUT PUSBPORT_DEVICE_HANDLE OldDeviceHandle,
+                      IN OUT PUSBPORT_DEVICE_HANDLE NewDeviceHandle)
+{
+    PUSBPORT_DEVICE_EXTENSION  FdoExtension;
+    PLIST_ENTRY iHandleList;
+    PUSBPORT_ENDPOINT Endpoint;
+    ULONG EndpointRequirements[2] = {0};
+    USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
+    NTSTATUS Status = STATUS_SUCCESS;
+    USBD_STATUS USBDStatus;
+    KIRQL OldIrql;
+    PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
+    PUSBPORT_PIPE_HANDLE PipeHandle;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+
+    DPRINT("USBPORT_RestoreDevice: OldDeviceHandle - %p, NewDeviceHandle - %p\n",
+           OldDeviceHandle,
+           NewDeviceHandle);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
+                          Executive,
+                          KernelMode,
+                          FALSE,
+                          NULL);
+
+    if (!USBPORT_ValidateDeviceHandle(FdoDevice, OldDeviceHandle))
+    {
+        KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
+                           LOW_REALTIME_PRIORITY,
+                           1,
+                           FALSE);
+
+#ifndef NDEBUG
+        DPRINT("USBPORT_RestoreDevice: OldDeviceHandle not valid\n");
+        DbgBreakPoint();
+#endif
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
+
+    if (!USBPORT_ValidateDeviceHandle(FdoDevice, NewDeviceHandle))
+    {
+        KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
+                           LOW_REALTIME_PRIORITY,
+                           1,
+                           FALSE);
+#ifndef NDEBUG
+        DPRINT("USBPORT_RestoreDevice: NewDeviceHandle not valid\n");
+        DbgBreakPoint();
+#endif
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
+
+    USBPORT_RemoveDeviceHandle(FdoDevice, OldDeviceHandle);
+    USBPORT_AbortTransfers(FdoDevice, OldDeviceHandle);
+
+    while (InterlockedDecrement(&OldDeviceHandle->DeviceHandleLock) >= 0)
+    {
+        InterlockedIncrement(&OldDeviceHandle->DeviceHandleLock);
+        USBPORT_Wait(FdoDevice, 100);
+    }
+
+    if (sizeof(USB_DEVICE_DESCRIPTOR) == RtlCompareMemory(&NewDeviceHandle->DeviceDescriptor,
+                                                          &OldDeviceHandle->DeviceDescriptor,
+                                                          sizeof(USB_DEVICE_DESCRIPTOR)))
+    {
+        NewDeviceHandle->ConfigHandle = OldDeviceHandle->ConfigHandle;
+
+        if (OldDeviceHandle->ConfigHandle)
+        {
+            RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+
+            SetupPacket.bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
+            SetupPacket.bRequest = USB_REQUEST_SET_CONFIGURATION;
+            SetupPacket.wValue.W = OldDeviceHandle->ConfigHandle->ConfigurationDescriptor->bConfigurationValue;
+            SetupPacket.wIndex.W = 0;
+            SetupPacket.wLength = 0;
+
+            USBPORT_SendSetupPacket(NewDeviceHandle,
+                                    FdoDevice,
+                                    &SetupPacket,
+                                    NULL,
+                                    0,
+                                    NULL,
+                                    &USBDStatus);
+
+            if (USBD_ERROR(USBDStatus))
+                Status = USBPORT_USBDStatusToNtStatus(NULL, USBDStatus);
+
+            if (NT_SUCCESS(Status))
+            {
+                iHandleList = NewDeviceHandle->ConfigHandle->InterfaceHandleList.Flink;
+
+                while (iHandleList &&
+                       iHandleList != &NewDeviceHandle->ConfigHandle->InterfaceHandleList)
+                {
+                    InterfaceHandle = CONTAINING_RECORD(iHandleList,
+                                                        USBPORT_INTERFACE_HANDLE,
+                                                        InterfaceLink);
+
+                    if (InterfaceHandle->AlternateSetting)
+                    {
+                        RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+
+                        SetupPacket.bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
+                        SetupPacket.bmRequestType.Type = BMREQUEST_STANDARD;
+                        SetupPacket.bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
+
+                        SetupPacket.bRequest = USB_REQUEST_SET_INTERFACE;
+                        SetupPacket.wValue.W = InterfaceHandle->InterfaceDescriptor.bAlternateSetting;
+                        SetupPacket.wIndex.W = InterfaceHandle->InterfaceDescriptor.bInterfaceNumber;
+                        SetupPacket.wLength = 0;
+
+                        USBPORT_SendSetupPacket(NewDeviceHandle,
+                                                FdoDevice,
+                                                &SetupPacket,
+                                                NULL,
+                                                0,
+                                                NULL,
+                                                &USBDStatus);
+                    }
+
+                    iHandleList = iHandleList->Flink;
+                }
+            }
+        }
+
+        if (NewDeviceHandle->Flags & DEVICE_HANDLE_FLAG_INITIALIZED)
+        {
+            DPRINT1("USBPORT_RestoreDevice: FIXME Transaction Translator\n");
+            NewDeviceHandle->TtCount = OldDeviceHandle->TtCount;
+        }
+
+        while (!IsListEmpty(&OldDeviceHandle->PipeHandleList))
+        {
+            PipeHandle = CONTAINING_RECORD(OldDeviceHandle->PipeHandleList.Flink,
+                                           USBPORT_PIPE_HANDLE,
+                                           PipeLink);
+
+            DPRINT("USBPORT_RestoreDevice: PipeHandle - %p\n", PipeHandle);
+
+            USBPORT_RemovePipeHandle(OldDeviceHandle, PipeHandle);
+
+            if (PipeHandle != &OldDeviceHandle->PipeHandle)
+            {
+                USBPORT_AddPipeHandle(NewDeviceHandle, PipeHandle);
+
+                if (!(PipeHandle->Flags & PIPE_HANDLE_FLAG_NULL_PACKET_SIZE))
+                {
+                    Endpoint = PipeHandle->Endpoint;
+                    Endpoint->DeviceHandle = NewDeviceHandle;
+                    Endpoint->EndpointProperties.DeviceAddress = NewDeviceHandle->DeviceAddress;
+
+                    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+                    if (!(Endpoint->Flags & ENDPOINT_FLAG_NUKE))
+                    {
+                        KeAcquireSpinLock(&FdoExtension->MiniportSpinLock,
+                                          &OldIrql);
+
+                        Packet->ReopenEndpoint(FdoExtension->MiniPortExt,
+                                               &Endpoint->EndpointProperties,
+                                               Endpoint + 1);
+
+                        Packet->SetEndpointDataToggle(FdoExtension->MiniPortExt,
+                                                      Endpoint + 1,
+                                                      0);
+
+                        Packet->SetEndpointStatus(FdoExtension->MiniPortExt,
+                                                  Endpoint + 1,
+                                                  USBPORT_ENDPOINT_RUN);
+
+                        KeReleaseSpinLock(&FdoExtension->MiniportSpinLock,
+                                          OldIrql);
+                    }
+                    else
+                    {
+                        MiniportCloseEndpoint(FdoDevice, Endpoint);
+
+                        RtlZeroMemory(Endpoint + 1, Packet->MiniPortEndpointSize);
+
+                        RtlZeroMemory((PVOID)Endpoint->EndpointProperties.BufferVA,
+                                      Endpoint->EndpointProperties.BufferLength);
+
+                        KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+
+                        Packet->QueryEndpointRequirements(FdoExtension->MiniPortExt,
+                                                          &Endpoint->EndpointProperties,
+                                                          EndpointRequirements);
+
+                        KeReleaseSpinLock(&FdoExtension->MiniportSpinLock,
+                                          OldIrql);
+
+                        MiniportOpenEndpoint(FdoDevice, Endpoint);
+
+                        Endpoint->Flags &= ~(ENDPOINT_FLAG_NUKE |
+                                             ENDPOINT_FLAG_ABORTING);
+
+                        KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
+                                          &Endpoint->EndpointOldIrql);
+
+                        if (Endpoint->StateLast == USBPORT_ENDPOINT_ACTIVE)
+                        {
+                            KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
+
+                            Packet->SetEndpointState(FdoExtension->MiniPortExt,
+                                                     Endpoint + 1,
+                                                     USBPORT_ENDPOINT_ACTIVE);
+
+                            KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
+                        }
+
+                        KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
+                                          Endpoint->EndpointOldIrql);
+                    }
+                }
+            }
+        }
+
+        USBPORT_AddPipeHandle(OldDeviceHandle, &OldDeviceHandle->PipeHandle);
+    }
+    else
+    {
+#ifndef NDEBUG
+        DPRINT("USBPORT_RestoreDevice: New DeviceDescriptor != Old DeviceDescriptor\n");
+        DbgBreakPoint();
+#endif
+        Status = STATUS_UNSUCCESSFUL;
+    }
+
+    USBPORT_ClosePipe(OldDeviceHandle, FdoDevice, &OldDeviceHandle->PipeHandle);
+
+    if (OldDeviceHandle->DeviceAddress != 0)
+        USBPORT_FreeUsbAddress(FdoDevice, OldDeviceHandle->DeviceAddress);
+
+    KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
+                       LOW_REALTIME_PRIORITY,
+                       1,
+                       FALSE);
+
+    ExFreePoolWithTag(OldDeviceHandle, USB_PORT_TAG);
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_InitializeTT(IN PDEVICE_OBJECT FdoDevice,
+                     IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
+                     IN ULONG TtNumber)
+{
+    DPRINT1("USBPORT_InitializeTT: UNIMPLEMENTED. FIXME. \n");
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_Initialize20Hub(IN PDEVICE_OBJECT FdoDevice,
+                        IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
+                        IN ULONG TtCount)
+{
+    NTSTATUS Status;
+    ULONG ix;
+
+    DPRINT("USBPORT_Initialize20Hub \n");
+
+    if (!HubDeviceHandle)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if (HubDeviceHandle->Flags & DEVICE_HANDLE_FLAG_ROOTHUB)
+    {
+        return STATUS_SUCCESS;
+    }
+
+    if (TtCount == 0)
+    {
+        HubDeviceHandle->TtCount = 0;
+        return STATUS_SUCCESS;
+    }
+
+    for (ix = 0; ix < TtCount; ++ix)
+    {
+        Status = USBPORT_InitializeTT(FdoDevice, HubDeviceHandle, ix + 1);
+
+        if (!NT_SUCCESS(Status))
+            break;
+    }
+
+    HubDeviceHandle->TtCount = TtCount;
+
+    return Status;
+}
\ No newline at end of file
diff --git a/reactos/drivers/usb/usbport/endpoint.c b/reactos/drivers/usb/usbport/endpoint.c
new file mode 100644 (file)
index 0000000..355d36e
--- /dev/null
@@ -0,0 +1,1560 @@
+#include "usbport.h"
+
+#define NDEBUG
+#include <debug.h>
+
+#define NDEBUG_USBPORT_CORE
+#include "usbdebug.h"
+
+ULONG
+NTAPI
+USBPORT_CalculateUsbBandwidth(IN PDEVICE_OBJECT FdoDevice,
+                              IN PUSBPORT_ENDPOINT Endpoint)
+{
+    PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
+    ULONG Bandwidth;
+    ULONG Additional;
+
+    DPRINT("USBPORT_CalculateUsbBandwidth ... \n");
+
+    EndpointProperties = &Endpoint->EndpointProperties;
+
+    switch (EndpointProperties->TransferType)
+    {
+        case USBPORT_TRANSFER_TYPE_ISOCHRONOUS:
+            Additional = 9;
+            break;
+
+        case USBPORT_TRANSFER_TYPE_INTERRUPT:
+            Additional = 13;
+            break;
+
+        default: //USBPORT_TRANSFER_TYPE_CONTROL or USBPORT_TRANSFER_TYPE_BULK
+            Additional = 0;
+            break;
+    }
+
+    if (Additional == 0)
+    {
+        Bandwidth = 0;
+    }
+    else
+    {
+        Bandwidth = (EndpointProperties->TotalMaxPacketSize + Additional) * 8 * 7 / 6;
+    }
+
+    if (EndpointProperties->DeviceSpeed == UsbLowSpeed)
+    {
+        Bandwidth *= 8;
+    }
+
+    return Bandwidth;
+}
+
+BOOLEAN
+NTAPI
+USBPORT_AllocateBandwidth(IN PDEVICE_OBJECT FdoDevice,
+                          IN PUSBPORT_ENDPOINT Endpoint)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
+    ULONG TransferType;
+    ULONG TotalBusBandwidth;
+    ULONG EndpointBandwidth;
+    ULONG Period;
+
+    DPRINT("USBPORT_AllocateBandwidth: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    EndpointProperties = &Endpoint->EndpointProperties;
+    TransferType = EndpointProperties->TransferType;
+
+    if (TransferType == USBPORT_TRANSFER_TYPE_BULK || 
+        TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
+        Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)
+    {
+        EndpointProperties->ScheduleOffset = 0;
+        return TRUE;
+    }
+
+    TotalBusBandwidth = FdoExtension->TotalBusBandwidth;
+    EndpointBandwidth = EndpointProperties->UsbBandwidth;
+    Period = EndpointProperties->Period;
+
+    DPRINT1("USBPORT_AllocateBandwidth: FIXME. \n");
+    DPRINT1("USBPORT_AllocateBandwidth: Endpoint - %p, Type - %x, TotalBandwidth - %x, EpBandwidth - %x, Period - %x\n",
+           Endpoint,
+           TransferType,
+           TotalBusBandwidth,
+           EndpointBandwidth,
+           Period);
+
+    return TRUE;
+}
+
+VOID
+NTAPI
+USBPORT_FreeBandwidth(IN PDEVICE_OBJECT FdoDevice,
+                      IN PUSBPORT_ENDPOINT Endpoint)
+{
+    DPRINT1("USBPORT_FreeBandwidth: UNIMPLEMENTED. FIXME. \n");
+}
+
+UCHAR
+NTAPI
+USBPORT_NormalizeHsInterval(UCHAR Interval)
+{
+    UCHAR interval;
+
+    DPRINT("USBPORT_NormalizeHsInterval: Interval - %x\n", Interval);
+
+    interval = Interval;
+
+    if (Interval)
+       interval = Interval - 1;
+
+    if (interval > 5)
+       interval = 5;
+
+    return 1 << interval;
+}
+
+BOOLEAN
+NTAPI
+USBPORT_EndpointHasQueuedTransfers(IN PDEVICE_OBJECT FdoDevice,
+                                   IN PUSBPORT_ENDPOINT Endpoint,
+                                   IN PULONG TransferCount)
+{
+    PLIST_ENTRY Entry;
+    PUSBPORT_TRANSFER Transfer;
+    BOOLEAN Result = FALSE;
+
+    DPRINT_CORE("USBPORT_EndpointHasQueuedTransfers: ... \n");
+
+    KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
+
+    if (!IsListEmpty(&Endpoint->PendingTransferList))
+        Result = TRUE;
+
+    if (!IsListEmpty(&Endpoint->TransferList))
+    {
+        Result = TRUE;
+
+        if (TransferCount)
+        {
+            *TransferCount = 0;
+
+            for (Entry = Endpoint->TransferList.Flink;
+                 Entry && Entry != &Endpoint->TransferList;
+                 Entry = Transfer->TransferLink.Flink)
+            {
+                Transfer = CONTAINING_RECORD(Entry,
+                                             USBPORT_TRANSFER,
+                                             TransferLink);
+
+                if (Transfer->Flags & TRANSFER_FLAG_SUBMITED)
+                {
+                    ++*TransferCount;
+                }
+            }
+        }
+    }
+
+    KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
+
+    return Result;
+}
+
+VOID
+NTAPI
+USBPORT_NukeAllEndpoints(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION  FdoExtension;
+    PLIST_ENTRY EndpointList;
+    PUSBPORT_ENDPOINT Endpoint;
+    KIRQL OldIrql;
+
+    DPRINT("USBPORT_NukeAllEndpoints \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql);
+
+    EndpointList = FdoExtension->EndpointList.Flink;
+
+    while (EndpointList && (EndpointList != &FdoExtension->EndpointList))
+    {
+        Endpoint = CONTAINING_RECORD(EndpointList,
+                                     USBPORT_ENDPOINT,
+                                     EndpointLink);
+
+        if (!(Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0))
+            Endpoint->Flags |= ENDPOINT_FLAG_NUKE;
+
+        EndpointList = Endpoint->EndpointLink.Flink;
+    }
+
+    KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql);
+}
+
+ULONG 
+NTAPI
+USBPORT_GetEndpointState(IN PUSBPORT_ENDPOINT Endpoint)
+{
+    ULONG State;
+
+    //DPRINT("USBPORT_GetEndpointState \n");
+
+    KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock);
+
+    if (Endpoint->StateLast != Endpoint->StateNext)
+    {
+        State = USBPORT_ENDPOINT_UNKNOWN;
+    }
+    else
+    {
+        State = Endpoint->StateLast;
+    }
+
+    KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock);
+
+    if (State != USBPORT_ENDPOINT_ACTIVE)
+    {
+        DPRINT("USBPORT_GetEndpointState: Endpoint - %p, State - %x\n",
+               Endpoint,
+               State);
+    }
+
+    return State;
+}
+
+VOID
+NTAPI
+USBPORT_SetEndpointState(IN PUSBPORT_ENDPOINT Endpoint,
+                         IN ULONG State)
+{
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    KIRQL OldIrql;
+
+    DPRINT("USBPORT_SetEndpointState: Endpoint - %p, State - %x\n",
+           Endpoint,
+           State);
+
+    FdoDevice = Endpoint->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    KeAcquireSpinLock(&Endpoint->StateChangeSpinLock,
+                      &Endpoint->EndpointStateOldIrql);
+
+    if (!(Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0))
+    {
+        if (Endpoint->Flags & ENDPOINT_FLAG_NUKE)
+        {
+            Endpoint->StateLast = State;
+            Endpoint->StateNext = State;
+
+            KeReleaseSpinLock(&Endpoint->StateChangeSpinLock,
+                              Endpoint->EndpointStateOldIrql);
+
+            USBPORT_InvalidateEndpointHandler(FdoDevice,
+                                              Endpoint,
+                                              INVALIDATE_ENDPOINT_WORKER_THREAD);
+            return;
+        }
+
+        KeReleaseSpinLock(&Endpoint->StateChangeSpinLock,
+                          Endpoint->EndpointStateOldIrql);
+
+        KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+        Packet->SetEndpointState(FdoExtension->MiniPortExt,
+                                 Endpoint + 1,
+                                 State);
+        KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+
+        Endpoint->StateNext = State;
+
+        KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+        Endpoint->FrameNumber = Packet->Get32BitFrameNumber(FdoExtension->MiniPortExt);
+        KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+
+        ExInterlockedInsertTailList(&FdoExtension->EpStateChangeList,
+                                    &Endpoint->StateChangeLink,
+                                    &FdoExtension->EpStateChangeSpinLock);
+
+        KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+        Packet->InterruptNextSOF(FdoExtension->MiniPortExt);
+        KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+    }
+    else
+    {
+        Endpoint->StateLast = State;
+        Endpoint->StateNext = State;
+
+        if (State == USBPORT_ENDPOINT_REMOVE)
+        {
+            KeReleaseSpinLock(&Endpoint->StateChangeSpinLock,
+                              Endpoint->EndpointStateOldIrql);
+
+            USBPORT_InvalidateEndpointHandler(FdoDevice,
+                                              Endpoint,
+                                              INVALIDATE_ENDPOINT_WORKER_THREAD);
+            return;
+        }
+
+        KeReleaseSpinLock(&Endpoint->StateChangeSpinLock,
+                          Endpoint->EndpointStateOldIrql);
+    }
+}
+
+VOID
+NTAPI
+USBPORT_AddPipeHandle(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+                      IN PUSBPORT_PIPE_HANDLE PipeHandle)
+{
+    DPRINT("USBPORT_AddPipeHandle: DeviceHandle - %p, PipeHandle - %p\n",
+           DeviceHandle,
+           PipeHandle);
+
+    InsertTailList(&DeviceHandle->PipeHandleList, &PipeHandle->PipeLink);
+}
+
+VOID
+NTAPI
+USBPORT_RemovePipeHandle(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+                         IN PUSBPORT_PIPE_HANDLE PipeHandle)
+{
+    DPRINT("USBPORT_RemovePipeHandle: PipeHandle - %p\n", PipeHandle);
+
+    RemoveEntryList(&PipeHandle->PipeLink);
+
+    PipeHandle->PipeLink.Flink = NULL;
+    PipeHandle->PipeLink.Blink = NULL;
+}
+
+BOOLEAN
+NTAPI
+USBPORT_ValidatePipeHandle(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+                           IN PUSBPORT_PIPE_HANDLE PipeHandle)
+{
+    PLIST_ENTRY HandleList;
+    PUSBPORT_PIPE_HANDLE CurrentHandle;
+
+    //DPRINT("USBPORT_ValidatePipeHandle: DeviceHandle - %p, PipeHandle - %p\n",
+    //       DeviceHandle,
+    //       PipeHandle);
+
+    HandleList = DeviceHandle->PipeHandleList.Flink;
+
+    while (HandleList != &DeviceHandle->PipeHandleList)
+    {
+        CurrentHandle = CONTAINING_RECORD(HandleList,
+                                          USBPORT_PIPE_HANDLE,
+                                          PipeLink);
+  
+        HandleList = HandleList->Flink;
+  
+        if (CurrentHandle == PipeHandle)
+            return TRUE;
+    }
+
+    return FALSE;
+}
+
+BOOLEAN
+NTAPI
+USBPORT_DeleteEndpoint(IN PDEVICE_OBJECT FdoDevice,
+                       IN PUSBPORT_ENDPOINT Endpoint)
+{
+    PUSBPORT_DEVICE_EXTENSION  FdoExtension;
+    BOOLEAN Result;
+    KIRQL OldIrql;
+
+    DPRINT("USBPORT_DeleteEndpoint: Endpoint - %p\n", Endpoint);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    if ((Endpoint->WorkerLink.Flink && Endpoint->WorkerLink.Blink) ||
+        Endpoint->LockCounter != -1)
+    {
+        KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql);
+
+        ExInterlockedInsertTailList(&FdoExtension->EndpointClosedList,
+                                    &Endpoint->CloseLink,
+                                    &FdoExtension->EndpointClosedSpinLock);
+
+        KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql);
+
+        Result = FALSE;
+    }
+    else
+    {
+        KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql);
+
+        RemoveEntryList(&Endpoint->EndpointLink);
+        Endpoint->EndpointLink.Flink = NULL;
+        Endpoint->EndpointLink.Blink = NULL;
+
+        KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql);
+
+        MiniportCloseEndpoint(FdoDevice, Endpoint);
+
+        if (Endpoint->HeaderBuffer)
+        {
+            USBPORT_FreeCommonBuffer(FdoDevice, Endpoint->HeaderBuffer);
+        }
+
+        ExFreePoolWithTag(Endpoint, USB_PORT_TAG);
+
+        Result = TRUE;
+    }
+
+    return Result;
+}
+
+VOID
+NTAPI
+MiniportCloseEndpoint(IN PDEVICE_OBJECT FdoDevice,
+                      IN PUSBPORT_ENDPOINT Endpoint)
+{
+    PUSBPORT_DEVICE_EXTENSION  FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    BOOLEAN IsDoDisablePeriodic;
+    ULONG TransferType;
+    KIRQL OldIrql;
+
+    DPRINT("MiniportCloseEndpoint: Endpoint - %p\n", Endpoint);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+
+    if (Endpoint->Flags & ENDPOINT_FLAG_OPENED)
+    {
+        TransferType = Endpoint->EndpointProperties.TransferType;
+
+        if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT ||
+            TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+        {
+            --FdoExtension->PeriodicEndpoints;
+        }
+
+        IsDoDisablePeriodic = FdoExtension->PeriodicEndpoints == 0;
+
+        Packet->CloseEndpoint(FdoExtension->MiniPortExt,
+                              Endpoint + 1,
+                              IsDoDisablePeriodic);
+
+        Endpoint->Flags &= ~ENDPOINT_FLAG_OPENED;
+        Endpoint->Flags |= ENDPOINT_FLAG_CLOSED;
+    }
+
+    KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+}
+
+VOID
+NTAPI
+USBPORT_ClosePipe(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+                  IN PDEVICE_OBJECT FdoDevice,
+                  IN PUSBPORT_PIPE_HANDLE PipeHandle)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PUSBPORT_ENDPOINT Endpoint;
+    BOOLEAN IsReady;
+    KIRQL OldIrql;
+
+    DPRINT("USBPORT_ClosePipe \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    if (PipeHandle->Flags & PIPE_HANDLE_FLAG_CLOSED)
+        return;
+
+    USBPORT_RemovePipeHandle(DeviceHandle, PipeHandle);
+
+    PipeHandle->Flags |= PIPE_HANDLE_FLAG_CLOSED;
+
+    if (PipeHandle->Flags & PIPE_HANDLE_FLAG_NULL_PACKET_SIZE)
+    {
+        PipeHandle->Flags &= ~PIPE_HANDLE_FLAG_NULL_PACKET_SIZE;
+        return;
+    }
+
+    Endpoint = PipeHandle->Endpoint;
+    DPRINT("USBPORT_ClosePipe: Endpoint - %p\n", Endpoint);
+
+    KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql);
+
+    if ((Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0) &&
+        (Endpoint->EndpointProperties.TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT))
+    {
+        PdoExtension = FdoExtension->RootHubPdo->DeviceExtension;
+        PdoExtension->Endpoint = NULL;
+    }
+
+    KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql);
+
+    while (TRUE)
+    {
+        IsReady = TRUE;
+
+        KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
+                          &Endpoint->EndpointOldIrql);
+
+        if (!IsListEmpty(&Endpoint->PendingTransferList))
+            IsReady = FALSE;
+
+        if (!IsListEmpty(&Endpoint->TransferList))
+            IsReady = FALSE;
+
+        if (!IsListEmpty(&Endpoint->CancelList))
+            IsReady = FALSE;
+
+        if (!IsListEmpty(&Endpoint->AbortList))
+            IsReady = FALSE;
+
+        KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock);
+        if (Endpoint->StateLast != Endpoint->StateNext)
+            IsReady = FALSE;
+        KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock);
+
+        KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
+                          Endpoint->EndpointOldIrql);
+
+        if (InterlockedIncrement(&Endpoint->LockCounter))
+            IsReady = FALSE;
+        InterlockedDecrement(&Endpoint->LockCounter);
+
+        if (IsReady == TRUE)
+            break;
+
+        USBPORT_Wait(FdoDevice, 1);
+    }
+
+    Endpoint->DeviceHandle = NULL;
+
+    if (FdoExtension->MiniPortInterface->Packet.MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
+    {
+        DPRINT("USBPORT_ClosePipe: FIXME USBPORT_FreeBandwidthUSB20\n");
+        //USBPORT_FreeBandwidthUSB20();
+    }
+    else
+    {
+        DPRINT("USBPORT_ClosePipe: FIXME USBPORT_FreeBandwidthUSB11\n");
+        //USBPORT_FreeBandwidthUSB11();
+    }
+
+    KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
+    USBPORT_SetEndpointState(Endpoint, USBPORT_ENDPOINT_REMOVE);
+    KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
+
+    USBPORT_SignalWorkerThread(FdoDevice);
+}
+
+MPSTATUS
+NTAPI
+MiniportOpenEndpoint(IN PDEVICE_OBJECT FdoDevice,
+                     IN PUSBPORT_ENDPOINT Endpoint)
+{
+    PUSBPORT_DEVICE_EXTENSION  FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    KIRQL OldIrql;
+    ULONG TransferType;
+    MPSTATUS MpStatus;
+
+    DPRINT("MiniportOpenEndpoint: Endpoint - %p\n", Endpoint);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+
+    Endpoint->Flags &= ~ENDPOINT_FLAG_CLOSED;
+
+    MpStatus = Packet->OpenEndpoint(FdoExtension->MiniPortExt,
+                                    &Endpoint->EndpointProperties,
+                                    Endpoint + 1);
+
+    if (!MpStatus)
+    {
+        TransferType = Endpoint->EndpointProperties.TransferType;
+
+        if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT ||
+            TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+        {
+            ++FdoExtension->PeriodicEndpoints;
+        }
+
+        Endpoint->Flags |= ENDPOINT_FLAG_OPENED;
+    }
+
+    KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+    return MpStatus;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_OpenPipe(IN PDEVICE_OBJECT FdoDevice,
+                 IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+                 IN PUSBPORT_PIPE_HANDLE PipeHandle,
+                 IN OUT PUSBD_STATUS UsbdStatus)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    ULONG EndpointSize;
+    PUSBPORT_ENDPOINT Endpoint;
+    PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
+    PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+    UCHAR Direction;
+    UCHAR Interval;
+    UCHAR Period;
+    ULONG TransferParams[2] = {0};
+    PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer;
+    MPSTATUS MpStatus;
+    USBD_STATUS USBDStatus;
+    NTSTATUS Status;
+    KIRQL OldIrql;
+    USHORT MaxPacketSize;
+    USHORT AdditionalTransaction;
+    BOOLEAN IsAllocatedBandwidth;
+
+    DPRINT("USBPORT_OpenPipe: DeviceHandle - %p, FdoDevice - %p, PipeHandle - %p\n",
+           DeviceHandle,
+           FdoDevice,
+           PipeHandle);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    EndpointSize = sizeof(USBPORT_ENDPOINT) + Packet->MiniPortEndpointSize;
+
+    if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
+    {
+        DPRINT1("USBPORT_OpenPipe: FIXME USB2 EndpointSize\n");
+    }
+
+    if (PipeHandle->EndpointDescriptor.wMaxPacketSize == 0)
+    {
+        USBPORT_AddPipeHandle(DeviceHandle, PipeHandle);
+  
+        PipeHandle->Flags = (PipeHandle->Flags & ~PIPE_HANDLE_FLAG_CLOSED) |
+                             PIPE_HANDLE_FLAG_NULL_PACKET_SIZE;
+
+        PipeHandle->Endpoint = (PUSBPORT_ENDPOINT)-1;
+
+        return STATUS_SUCCESS;
+    }
+
+    Endpoint = ExAllocatePoolWithTag(NonPagedPool, EndpointSize, USB_PORT_TAG);
+
+    if (!Endpoint)
+    {
+        DPRINT1("USBPORT_OpenPipe: Not allocated Endpoint!\n");
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        return Status;
+    }
+
+    RtlZeroMemory(Endpoint, EndpointSize);
+
+    Endpoint->FdoDevice = FdoDevice;
+    Endpoint->DeviceHandle = DeviceHandle;
+    Endpoint->LockCounter = -1;
+
+    KeInitializeSpinLock(&Endpoint->EndpointSpinLock);
+    KeInitializeSpinLock(&Endpoint->StateChangeSpinLock);
+
+    InitializeListHead(&Endpoint->PendingTransferList);
+    InitializeListHead(&Endpoint->TransferList);
+    InitializeListHead(&Endpoint->CancelList);
+    InitializeListHead(&Endpoint->AbortList);
+
+    EndpointProperties = &Endpoint->EndpointProperties;
+    EndpointDescriptor = &PipeHandle->EndpointDescriptor;
+
+    MaxPacketSize = EndpointDescriptor->wMaxPacketSize & 0x7FF;
+    AdditionalTransaction = (EndpointDescriptor->wMaxPacketSize >> 11) & 3;
+
+    EndpointProperties->DeviceAddress = DeviceHandle->DeviceAddress;
+    EndpointProperties->DeviceSpeed = DeviceHandle->DeviceSpeed;
+    EndpointProperties->Period = 0;
+    EndpointProperties->EndpointAddress = EndpointDescriptor->bEndpointAddress;
+    EndpointProperties->TransactionPerMicroframe = AdditionalTransaction + 1;
+    EndpointProperties->MaxPacketSize = MaxPacketSize;
+    EndpointProperties->TotalMaxPacketSize = MaxPacketSize *
+                                             (AdditionalTransaction + 1);
+
+    switch (EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK)
+    {
+        case USB_ENDPOINT_TYPE_CONTROL:
+            EndpointProperties->TransferType = USBPORT_TRANSFER_TYPE_CONTROL;
+
+            if (EndpointProperties->EndpointAddress == 0)
+            {
+                EndpointProperties->MaxTransferSize = 0x1000; // OUT Ep0
+            }
+            else
+            {
+                EndpointProperties->MaxTransferSize = 0x10000;
+            }
+
+            break;
+
+        case USB_ENDPOINT_TYPE_ISOCHRONOUS:
+            DPRINT1("USBPORT_OpenPipe: USB_ENDPOINT_TYPE_ISOCHRONOUS UNIMPLEMENTED. FIXME. \n");
+            EndpointProperties->TransferType = USBPORT_TRANSFER_TYPE_ISOCHRONOUS;
+            EndpointProperties->MaxTransferSize = 0x1000000;
+            break;
+
+        case USB_ENDPOINT_TYPE_BULK:
+            EndpointProperties->TransferType = USBPORT_TRANSFER_TYPE_BULK;
+            EndpointProperties->MaxTransferSize = 0x10000;
+            break;
+
+        case USB_ENDPOINT_TYPE_INTERRUPT:
+            EndpointProperties->TransferType = USBPORT_TRANSFER_TYPE_INTERRUPT;
+            EndpointProperties->MaxTransferSize = 0x400;
+            break;
+    }
+
+    if (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
+    {
+        if (EndpointProperties->DeviceSpeed == UsbHighSpeed)
+        {
+            Interval = USBPORT_NormalizeHsInterval(EndpointDescriptor->bInterval);
+        }
+        else
+        {
+            Interval = EndpointDescriptor->bInterval;
+        }
+
+        EndpointProperties->Period = 32;
+
+        if (Interval && (Interval < 32))
+        {
+            if ((EndpointProperties->DeviceSpeed != UsbLowSpeed) ||
+                (Interval >= 8))
+            {
+                if (!(Interval & 0x20))
+                {
+                    Period = EndpointProperties->Period;
+
+                    do
+                    {
+                        Period >>= 1;
+                    }
+                    while (!(Period & Interval));
+
+                    EndpointProperties->Period = Period;
+                }
+            }
+            else
+            {
+                EndpointProperties->Period = 8;
+            }
+        }
+    }
+
+    if (EndpointProperties->TransferType == USB_ENDPOINT_TYPE_ISOCHRONOUS)
+    {
+        if (EndpointProperties->DeviceSpeed == UsbHighSpeed)
+        {
+            EndpointProperties->Period = 
+                USBPORT_NormalizeHsInterval(EndpointDescriptor->bInterval);
+        }
+        else
+        {
+            EndpointProperties->Period = 1;
+        }
+    }
+
+    if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
+    {
+        IsAllocatedBandwidth = USBPORT_AllocateBandwidthUSB2(FdoDevice, Endpoint);
+    }
+    else
+    {
+        EndpointProperties->UsbBandwidth = USBPORT_CalculateUsbBandwidth(FdoDevice,
+                                                                         Endpoint);
+
+        IsAllocatedBandwidth = USBPORT_AllocateBandwidth(FdoDevice, Endpoint);
+    }
+
+    if (!IsAllocatedBandwidth)
+    {
+        Status = USBPORT_USBDStatusToNtStatus(NULL, USBD_STATUS_NO_BANDWIDTH);
+
+        if (UsbdStatus)
+        {
+            *UsbdStatus = USBD_STATUS_NO_BANDWIDTH;
+        }
+
+        goto ExitWithError;
+    }
+
+    Direction = USB_ENDPOINT_DIRECTION_IN(EndpointDescriptor->bEndpointAddress);
+    EndpointProperties->Direction = Direction;
+
+    if (DeviceHandle->IsRootHub)
+    {
+        Endpoint->EndpointWorker = 0; // USBPORT_RootHubEndpointWorker;
+
+        Endpoint->Flags |= ENDPOINT_FLAG_ROOTHUB_EP0;
+
+        Endpoint->StateLast = USBPORT_ENDPOINT_ACTIVE;
+        Endpoint->StateNext = USBPORT_ENDPOINT_ACTIVE;
+
+        PdoExtension = FdoExtension->RootHubPdo->DeviceExtension;
+
+        if (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
+        {
+            PdoExtension->Endpoint = Endpoint;
+        }
+
+        USBDStatus = USBD_STATUS_SUCCESS;
+    }
+    else
+    {
+        Endpoint->EndpointWorker = 1; // USBPORT_DmaEndpointWorker;
+
+        KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+
+        Packet->QueryEndpointRequirements(FdoExtension->MiniPortExt,
+                                          &Endpoint->EndpointProperties,
+                                          TransferParams);
+
+        KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+
+        if ((EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_BULK) ||
+            (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT))
+        {
+            EndpointProperties->MaxTransferSize = TransferParams[1];
+        }
+
+        if (TransferParams[0])
+        {
+            HeaderBuffer = USBPORT_AllocateCommonBuffer(FdoDevice,
+                                                        TransferParams[0]);
+        }
+        else
+        {
+            HeaderBuffer = NULL;
+        }
+
+        if (HeaderBuffer || (TransferParams[0] == 0))
+        {
+            Endpoint->HeaderBuffer = HeaderBuffer;
+
+            if (HeaderBuffer)
+            {
+                EndpointProperties->BufferVA = HeaderBuffer->VirtualAddress;
+                EndpointProperties->BufferPA = HeaderBuffer->PhysicalAddress;
+                EndpointProperties->BufferLength = HeaderBuffer->BufferLength; // BufferLength + LengthPadded;
+            }
+
+            MpStatus = MiniportOpenEndpoint(FdoDevice, Endpoint);
+
+            Endpoint->Flags |= ENDPOINT_FLAG_DMA_TYPE;
+            Endpoint->Flags |= ENDPOINT_FLAG_QUEUENE_EMPTY;
+
+            if (MpStatus == 0)
+            {
+                ULONG State;
+
+                KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
+                                  &Endpoint->EndpointOldIrql);
+
+                Endpoint->StateLast = USBPORT_ENDPOINT_PAUSED;
+                Endpoint->StateNext = USBPORT_ENDPOINT_PAUSED;
+
+                USBPORT_SetEndpointState(Endpoint, USBPORT_ENDPOINT_ACTIVE);
+
+                KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
+                                  Endpoint->EndpointOldIrql);
+
+                while (TRUE)
+                {
+                    KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
+                                      &Endpoint->EndpointOldIrql);
+
+                    State = USBPORT_GetEndpointState(Endpoint);
+
+                    KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
+                                      Endpoint->EndpointOldIrql);
+
+                    if (State == USBPORT_ENDPOINT_ACTIVE)
+                    {
+                        break;
+                    }
+
+                    USBPORT_Wait(FdoDevice, 1); // 1 msec.
+                }
+            }
+        }
+        else
+        {
+            MpStatus = MP_STATUS_NO_RESOURCES;
+            Endpoint->HeaderBuffer = NULL;
+        }
+
+        if (MpStatus)
+        {
+            USBDStatus = USBD_STATUS_INSUFFICIENT_RESOURCES;
+        }
+        else
+        {
+            USBDStatus = USBD_STATUS_SUCCESS;
+        }
+    }
+
+    if (UsbdStatus)
+    {
+        *UsbdStatus = USBDStatus;
+    }
+
+    Status = USBPORT_USBDStatusToNtStatus(NULL, USBDStatus);
+
+    if (NT_SUCCESS(Status))
+    {
+        USBPORT_AddPipeHandle(DeviceHandle, PipeHandle);
+
+        ExInterlockedInsertTailList(&FdoExtension->EndpointList,
+                                    &Endpoint->EndpointLink,
+                                    &FdoExtension->EndpointListSpinLock);
+
+        PipeHandle->Endpoint = Endpoint;
+        PipeHandle->Flags &= ~PIPE_HANDLE_FLAG_CLOSED;
+
+        return Status;
+    }
+
+ExitWithError:
+
+    if (Endpoint)
+    {
+        if (IsAllocatedBandwidth)
+        {
+            if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
+            {
+                USBPORT_FreeBandwidthUSB2(FdoDevice, Endpoint);
+            }
+            else
+            {
+                USBPORT_FreeBandwidth(FdoDevice, Endpoint);
+            }
+        }
+
+        ExFreePoolWithTag(Endpoint, USB_PORT_TAG);
+    }
+
+    DPRINT1("USBPORT_OpenPipe: Status - %lx\n", Status);
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_ReopenPipe(IN PDEVICE_OBJECT FdoDevice,
+                   IN PUSBPORT_ENDPOINT Endpoint)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer;
+    ULONG EndpointRequirements[2] = {0};
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    KIRQL MiniportOldIrql;
+    NTSTATUS Status;
+
+    DPRINT("USBPORT_ReopenPipe ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    while (TRUE)
+    {
+        if (!InterlockedIncrement(&Endpoint->LockCounter))
+            break;
+
+        InterlockedDecrement(&Endpoint->LockCounter);
+        USBPORT_Wait(FdoDevice, 1);
+    }
+
+    KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &MiniportOldIrql);
+
+    Packet->SetEndpointState(FdoExtension->MiniPortExt,
+                             Endpoint + 1,
+                             USBPORT_ENDPOINT_REMOVE);
+
+    KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, MiniportOldIrql);
+
+    USBPORT_Wait(FdoDevice, 2);
+
+    MiniportCloseEndpoint(FdoDevice, Endpoint);
+
+    RtlZeroMemory(Endpoint + 1,
+                  Packet->MiniPortEndpointSize);
+
+    if (Endpoint->HeaderBuffer)
+    {
+        USBPORT_FreeCommonBuffer(FdoDevice, Endpoint->HeaderBuffer);
+        Endpoint->HeaderBuffer = NULL;
+    }
+
+    KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &MiniportOldIrql);
+
+    Packet->QueryEndpointRequirements(FdoExtension->MiniPortExt,
+                                      &Endpoint->EndpointProperties,
+                                      EndpointRequirements);
+
+    KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, MiniportOldIrql);
+
+    if (EndpointRequirements[0])
+    {
+        HeaderBuffer = USBPORT_AllocateCommonBuffer(FdoDevice,
+                                                    EndpointRequirements[0]);
+    }
+    else
+    {
+        HeaderBuffer = NULL;
+    }
+
+    if (HeaderBuffer || EndpointRequirements[0] == 0)
+    {
+        Endpoint->HeaderBuffer = HeaderBuffer;
+        Status = STATUS_SUCCESS;
+    }
+    else
+    {
+        Endpoint->HeaderBuffer = 0;
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    if (Endpoint->HeaderBuffer && HeaderBuffer)
+    {
+        Endpoint->EndpointProperties.BufferVA = HeaderBuffer->VirtualAddress;
+        Endpoint->EndpointProperties.BufferPA = HeaderBuffer->PhysicalAddress;
+        Endpoint->EndpointProperties.BufferLength = HeaderBuffer->BufferLength;
+    }
+
+    if (NT_SUCCESS(Status))
+    {
+        MiniportOpenEndpoint(FdoDevice, Endpoint);
+
+        KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
+        KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock);
+
+        if (Endpoint->StateLast == USBPORT_ENDPOINT_ACTIVE)
+        {
+            KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
+
+            Packet->SetEndpointState(FdoExtension->MiniPortExt,
+                                     Endpoint + 1,
+                                     USBPORT_ENDPOINT_ACTIVE);
+
+            KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
+        }
+
+        KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock);
+        KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
+    }
+
+    InterlockedDecrement(&Endpoint->LockCounter);
+
+    return Status;
+}
+
+VOID
+NTAPI
+USBPORT_FlushClosedEndpointList(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION  FdoExtension;
+    KIRQL OldIrql;
+    PLIST_ENTRY ClosedList;
+    PUSBPORT_ENDPOINT Endpoint;
+
+    DPRINT("USBPORT_FlushClosedEndpointList: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    KeAcquireSpinLock(&FdoExtension->EndpointClosedSpinLock, &OldIrql);
+    ClosedList = &FdoExtension->EndpointClosedList;
+
+    while (!IsListEmpty(ClosedList))
+    {
+        Endpoint = CONTAINING_RECORD(ClosedList->Flink,
+                                     USBPORT_ENDPOINT,
+                                     CloseLink);
+
+        RemoveHeadList(ClosedList);
+        Endpoint->CloseLink.Flink = NULL;
+        Endpoint->CloseLink.Blink = NULL;
+
+        KeReleaseSpinLock(&FdoExtension->EndpointClosedSpinLock, OldIrql);
+
+        USBPORT_DeleteEndpoint(FdoDevice, Endpoint);
+
+        KeAcquireSpinLock(&FdoExtension->EndpointClosedSpinLock, &OldIrql);
+    }
+
+    KeReleaseSpinLock(&FdoExtension->EndpointClosedSpinLock, OldIrql);
+}
+
+VOID
+NTAPI
+USBPORT_InvalidateEndpointHandler(IN PDEVICE_OBJECT FdoDevice,
+                                  IN PUSBPORT_ENDPOINT Endpoint,
+                                  IN ULONG Type)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    PLIST_ENTRY Entry;
+    PLIST_ENTRY WorkerLink;
+    PUSBPORT_ENDPOINT endpoint;
+    KIRQL OldIrql;
+    BOOLEAN IsAddEntry = FALSE;
+
+    DPRINT_CORE("USBPORT_InvalidateEndpointHandler: Endpoint - %p, Type - %x\n",
+                Endpoint,
+                Type);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    if (Endpoint)
+    {
+        WorkerLink = &Endpoint->WorkerLink;
+        KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql);
+        DPRINT_CORE("USBPORT_InvalidateEndpointHandler: KeAcquireSpinLock \n");
+
+        if ((!WorkerLink->Flink || !WorkerLink->Blink) &&
+            !(Endpoint->Flags & ENDPOINT_FLAG_IDLE) &&
+            USBPORT_GetEndpointState(Endpoint) != USBPORT_ENDPOINT_CLOSED)
+        {
+            DPRINT_CORE("USBPORT_InvalidateEndpointHandler: InsertTailList \n");
+            InsertTailList(&FdoExtension->WorkerList, WorkerLink);
+            IsAddEntry = TRUE;
+        }
+
+        KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql);
+
+        if (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)
+            Type = INVALIDATE_ENDPOINT_WORKER_THREAD;
+    }
+    else
+    {
+        KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql);
+
+        Entry = &FdoExtension->EndpointList;
+
+        while (Entry && Entry != &FdoExtension->EndpointList)
+        {
+            endpoint = CONTAINING_RECORD(Entry,
+                                         USBPORT_ENDPOINT,
+                                         EndpointLink);
+
+            if (!endpoint->WorkerLink.Flink || !endpoint->WorkerLink.Blink)
+            {
+                if (!(endpoint->Flags & ENDPOINT_FLAG_IDLE) &&
+                    !(endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0) &&
+                    USBPORT_GetEndpointState(endpoint) != USBPORT_ENDPOINT_CLOSED)
+                {
+                    DPRINT_CORE("USBPORT_InvalidateEndpointHandler: InsertTailList \n");
+                    InsertTailList(&FdoExtension->WorkerList, &endpoint->WorkerLink);
+                    IsAddEntry = TRUE;
+                }
+            }
+
+            Entry = endpoint->EndpointLink.Flink;
+        }
+
+        KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql);
+    }
+
+    if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND)
+    {
+        Type = INVALIDATE_ENDPOINT_WORKER_THREAD;
+    }
+    else if (IsAddEntry == FALSE && Type == INVALIDATE_ENDPOINT_INT_NEXT_SOF)
+    {
+        Type = INVALIDATE_ENDPOINT_ONLY;
+    }
+
+    switch (Type)
+    {
+        case INVALIDATE_ENDPOINT_WORKER_THREAD:
+            USBPORT_SignalWorkerThread(FdoDevice);
+            break;
+
+        case INVALIDATE_ENDPOINT_WORKER_DPC:
+            KeInsertQueueDpc(&FdoExtension->WorkerRequestDpc, NULL, NULL);
+            break;
+
+        case INVALIDATE_ENDPOINT_INT_NEXT_SOF:
+            KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+            Packet->InterruptNextSOF(FdoExtension->MiniPortExt);
+            KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+            break;
+    }
+}
+
+ULONG
+NTAPI
+USBPORT_DmaEndpointPaused(IN PDEVICE_OBJECT FdoDevice,
+                          IN PUSBPORT_ENDPOINT Endpoint)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    PLIST_ENTRY Entry;
+    PUSBPORT_TRANSFER Transfer;
+    PURB Urb;
+    ULONG Frame;
+    ULONG CurrentFrame;
+    ULONG CompletedLen = 0;
+    KIRQL OldIrql;
+
+    DPRINT_CORE("USBPORT_DmaEndpointPaused \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    Entry = Endpoint->TransferList.Flink;
+
+    if (Entry == &Endpoint->TransferList)
+        return USBPORT_ENDPOINT_ACTIVE;
+
+    while (Entry && Entry != &Endpoint->TransferList)
+    {
+        Transfer = CONTAINING_RECORD(Entry,
+                                     USBPORT_TRANSFER,
+                                     TransferLink);
+
+        if (Transfer->Flags & (TRANSFER_FLAG_CANCELED | TRANSFER_FLAG_ABORTED))
+        {
+            if (Transfer->Flags & TRANSFER_FLAG_ISO &&
+                Transfer->Flags & TRANSFER_FLAG_SUBMITED &&
+                !(Endpoint->Flags & ENDPOINT_FLAG_NUKE))
+            {
+                Urb = Transfer->Urb;
+
+                Frame = Urb->UrbIsochronousTransfer.StartFrame +
+                        Urb->UrbIsochronousTransfer.NumberOfPackets;
+
+                KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+                CurrentFrame = Packet->Get32BitFrameNumber(FdoExtension->MiniPortExt);
+                KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+
+                if (Frame + 1 > CurrentFrame)
+                {
+                    return USBPORT_GetEndpointState(Endpoint);
+                }
+            }
+
+            if ((Transfer->Flags & TRANSFER_FLAG_SUBMITED) &&
+                 !(Endpoint->Flags & ENDPOINT_FLAG_NUKE))
+            {
+                KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+
+                Packet->AbortTransfer(FdoExtension->MiniPortExt,
+                                      Endpoint + 1,
+                                      Transfer->MiniportTransfer,
+                                      &CompletedLen);
+
+                KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+
+                if (Transfer->Flags & TRANSFER_FLAG_ISO)
+                {
+                    DPRINT1("USBPORT_DmaEndpointActive: FIXME call USBPORT_FlushIsoTransfer\n");
+                    ASSERT(FALSE); //USBPORT_FlushIsoTransfer();
+                }
+                else
+                {
+                    Transfer->CompletedTransferLen = CompletedLen;
+                }
+            }
+
+            RemoveEntryList(&Transfer->TransferLink);
+            Entry = Transfer->TransferLink.Flink;
+
+            if (Transfer->Flags & TRANSFER_FLAG_SPLITED)
+            {
+                DPRINT1("USBPORT_DmaEndpointActive: FIXME call USBPORT_CancelSplitTransfer\n");
+                ASSERT(FALSE); //USBPORT_CancelSplitTransfer();
+            }
+            else
+            {
+                InsertTailList(&Endpoint->CancelList, &Transfer->TransferLink);
+            }
+        }
+        else
+        {
+            Entry = Transfer->TransferLink.Flink;
+        }
+    }
+
+    return USBPORT_ENDPOINT_ACTIVE;
+}
+
+ULONG
+NTAPI
+USBPORT_DmaEndpointActive(IN PDEVICE_OBJECT FdoDevice,
+                          IN PUSBPORT_ENDPOINT Endpoint)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    PLIST_ENTRY Entry;
+    PUSBPORT_TRANSFER Transfer;
+    LARGE_INTEGER TimeOut;
+    MPSTATUS MpStatus;
+    KIRQL OldIrql;
+
+    DPRINT_CORE("USBPORT_DmaEndpointActive \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    Entry = Endpoint->TransferList.Flink;
+
+    while (Entry && Entry != &Endpoint->TransferList)
+    {
+        Transfer = CONTAINING_RECORD(Entry,
+                                     USBPORT_TRANSFER,
+                                     TransferLink);
+
+        if (!(Transfer->Flags & TRANSFER_FLAG_SUBMITED) &&
+             !(Endpoint->Flags & ENDPOINT_FLAG_NUKE))
+        {
+            KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+
+            Packet = &FdoExtension->MiniPortInterface->Packet;
+
+            if (Transfer->Flags & TRANSFER_FLAG_ISO)
+            {
+                DPRINT1("USBPORT_DmaEndpointActive: FIXME call SubmitIsoTransfer\n");
+
+                MpStatus = Packet->SubmitIsoTransfer(FdoExtension->MiniPortExt,
+                                                     Endpoint + 1,
+                                                     &Transfer->TransferParameters,
+                                                     Transfer->MiniportTransfer,
+                                                     NULL);//&Transfer->IsoTransferParameters);
+            }
+            else
+            {
+                MpStatus = Packet->SubmitTransfer(FdoExtension->MiniPortExt,
+                                                  Endpoint + 1,
+                                                  &Transfer->TransferParameters,
+                                                  Transfer->MiniportTransfer,
+                                                  &Transfer->SgList);
+            }
+
+            KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+
+            if (MpStatus)
+            {
+                if ((MpStatus != MP_STATUS_FAILURE) && Transfer->Flags & TRANSFER_FLAG_ISO)
+                {
+                    DPRINT1("USBPORT_DmaEndpointActive: FIXME call USBPORT_ErrorCompleteIsoTransfer\n");
+                    ASSERT(FALSE); //USBPORT_ErrorCompleteIsoTransfer();
+                }
+
+                return USBPORT_ENDPOINT_ACTIVE;
+            }
+
+            Transfer->Flags |= TRANSFER_FLAG_SUBMITED;
+            KeQuerySystemTime(&Transfer->Time);
+
+            TimeOut.QuadPart = 10000 * Transfer->TimeOut;
+            Transfer->Time.QuadPart += TimeOut.QuadPart;
+        }
+
+        if (Transfer->Flags & (TRANSFER_FLAG_CANCELED | TRANSFER_FLAG_ABORTED))
+        {
+            return USBPORT_ENDPOINT_PAUSED;
+        }
+
+        Entry = Transfer->TransferLink.Flink;
+    }
+
+    return USBPORT_ENDPOINT_ACTIVE;
+}
+
+VOID
+NTAPI
+USBPORT_DmaEndpointWorker(IN PUSBPORT_ENDPOINT Endpoint)
+{
+    PDEVICE_OBJECT FdoDevice;
+    ULONG PrevState;
+    ULONG EndpointState;
+    BOOLEAN IsPaused = FALSE;
+
+    DPRINT_CORE("USBPORT_DmaEndpointWorker ... \n");
+
+    FdoDevice = Endpoint->FdoDevice;
+
+    KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
+
+    PrevState = USBPORT_GetEndpointState(Endpoint);
+
+    if (PrevState == USBPORT_ENDPOINT_PAUSED)
+    {
+        EndpointState = USBPORT_DmaEndpointPaused(FdoDevice, Endpoint);
+    }
+    else if (PrevState == USBPORT_ENDPOINT_ACTIVE)
+    {
+        EndpointState = USBPORT_DmaEndpointActive(FdoDevice, Endpoint);
+    }
+    else
+    {
+#ifndef NDEBUG_USBPORT_CORE
+        DPRINT1("USBPORT_DmaEndpointWorker: DbgBreakPoint. EndpointState - %x\n",
+                EndpointState);
+        DbgBreakPoint();
+#endif
+        EndpointState = USBPORT_ENDPOINT_UNKNOWN;
+    }
+
+    KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
+
+    USBPORT_FlushCancelList(Endpoint);
+
+    KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
+
+    if (EndpointState == PrevState)
+    {
+        if (EndpointState == USBPORT_ENDPOINT_PAUSED)
+        {
+            IsPaused = TRUE;
+        }
+    }
+    else
+    {
+        USBPORT_SetEndpointState(Endpoint, EndpointState);
+    }
+
+    KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
+
+    if (IsPaused)
+    {
+       USBPORT_InvalidateEndpointHandler(FdoDevice,
+                                         Endpoint,
+                                         INVALIDATE_ENDPOINT_WORKER_THREAD);
+    }
+
+    DPRINT_CORE("USBPORT_DmaEndpointWorker exit \n");
+}
+
+BOOLEAN
+NTAPI
+USBPORT_EndpointWorker(IN PUSBPORT_ENDPOINT Endpoint,
+                       IN BOOLEAN LockNotChecked)
+{
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    ULONG EndpointState;
+
+    DPRINT_CORE("USBPORT_EndpointWorker: Endpoint - %p, LockNotChecked - %x\n",
+           Endpoint,
+           LockNotChecked);
+
+    FdoDevice = Endpoint->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    if (LockNotChecked == FALSE)
+    {
+        if (InterlockedIncrement(&Endpoint->LockCounter))
+        {
+            InterlockedDecrement(&Endpoint->LockCounter);
+            DPRINT_CORE("USBPORT_EndpointWorker: LockCounter > 0\n");
+            return TRUE;
+        }
+    }
+
+    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+    KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock);
+
+    if (USBPORT_GetEndpointState(Endpoint) == USBPORT_ENDPOINT_CLOSED)
+    {
+        KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
+        InterlockedDecrement(&Endpoint->LockCounter);
+        DPRINT_CORE("USBPORT_EndpointWorker: State == USBPORT_ENDPOINT_CLOSED. return FALSE\n");
+        return FALSE;
+    }
+
+    if ((Endpoint->Flags & (ENDPOINT_FLAG_ROOTHUB_EP0 | ENDPOINT_FLAG_NUKE)) == 0)
+    {
+        KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
+        Packet->PollEndpoint(FdoExtension->MiniPortExt, Endpoint + 1);
+        KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
+    }
+
+    EndpointState = USBPORT_GetEndpointState(Endpoint);
+
+    if (EndpointState == USBPORT_ENDPOINT_REMOVE)
+    {
+        KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock);
+        Endpoint->StateLast = USBPORT_ENDPOINT_CLOSED;
+        Endpoint->StateNext = USBPORT_ENDPOINT_CLOSED;
+        KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock);
+
+        KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
+
+        KeAcquireSpinLockAtDpcLevel(&FdoExtension->EndpointListSpinLock);
+
+        ExInterlockedInsertTailList(&FdoExtension->EndpointClosedList,
+                                    &Endpoint->CloseLink,
+                                    &FdoExtension->EndpointClosedSpinLock);
+
+        KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock);
+
+        InterlockedDecrement(&Endpoint->LockCounter);
+        DPRINT_CORE("USBPORT_EndpointWorker: State == USBPORT_ENDPOINT_REMOVE. return FALSE\n");
+        return FALSE;
+    }
+
+    if (!IsListEmpty(&Endpoint->PendingTransferList) ||
+        !IsListEmpty(&Endpoint->TransferList) ||
+        !IsListEmpty(&Endpoint->CancelList))
+    {
+        KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
+
+        EndpointState = USBPORT_GetEndpointState(Endpoint);
+
+        KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock);
+        if (EndpointState == Endpoint->StateNext)
+        {
+            KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock);
+
+            if (Endpoint->EndpointWorker)
+            {
+                USBPORT_DmaEndpointWorker(Endpoint);
+            }
+            else
+            {
+                USBPORT_RootHubEndpointWorker(Endpoint);
+            }
+
+            USBPORT_FlushAbortList(Endpoint);
+
+            InterlockedDecrement(&Endpoint->LockCounter);
+            DPRINT_CORE("USBPORT_EndpointWorker: return FALSE\n");
+            return FALSE;
+        }
+
+        KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock);
+        InterlockedDecrement(&Endpoint->LockCounter);
+
+        DPRINT_CORE("USBPORT_EndpointWorker: return TRUE\n");
+        return TRUE;
+    }
+
+    KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
+
+    USBPORT_FlushAbortList(Endpoint);
+
+    InterlockedDecrement(&Endpoint->LockCounter);
+    DPRINT_CORE("USBPORT_EndpointWorker: return FALSE\n");
+    return FALSE;
+}
diff --git a/reactos/drivers/usb/usbport/guid.c b/reactos/drivers/usb/usbport/guid.c
new file mode 100644 (file)
index 0000000..50a6036
--- /dev/null
@@ -0,0 +1,9 @@
+/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */
+
+#include <wdm.h>
+#include <initguid.h>
+#include <wdmguid.h>
+#include <hubbusif.h>
+#include <usbbusif.h>
+
+/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */
diff --git a/reactos/drivers/usb/usbport/iface.c b/reactos/drivers/usb/usbport/iface.c
new file mode 100644 (file)
index 0000000..aeacdef
--- /dev/null
@@ -0,0 +1,901 @@
+#include "usbport.h"
+
+#define NDEBUG
+#include <debug.h>
+
+VOID
+USB_BUSIFFN
+USBI_InterfaceReference(IN PVOID BusContext)
+{
+    DPRINT("USBI_InterfaceReference \n");
+}
+
+VOID
+USB_BUSIFFN
+USBI_InterfaceDereference(IN PVOID BusContext)
+{
+    DPRINT("USBI_InterfaceDereference \n");
+}
+
+/* USB port driver Interface functions */
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_CreateUsbDevice(IN PVOID BusContext,
+                      IN OUT PUSB_DEVICE_HANDLE *UsbdDeviceHandle,
+                      IN PUSB_DEVICE_HANDLE UsbdHubDeviceHandle,
+                      IN USHORT PortStatus,
+                      IN USHORT PortNumber)
+{
+    PDEVICE_OBJECT PdoDevice;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PUSB_DEVICE_HANDLE deviceHandle = NULL;
+    NTSTATUS Status;
+
+    DPRINT("USBHI_CreateUsbDevice: ... \n");
+
+    PdoDevice = BusContext;
+    PdoExtension = PdoDevice->DeviceExtension;
+
+    Status = USBPORT_CreateDevice(&deviceHandle,
+                                  PdoExtension->FdoDevice,
+                                  (PUSBPORT_DEVICE_HANDLE)UsbdHubDeviceHandle,
+                                  PortStatus,
+                                  PortNumber);
+
+    *UsbdDeviceHandle = deviceHandle;
+
+    return Status;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_InitializeUsbDevice(IN PVOID BusContext,
+                          OUT PUSB_DEVICE_HANDLE UsbdDeviceHandle)
+{
+    PDEVICE_OBJECT PdoDevice;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+
+    DPRINT("USBHI_InitializeUsbDevice \n");
+
+    PdoDevice = BusContext;
+    PdoExtension = PdoDevice->DeviceExtension;
+
+    return USBPORT_InitializeDevice((PUSBPORT_DEVICE_HANDLE)UsbdDeviceHandle,
+                                    PdoExtension->FdoDevice);
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_GetUsbDescriptors(IN PVOID BusContext,
+                        IN PUSB_DEVICE_HANDLE UsbdDeviceHandle,
+                        IN PUCHAR DeviceDescBuffer,
+                        IN PULONG DeviceDescBufferLen,
+                        IN PUCHAR ConfigDescBuffer,
+                        IN PULONG ConfigDescBufferLen)
+{
+    PDEVICE_OBJECT PdoDevice;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PUSBPORT_DEVICE_HANDLE DeviceHandle;
+
+    NTSTATUS Status;
+
+    DPRINT("USBHI_GetUsbDescriptors ...\n");
+
+    PdoDevice = BusContext;
+    PdoExtension = PdoDevice->DeviceExtension;
+    DeviceHandle = (PUSBPORT_DEVICE_HANDLE)UsbdDeviceHandle;
+
+    if (DeviceDescBuffer && *DeviceDescBufferLen)
+    {
+        if (*DeviceDescBufferLen > sizeof(USB_DEVICE_DESCRIPTOR))
+            *DeviceDescBufferLen = sizeof(USB_DEVICE_DESCRIPTOR);
+
+        RtlCopyMemory(DeviceDescBuffer,
+                      &DeviceHandle->DeviceDescriptor,
+                      *DeviceDescBufferLen);
+    }
+
+    Status = USBPORT_GetUsbDescriptor(DeviceHandle,
+                                      PdoExtension->FdoDevice,
+                                      USB_CONFIGURATION_DESCRIPTOR_TYPE,
+                                      ConfigDescBuffer,
+                                      ConfigDescBufferLen);
+
+    USBPORT_DumpingDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)DeviceDescBuffer);
+
+    return Status;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_RemoveUsbDevice(IN PVOID BusContext,
+                      IN OUT PUSB_DEVICE_HANDLE UsbdDeviceHandle,
+                      IN ULONG Flags)
+{
+    PDEVICE_OBJECT PdoDevice;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+
+    DPRINT("USBHI_RemoveUsbDevice: UsbdDeviceHandle - %p, Flags - %x\n",
+           UsbdDeviceHandle,
+           Flags);
+
+    PdoDevice = BusContext;
+    PdoExtension = PdoDevice->DeviceExtension;
+
+    return USBPORT_RemoveDevice(PdoExtension->FdoDevice,
+                                (PUSBPORT_DEVICE_HANDLE)UsbdDeviceHandle,
+                                Flags);
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_RestoreUsbDevice(IN PVOID BusContext,
+                       OUT PUSB_DEVICE_HANDLE OldUsbdDeviceHandle,
+                       OUT PUSB_DEVICE_HANDLE NewUsbdDeviceHandle)
+{
+    PDEVICE_OBJECT PdoDevice;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+
+    DPRINT("USBHI_RestoreUsbDevice: OldUsbdDeviceHandle - %p, NewUsbdDeviceHandle - %x\n",
+           OldUsbdDeviceHandle,
+           NewUsbdDeviceHandle);
+
+    PdoDevice = BusContext;
+    PdoExtension = PdoDevice->DeviceExtension;
+
+    return USBPORT_RestoreDevice(PdoExtension->FdoDevice,
+                                (PUSBPORT_DEVICE_HANDLE)OldUsbdDeviceHandle,
+                                (PUSBPORT_DEVICE_HANDLE)NewUsbdDeviceHandle);
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_QueryDeviceInformation(IN PVOID BusContext,
+                             IN PUSB_DEVICE_HANDLE UsbdDeviceHandle,
+                             OUT PVOID DeviceInfoBuffer,
+                             IN ULONG DeviceInfoBufferLen,
+                             OUT PULONG LenDataReturned)
+{
+    PUSB_DEVICE_INFORMATION_0 DeviceInfo;
+    PUSBPORT_CONFIGURATION_HANDLE ConfigHandle;
+    PLIST_ENTRY InterfaceEntry;
+    PUSBPORT_DEVICE_HANDLE DeviceHandle;
+    ULONG NumberOfOpenPipes = 0;
+    PUSB_PIPE_INFORMATION_0 PipeInfo;
+    PUSBPORT_PIPE_HANDLE PipeHandle;
+    PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
+    ULONG ActualLength;
+    ULONG ix;
+
+    DPRINT("USBHI_QueryDeviceInformation: ... \n");
+
+    *LenDataReturned = 0;
+
+    if (DeviceInfoBufferLen < sizeof(USB_LEVEL_INFORMATION))
+    {
+        return STATUS_BUFFER_TOO_SMALL;
+    }
+
+    DeviceInfo = DeviceInfoBuffer;
+
+    if (DeviceInfo->InformationLevel > 0)
+    {
+        return STATUS_NOT_SUPPORTED;
+    }
+
+    DeviceHandle = UsbdDeviceHandle;
+    ConfigHandle = DeviceHandle->ConfigHandle;
+
+    if (ConfigHandle)
+    {
+        InterfaceEntry = ConfigHandle->InterfaceHandleList.Flink;
+
+        while (InterfaceEntry &&
+               InterfaceEntry != &ConfigHandle->InterfaceHandleList)
+        {
+            InterfaceHandle = CONTAINING_RECORD(InterfaceEntry,
+                                                USBPORT_INTERFACE_HANDLE,
+                                                InterfaceLink);
+
+            NumberOfOpenPipes += InterfaceHandle->InterfaceDescriptor.bNumEndpoints;
+
+            InterfaceEntry = InterfaceEntry->Flink;
+        }
+    }
+
+    ActualLength = sizeof(USB_DEVICE_INFORMATION_0) + 
+                   (NumberOfOpenPipes - 1) * sizeof(USB_PIPE_INFORMATION_0);
+
+    if (DeviceInfoBufferLen < ActualLength)
+    {
+        DeviceInfo->ActualLength = ActualLength;
+        *LenDataReturned = sizeof(USB_LEVEL_INFORMATION);
+
+        return STATUS_BUFFER_TOO_SMALL;
+    }
+
+    RtlZeroMemory(DeviceInfo, ActualLength);
+
+    DeviceInfo->InformationLevel = 0;
+    DeviceInfo->ActualLength = ActualLength;
+    DeviceInfo->DeviceAddress = DeviceHandle->DeviceAddress;
+    DeviceInfo->NumberOfOpenPipes = NumberOfOpenPipes;
+    DeviceInfo->DeviceSpeed = DeviceHandle->DeviceSpeed;
+
+    RtlCopyMemory(&DeviceInfo->DeviceDescriptor,
+                  &DeviceHandle->DeviceDescriptor,
+                  sizeof(USB_DEVICE_DESCRIPTOR));
+
+    USBPORT_DumpingDeviceDescriptor(&DeviceInfo->DeviceDescriptor);
+
+    if (DeviceHandle->DeviceSpeed == UsbFullSpeed ||
+        DeviceHandle->DeviceSpeed == UsbLowSpeed)
+    {
+        DeviceInfo->DeviceType = Usb11Device;
+    }
+    else if (DeviceHandle->DeviceSpeed == UsbHighSpeed)
+    {
+        DeviceInfo->DeviceType = Usb20Device;
+    }
+
+    DeviceInfo->CurrentConfigurationValue = 0;
+
+    if (!ConfigHandle)
+    {
+        *LenDataReturned = ActualLength;
+        return STATUS_SUCCESS;
+    }
+
+    DeviceInfo->CurrentConfigurationValue = 
+        ConfigHandle->ConfigurationDescriptor->bConfigurationValue;
+
+    InterfaceEntry = ConfigHandle->InterfaceHandleList.Flink;
+
+    while (InterfaceEntry &&
+           InterfaceEntry != &ConfigHandle->InterfaceHandleList)
+    {
+        InterfaceHandle = CONTAINING_RECORD(InterfaceEntry,
+                                            USBPORT_INTERFACE_HANDLE,
+                                            InterfaceLink);
+
+        if (InterfaceHandle->InterfaceDescriptor.bNumEndpoints > 0)
+        {
+            PipeInfo = &DeviceInfo->PipeList[0];
+            PipeHandle = &InterfaceHandle->PipeHandle[0];
+
+            for (ix = 0;
+                 ix < InterfaceHandle->InterfaceDescriptor.bNumEndpoints;
+                 ix++)
+            {
+                if (PipeHandle->Flags & PIPE_HANDLE_FLAG_NULL_PACKET_SIZE)
+                {
+                    PipeInfo->ScheduleOffset = 1;
+                }
+                else
+                {
+                    PipeInfo->ScheduleOffset = 
+                        PipeHandle->Endpoint->EndpointProperties.ScheduleOffset;
+                }
+
+                RtlCopyMemory(&PipeInfo->EndpointDescriptor,
+                              &PipeHandle->EndpointDescriptor,
+                              sizeof(USB_ENDPOINT_DESCRIPTOR));
+
+                PipeInfo += 1;
+                PipeHandle += 1;
+            }
+        }
+
+        InterfaceEntry = InterfaceEntry->Flink;
+    }
+
+    *LenDataReturned = ActualLength;
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_GetControllerInformation(IN PVOID BusContext,
+                               OUT PVOID ControllerInfoBuffer,
+                               IN ULONG ControllerInfoBufferLen,
+                               OUT PULONG LenDataReturned)
+{
+    PDEVICE_OBJECT PdoDevice;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSB_CONTROLLER_INFORMATION_0 InfoBuffer;
+    NTSTATUS Status;
+
+    DPRINT("USBHI_GetControllerInformation: ControllerInfoBufferLen - %x\n",
+           ControllerInfoBufferLen);
+
+    PdoDevice = BusContext;
+    PdoExtension = PdoDevice->DeviceExtension;
+    FdoDevice = PdoExtension->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    InfoBuffer = ControllerInfoBuffer;
+
+    *LenDataReturned = 0;
+
+    if (ControllerInfoBufferLen < sizeof(USB_LEVEL_INFORMATION))
+    {
+        Status = STATUS_BUFFER_TOO_SMALL;
+        return Status;
+    }
+
+    *LenDataReturned = sizeof(USB_LEVEL_INFORMATION);
+
+    if (InfoBuffer->InformationLevel > 0)
+    {
+        Status = STATUS_NOT_SUPPORTED;
+        return Status;
+    }
+
+    InfoBuffer->ActualLength = sizeof(USB_CONTROLLER_INFORMATION_0);
+
+    if (ControllerInfoBufferLen >= sizeof(USB_CONTROLLER_INFORMATION_0))
+    {
+        InfoBuffer->SelectiveSuspendEnabled = 
+            (FdoExtension->Flags & USBPORT_FLAG_SELECTIVE_SUSPEND) == 
+            USBPORT_FLAG_SELECTIVE_SUSPEND;
+    }
+
+    *LenDataReturned = sizeof(USB_CONTROLLER_INFORMATION_0);
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_ControllerSelectiveSuspend(IN PVOID BusContext,
+                                 IN BOOLEAN Enable)
+{
+    PDEVICE_OBJECT PdoDevice;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    ULONG Flags;
+    ULONG HcDisable;
+    NTSTATUS Status;
+
+    DPRINT("USBHI_ControllerSelectiveSuspend: Enable - %x\n", Enable);
+
+    PdoDevice = BusContext;
+    PdoExtension = PdoDevice->DeviceExtension;
+    FdoDevice = PdoExtension->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    Flags = FdoExtension->Flags;
+
+    if (Flags & USBPORT_FLAG_BIOS_DISABLE_SS)
+    {
+        return STATUS_SUCCESS;
+    }
+
+    if (Enable)
+    {
+        FdoExtension->Flags |= USBPORT_FLAG_SELECTIVE_SUSPEND;
+        HcDisable = 0;
+    }
+    else
+    {
+        FdoExtension->Flags &= ~USBPORT_FLAG_SELECTIVE_SUSPEND;
+        HcDisable = 1;
+    }
+
+    Status = USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
+                                         TRUE,
+                                         REG_DWORD,
+                                         L"HcDisableSelectiveSuspend",
+                                         &HcDisable,
+                                         sizeof(HcDisable));
+
+    if (NT_SUCCESS(Status))
+    {
+        if (Enable) 
+            FdoExtension->Flags |= USBPORT_FLAG_SELECTIVE_SUSPEND;
+        else
+            FdoExtension->Flags &= ~USBPORT_FLAG_SELECTIVE_SUSPEND;
+    }
+
+    return Status;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_GetExtendedHubInformation(IN PVOID BusContext,
+                                IN PDEVICE_OBJECT HubPhysicalDeviceObject,
+                                IN OUT PVOID HubInformationBuffer,
+                                IN ULONG HubInfoLen,
+                                IN OUT PULONG LenDataReturned)
+{
+    PDEVICE_OBJECT PdoDevice;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    ULONG NumPorts;
+    ULONG ix;
+    PUSB_EXTHUB_INFORMATION_0 HubInfoBuffer;
+    USBHUB_PORT_STATUS PortStatus;
+    ULONG PortAttrX;
+
+    DPRINT("USBHI_GetExtendedHubInformation: ... \n");
+
+    PdoDevice = BusContext;
+    PdoExtension = PdoDevice->DeviceExtension;
+    FdoDevice = PdoExtension->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    HubInfoBuffer = HubInformationBuffer;
+    PortStatus.AsULONG = 0;
+
+    if (HubPhysicalDeviceObject != PdoDevice)
+    {
+        *LenDataReturned = 0;
+        return STATUS_NOT_SUPPORTED;
+    }
+
+    if (HubInfoLen < sizeof(USB_EXTHUB_INFORMATION_0))
+    {
+        *LenDataReturned = 0;
+        return STATUS_BUFFER_TOO_SMALL;
+    }
+
+    NumPorts = PdoExtension->RootHubDescriptors->Descriptor.bNumberOfPorts;
+    HubInfoBuffer->NumberOfPorts = NumPorts;
+
+    if (NumPorts == 0)
+    {
+        *LenDataReturned = sizeof(USB_EXTHUB_INFORMATION_0);
+        return STATUS_SUCCESS;
+    }
+
+    for (ix = 0; ix < HubInfoBuffer->NumberOfPorts; ++ix)
+    {
+        HubInfoBuffer->Port[ix].PhysicalPortNumber = ix + 1;
+        HubInfoBuffer->Port[ix].PortLabelNumber = ix;
+        HubInfoBuffer->Port[ix].VidOverride = 0;
+        HubInfoBuffer->Port[ix].PidOverride = 0;
+        HubInfoBuffer->Port[ix].PortAttributes = 0;
+
+        if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
+        {
+            HubInfoBuffer->Port[ix].PortAttributes = USB_PORTATTR_SHARED_USB2;
+
+            Packet->RH_GetPortStatus(FdoExtension->MiniPortExt,
+                                     ix,
+                                     &PortStatus);
+
+            if (PortStatus.UsbPortStatus.Usb20PortStatus.AsUshort16 & 0x8000)
+            {
+                HubInfoBuffer->Port[ix].PortAttributes |= USB_PORTATTR_OWNED_BY_CC;
+            }
+        }
+        else
+        {
+            if (!(FdoExtension->Flags & USBPORT_FLAG_COMPANION_HC))
+            {
+                continue;
+            }
+
+            if (USBPORT_FindUSB2Controller(FdoDevice))
+            {
+                HubInfoBuffer->Port[ix].PortAttributes |= USB_PORTATTR_NO_OVERCURRENT_UI;
+            }
+        }
+    }
+
+    for (ix = 0; ix < HubInfoBuffer->NumberOfPorts; ++ix)
+    {
+        PortAttrX = 0;
+
+        USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
+                                            FdoExtension->CommonExtension.LowerPdoDevice,
+                                            FALSE,
+                                            L"PortAttrX",
+                                            sizeof(L"PortAttrX"),
+                                            &PortAttrX,
+                                            sizeof(PortAttrX));
+
+        HubInfoBuffer->Port[ix].PortAttributes |= PortAttrX;
+    }
+
+    *LenDataReturned = sizeof(USB_EXTHUB_INFORMATION_0);
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_GetRootHubSymbolicName(IN PVOID BusContext,
+                             IN OUT PVOID HubInfoBuffer,
+                             IN ULONG HubInfoBufferLen,
+                             OUT PULONG HubNameActualLen)
+{
+    PDEVICE_OBJECT PdoDevice;
+    UNICODE_STRING HubName;
+    PUNICODE_STRING InfoBuffer;
+    NTSTATUS Status;
+
+    DPRINT("USBHI_GetRootHubSymbolicName: ... \n");
+
+    PdoDevice = BusContext;
+
+    Status = USBPORT_GetSymbolicName(PdoDevice, &HubName);
+
+    if (HubInfoBufferLen < HubName.Length)
+    {
+        InfoBuffer = HubInfoBuffer;
+        InfoBuffer->Length = 0;
+    }
+    else
+    {
+        RtlCopyMemory(HubInfoBuffer, HubName.Buffer, HubName.Length);
+    }
+
+    *HubNameActualLen = HubName.Length;
+
+    if (NT_SUCCESS(Status))
+        RtlFreeUnicodeString(&HubName);
+
+    return Status;
+}
+
+PVOID
+USB_BUSIFFN
+USBHI_GetDeviceBusContext(IN PVOID BusContext,
+                          IN PVOID DeviceHandle)
+{
+    DPRINT1("USBHI_GetDeviceBusContext: UNIMPLEMENTED. FIXME. \n");
+    return NULL;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_Initialize20Hub(IN PVOID BusContext,
+                      IN PUSB_DEVICE_HANDLE UsbdHubDeviceHandle,
+                      IN ULONG TtCount)
+{
+    PDEVICE_OBJECT PdoDevice;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+
+    DPRINT("USBHI_Initialize20Hub: UsbdHubDeviceHandle - %p, TtCount - %x\n",
+           UsbdHubDeviceHandle,
+           TtCount);
+
+    PdoDevice = BusContext;
+    PdoExtension = PdoDevice->DeviceExtension;
+
+    return USBPORT_Initialize20Hub(PdoExtension->FdoDevice,
+                                   (PUSBPORT_DEVICE_HANDLE)UsbdHubDeviceHandle,
+                                   TtCount);
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBHI_RootHubInitNotification(IN PVOID BusContext,
+                              IN PVOID CallbackContext,
+                              IN PRH_INIT_CALLBACK CallbackFunction)
+{
+    PDEVICE_OBJECT PdoDevice;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    KIRQL OldIrql;
+
+    DPRINT("USBHI_RootHubInitNotification \n");
+
+    PdoDevice = BusContext;
+    PdoExtension = PdoDevice->DeviceExtension;
+    FdoDevice = PdoExtension->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    KeAcquireSpinLock(&FdoExtension->RootHubCallbackSpinLock, &OldIrql);
+    PdoExtension->RootHubInitContext = CallbackContext;
+    PdoExtension->RootHubInitCallback = CallbackFunction;
+    KeReleaseSpinLock(&FdoExtension->RootHubCallbackSpinLock, OldIrql);
+
+    return STATUS_SUCCESS;
+}
+
+VOID
+USB_BUSIFFN
+USBHI_FlushTransfers(IN PVOID BusContext,
+                     OUT PUSB_DEVICE_HANDLE UsbdDeviceHandle)
+{
+    PDEVICE_OBJECT PdoDevice;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+
+    DPRINT("USBHI_FlushTransfers: ... \n");
+
+    PdoDevice = BusContext;
+    PdoExtension = PdoDevice->DeviceExtension;
+
+    USBPORT_BadRequestFlush(PdoExtension->FdoDevice);
+}
+
+VOID
+USB_BUSIFFN
+USBHI_SetDeviceHandleData(IN PVOID BusContext,
+                          IN PVOID DeviceHandle,
+                          IN PDEVICE_OBJECT UsbDevicePdo)
+{
+    DPRINT1("USBHI_SetDeviceHandleData: UNIMPLEMENTED. FIXME. \n");
+}
+
+/* USB bus driver Interface functions */
+
+VOID
+USB_BUSIFFN
+USBDI_GetUSBDIVersion(IN PVOID BusContext,
+                      OUT PUSBD_VERSION_INFORMATION VersionInfo,
+                      OUT PULONG HcdCapabilities)
+{
+    DPRINT1("USBDI_GetUSBDIVersion: UNIMPLEMENTED. FIXME. \n");
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBDI_QueryBusTime(IN PVOID BusContext,
+                   OUT PULONG CurrentFrame)
+{
+    DPRINT1("USBDI_QueryBusTime: UNIMPLEMENTED. FIXME. \n");
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBDI_SubmitIsoOutUrb(IN PVOID BusContext,
+                      IN PURB Urb)
+{
+    DPRINT1("USBDI_SubmitIsoOutUrb: UNIMPLEMENTED. FIXME. \n");
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBDI_QueryBusInformation(IN PVOID BusContext,
+                          IN ULONG Level,
+                          OUT PVOID BusInfoBuffer,
+                          OUT PULONG BusInfoBufferLen,
+                          OUT PULONG BusInfoActualLen)
+{
+    PDEVICE_OBJECT PdoDevice;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    SIZE_T Length;
+    PUSB_BUS_INFORMATION_LEVEL_1 Buffer1;
+
+    DPRINT("USBDI_QueryBusInformation: Level - %p\n", Level);
+
+    if ((Level != 0) || (Level != 1))
+    {
+        DPRINT1("USBDI_QueryBusInformation: Level should be 0 or 1\n");
+        return STATUS_NOT_SUPPORTED;
+    }
+
+    PdoDevice = BusContext;
+    PdoExtension = PdoDevice->DeviceExtension;
+    FdoDevice = PdoExtension->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    if (Level == 0)
+    {
+        if (BusInfoActualLen)
+            *BusInfoActualLen = sizeof(USB_BUS_INFORMATION_LEVEL_0);
+
+        if (*BusInfoBufferLen < sizeof(USB_BUS_INFORMATION_LEVEL_0))
+        {
+            return STATUS_BUFFER_TOO_SMALL;
+        }
+
+        *BusInfoBufferLen = sizeof(USB_BUS_INFORMATION_LEVEL_0);
+
+        //Buffer0 = BusInfoBuffer;
+        DPRINT1("USBDI_QueryBusInformation: LEVEL_0 UNIMPLEMENTED. FIXME\n");
+        //Buffer0->TotalBandwidth = USBPORT_GetTotalBandwidth();
+        //Buffer0->ConsumedBandwidth = USBPORT_GetAllocatedBandwidth();
+
+        return STATUS_SUCCESS;
+    }
+
+    if (Level == 1)
+    {
+        Length = sizeof(USB_BUS_INFORMATION_LEVEL_1) + 
+                 FdoExtension->CommonExtension.SymbolicLinkName.Length;
+
+        if (BusInfoActualLen)
+            *BusInfoActualLen = Length;
+
+        if (*BusInfoBufferLen < Length)
+        {
+            return STATUS_BUFFER_TOO_SMALL;
+        }
+
+        *BusInfoBufferLen = Length;
+
+        Buffer1 = BusInfoBuffer;
+        DPRINT1("USBDI_QueryBusInformation: LEVEL_1 UNIMPLEMENTED. FIXME\n");
+        //Buffer1->TotalBandwidth = USBPORT_GetTotalBandwidth();
+        //Buffer1->ConsumedBandwidth = USBPORT_GetAllocatedBandwidth();
+        Buffer1->ControllerNameLength = FdoExtension->CommonExtension.SymbolicLinkName.Length;
+
+        RtlCopyMemory(&Buffer1->ControllerNameUnicodeString,
+                      FdoExtension->CommonExtension.SymbolicLinkName.Buffer,
+                      FdoExtension->CommonExtension.SymbolicLinkName.Length);
+
+        return STATUS_SUCCESS;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+BOOLEAN
+USB_BUSIFFN
+USBDI_IsDeviceHighSpeed(IN PVOID BusContext)
+{
+    PDEVICE_OBJECT PdoDevice;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+
+    DPRINT("USBDI_IsDeviceHighSpeed: ... \n");
+
+    PdoDevice = BusContext;
+    PdoExtension = PdoDevice->DeviceExtension;
+    FdoDevice = PdoExtension->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    return (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2) != 0;
+}
+
+NTSTATUS
+USB_BUSIFFN
+USBDI_EnumLogEntry(IN PVOID BusContext,
+                   IN ULONG DriverTag,
+                   IN ULONG EnumTag,
+                   IN ULONG P1,
+                   IN ULONG P2)
+{
+    DPRINT1("USBDI_EnumLogEntry: UNIMPLEMENTED. FIXME. \n");
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_PdoQueryInterface(IN PDEVICE_OBJECT FdoDevice,
+                          IN PDEVICE_OBJECT PdoDevice,
+                          IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
+    PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub;
+    PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI;
+    UNICODE_STRING GuidBuffer;
+    NTSTATUS Status;
+
+    DPRINT("USBPORT_PdoQueryInterface: ... \n");
+
+    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);
+
+            return STATUS_NOT_SUPPORTED; // Version not supported
+        }
+
+        /* Interface version 0 */
+        InterfaceHub->Size = IoStack->Parameters.QueryInterface.Size;
+        InterfaceHub->BusContext = PdoDevice;
+
+        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);
+
+            return STATUS_NOT_SUPPORTED; // Version not supported
+        }
+
+        /* Interface version 0 */
+        InterfaceDI->Size = IoStack->Parameters.QueryInterface.Size;
+        InterfaceDI->BusContext = PdoDevice;
+        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;
+
+        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);
+            
+            RtlFreeUnicodeString(&GuidBuffer); // Free GUID buffer
+        }
+    }
+
+    return STATUS_NOT_SUPPORTED;
+}
diff --git a/reactos/drivers/usb/usbport/ioctl.c b/reactos/drivers/usb/usbport/ioctl.c
new file mode 100644 (file)
index 0000000..96142c7
--- /dev/null
@@ -0,0 +1,451 @@
+#include "usbport.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+VOID
+NTAPI
+USBPORT_UserGetHcName(IN PDEVICE_OBJECT FdoDevice,
+                      IN PUSBUSER_CONTROLLER_UNICODE_NAME ControllerName,
+                      IN PUSB_UNICODE_NAME UnicodeName)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    ULONG Length;
+    NTSTATUS Status;
+    ULONG ResultLength;
+
+    DPRINT("USBPORT_UserGetHcName: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    Length = ControllerName->Header.RequestBufferLength -
+             sizeof(USBUSER_CONTROLLER_UNICODE_NAME);
+
+    RtlZeroMemory(UnicodeName, Length);
+
+    Status = IoGetDeviceProperty(FdoExtension->CommonExtension.LowerPdoDevice,
+                                 DevicePropertyDriverKeyName,
+                                 Length,
+                                 UnicodeName->String,
+                                 &ResultLength);
+
+    if (!NT_SUCCESS(Status))
+    {
+        if (Status == STATUS_BUFFER_TOO_SMALL)
+        {
+            ControllerName->Header.UsbUserStatusCode = UsbUserBufferTooSmall;
+        }
+        else
+        {
+            ControllerName->Header.UsbUserStatusCode = UsbUserInvalidParameter;
+        }
+    }
+    else
+    {
+        ControllerName->Header.UsbUserStatusCode = UsbUserSuccess;
+        UnicodeName->Length = ResultLength + sizeof(UNICODE_NULL);
+    }
+
+    ControllerName->Header.ActualBufferLength = sizeof(USBUSER_CONTROLLER_UNICODE_NAME) +
+                                                ResultLength;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_GetSymbolicName(IN PDEVICE_OBJECT RootHubPdo,
+                        IN PUNICODE_STRING DestinationString)
+{
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PUNICODE_STRING RootHubName;
+    PWCHAR Buffer;
+    SIZE_T LengthName;
+    SIZE_T Length;
+    PWSTR SourceString;
+    WCHAR Character;
+
+    DPRINT("USBPORT_GetSymbolicName: ... \n");
+
+    PdoExtension = RootHubPdo->DeviceExtension;
+    RootHubName = &PdoExtension->CommonExtension.SymbolicLinkName;
+    Buffer = RootHubName->Buffer;
+
+    if (!Buffer)
+    {
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    LengthName = RootHubName->Length;
+
+    SourceString = ExAllocatePoolWithTag(PagedPool, LengthName, USB_PORT_TAG);
+
+    if (!SourceString)
+    {
+        RtlInitUnicodeString(DestinationString, NULL);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    RtlZeroMemory(SourceString, LengthName);
+
+    if (*Buffer == L'\\')
+    {
+         Buffer += 1;
+
+        if (*Buffer == L'\\')
+        {
+            Buffer += 1;
+            goto Exit;
+        }
+
+        Character = *Buffer;
+
+        do
+        {
+            if (Character == UNICODE_NULL)
+            {
+                break;
+            }
+
+            Buffer += 1;
+            Character = *Buffer;
+        }
+        while (*Buffer != L'\\');
+
+        if (*Buffer == L'\\')
+        {
+            Buffer += 1;
+        }
+
+Exit:
+        Length = (ULONG_PTR)Buffer - (ULONG_PTR)RootHubName->Buffer;
+    }
+    else
+    {
+        Length = 0;
+    }
+
+    RtlCopyMemory(SourceString,
+                  (PVOID)((ULONG_PTR)RootHubName->Buffer + Length),
+                  RootHubName->Length - Length);
+
+    RtlInitUnicodeString(DestinationString, SourceString);
+
+    DPRINT("USBPORT_RegisterDeviceInterface: DestinationString  - %wZ\n",
+           DestinationString);
+
+    return STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+USBPORT_UserGetRootHubName(IN PDEVICE_OBJECT FdoDevice,
+                           IN PUSBUSER_CONTROLLER_UNICODE_NAME RootHubName,
+                           IN PUSB_UNICODE_NAME UnicodeName)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    UNICODE_STRING UnicodeString;
+    ULONG Length;
+    ULONG ResultLength = 0;
+    NTSTATUS Status;
+
+    DPRINT("USBPORT_UserGetRootHubName: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    Length = RootHubName->Header.RequestBufferLength -
+             sizeof(USBUSER_CONTROLLER_UNICODE_NAME);
+
+    RtlZeroMemory(UnicodeName, Length);
+
+    Status = USBPORT_GetSymbolicName(FdoExtension->RootHubPdo, &UnicodeString);
+
+    if (NT_SUCCESS(Status))
+    {
+        ResultLength = UnicodeString.Length;
+
+        if (UnicodeString.Length > Length)
+        {
+            UnicodeString.Length = Length;
+            Status = STATUS_BUFFER_TOO_SMALL;
+        }
+
+        if (UnicodeString.Length)
+        {
+            RtlCopyMemory(UnicodeName->String,
+                          UnicodeString.Buffer,
+                          UnicodeString.Length);
+        }
+
+        RtlFreeUnicodeString(&UnicodeString);
+    }
+
+    if (!NT_SUCCESS(Status))
+    {
+        if (Status == STATUS_BUFFER_TOO_SMALL)
+        {
+            RootHubName->Header.UsbUserStatusCode = UsbUserBufferTooSmall;
+        }
+        else
+        {
+            RootHubName->Header.UsbUserStatusCode = UsbUserInvalidParameter;
+        }
+    }
+    else
+    {
+        RootHubName->Header.UsbUserStatusCode = UsbUserSuccess;
+        UnicodeName->Length = ResultLength + sizeof(UNICODE_NULL);
+    }
+
+    RootHubName->Header.ActualBufferLength = sizeof(USBUSER_CONTROLLER_UNICODE_NAME) +
+                                             ResultLength;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_GetUnicodeName(IN PDEVICE_OBJECT FdoDevice,
+                       IN PIRP Irp,
+                       IN PULONG Information)
+{
+    PUSB_HCD_DRIVERKEY_NAME DriverKey;
+    PIO_STACK_LOCATION IoStack;
+    ULONG OutputBufferLength;
+    ULONG IoControlCode;
+    ULONG Length;
+    PUSBUSER_CONTROLLER_UNICODE_NAME ControllerName;
+    PUSB_UNICODE_NAME UnicodeName;
+    ULONG ActualLength;
+
+    DPRINT("USBPORT_GetUnicodeName: ... \n");
+
+    *Information = 0;
+    DriverKey = Irp->AssociatedIrp.SystemBuffer;
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    OutputBufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
+    IoControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
+
+    if (OutputBufferLength < sizeof(USB_UNICODE_NAME))
+    {
+        return STATUS_BUFFER_TOO_SMALL;
+    }
+
+    Length = sizeof(USBUSER_CONTROLLER_UNICODE_NAME);
+
+    while (TRUE)
+    {
+        ControllerName = ExAllocatePoolWithTag(PagedPool,
+                                               Length,
+                                               USB_PORT_TAG);
+
+        if (!ControllerName)
+        {
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
+
+        RtlZeroMemory(ControllerName, Length);
+
+        ControllerName->Header.RequestBufferLength = Length;
+        UnicodeName = &ControllerName->UnicodeName;
+
+        if (IoControlCode == IOCTL_GET_HCD_DRIVERKEY_NAME)
+        {
+            ControllerName->Header.UsbUserRequest = USBUSER_GET_CONTROLLER_DRIVER_KEY;
+            USBPORT_UserGetHcName(FdoDevice, ControllerName, UnicodeName);
+        }
+        else
+        {
+            ControllerName->Header.UsbUserRequest = USBUSER_GET_ROOTHUB_SYMBOLIC_NAME;
+            USBPORT_UserGetRootHubName(FdoDevice, ControllerName, UnicodeName);
+        }
+
+        if (ControllerName->Header.UsbUserStatusCode != UsbUserBufferTooSmall)
+        {
+            break;
+        }
+
+        Length = ControllerName->Header.ActualBufferLength;
+
+        ExFreePoolWithTag(ControllerName, USB_PORT_TAG);
+    }
+
+    if (ControllerName->Header.UsbUserStatusCode != UsbUserSuccess)
+    {
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    ActualLength = sizeof(ULONG) + ControllerName->UnicodeName.Length;
+
+    DriverKey->ActualLength = ActualLength;
+
+    if (OutputBufferLength < ActualLength)
+    {
+        DriverKey->DriverKeyName[0] = UNICODE_NULL;
+        *Information = sizeof(USB_UNICODE_NAME);
+    }
+    else
+    {
+        RtlCopyMemory(DriverKey->DriverKeyName,
+                      ControllerName->UnicodeName.String,
+                      ControllerName->UnicodeName.Length);
+
+        *Information = DriverKey->ActualLength;
+    }
+
+    ExFreePoolWithTag(ControllerName, USB_PORT_TAG);
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_PdoDeviceControl(IN PDEVICE_OBJECT PdoDevice,
+                         IN PIRP Irp)
+{
+    DPRINT1("USBPORT_PdoDeviceControl: UNIMPLEMENTED. FIXME. \n");
+    return 0;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_PdoInternalDeviceControl(IN PDEVICE_OBJECT PdoDevice,
+                                 IN PIRP Irp)
+{
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PIO_STACK_LOCATION IoStack;
+    ULONG IoCtl;
+    NTSTATUS Status;
+
+    PdoExtension = PdoDevice->DeviceExtension;
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    IoCtl = IoStack->Parameters.DeviceIoControl.IoControlCode;
+
+    DPRINT("USBPORT_PdoInternalDeviceControl: PdoDevice - %p, Irp - %p, IoCtl - %x\n",
+           PdoDevice,
+           Irp,
+           IoCtl);
+
+    if (IoCtl == IOCTL_INTERNAL_USB_SUBMIT_URB)
+    {
+        return USBPORT_HandleSubmitURB(PdoDevice, Irp, URB_FROM_IRP(Irp));
+    }
+
+    if (IoCtl == IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO)
+    {
+        DPRINT("USBPORT_PdoInternalDeviceControl: IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
+
+        if (IoStack->Parameters.Others.Argument1)
+            *(PVOID *)IoStack->Parameters.Others.Argument1 = PdoDevice;
+
+        if (IoStack->Parameters.Others.Argument2)
+            *(PVOID *)IoStack->Parameters.Others.Argument2 = PdoDevice;
+
+        Status = STATUS_SUCCESS;
+        goto Exit;
+    }
+
+    if (IoCtl == IOCTL_INTERNAL_USB_GET_HUB_COUNT)
+    {
+        DPRINT("USBPORT_PdoInternalDeviceControl: IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
+
+        if (IoStack->Parameters.Others.Argument1)
+        {
+            ++*(PULONG)IoStack->Parameters.Others.Argument1;
+        }
+
+        Status = STATUS_SUCCESS;
+        goto Exit;
+    }
+
+    if (IoCtl == IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE)
+    {
+        DPRINT("USBPORT_PdoInternalDeviceControl: IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
+
+        if (IoStack->Parameters.Others.Argument1)
+        {
+            *(PVOID *)IoStack->Parameters.Others.Argument1 = &PdoExtension->DeviceHandle;
+        }
+
+        Status = STATUS_SUCCESS;
+        goto Exit;
+    }
+
+    if (IoCtl == IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION)
+    {
+        DPRINT("USBPORT_PdoInternalDeviceControl: IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION\n");
+        return USBPORT_IdleNotification(PdoDevice, Irp);
+    }
+
+    DPRINT("USBPORT_PdoInternalDeviceControl: INVALID INTERNAL DEVICE CONTROL\n");
+    Status = STATUS_INVALID_DEVICE_REQUEST;
+
+Exit:
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_FdoDeviceControl(IN PDEVICE_OBJECT FdoDevice,
+                         IN PIRP Irp)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PIO_STACK_LOCATION IoStack;
+    ULONG ControlCode;
+    NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
+    ULONG_PTR Information = 0;
+
+    DPRINT("USBPORT_FdoDeviceControl: Irp - %p\n", Irp);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    ControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
+
+    switch (ControlCode)
+    {
+        case IOCTL_USB_DIAGNOSTIC_MODE_ON:
+            DPRINT("USBPORT_FdoDeviceControl: IOCTL_USB_DIAGNOSTIC_MODE_ON\n");
+            FdoExtension->Flags |= USBPORT_FLAG_DIAGNOSTIC_MODE;
+            break;
+
+        case IOCTL_USB_DIAGNOSTIC_MODE_OFF:
+            DPRINT("USBPORT_FdoDeviceControl: IOCTL_USB_DIAGNOSTIC_MODE_OFF\n");
+            FdoExtension->Flags &= ~USBPORT_FLAG_DIAGNOSTIC_MODE;
+            break;
+
+        case IOCTL_USB_GET_NODE_INFORMATION:
+            DPRINT1("USBPORT_FdoDeviceControl: IOCTL_USB_GET_NODE_INFORMATION\n");
+            Status = USBPORT_GetUnicodeName(FdoDevice, Irp, &Information);
+            break;
+
+        case IOCTL_GET_HCD_DRIVERKEY_NAME:
+            DPRINT1("USBPORT_FdoDeviceControl: IOCTL_GET_HCD_DRIVERKEY_NAME\n");
+            Status = USBPORT_GetUnicodeName(FdoDevice, Irp, &Information);
+            break;
+
+        case IOCTL_USB_USER_REQUEST:
+            DPRINT1("USBPORT_FdoDeviceControl: IOCTL_USB_USER_REQUEST UNIMPLEMENTED. FIXME\n");
+            break;
+
+        default:
+            DPRINT1("USBPORT_FdoDeviceControl: Not supported IoControlCode - %x\n",
+                    ControlCode);
+            Status = STATUS_INVALID_DEVICE_REQUEST;
+            break;
+    }
+
+    Irp->IoStatus.Status = Status;
+    Irp->IoStatus.Information = Information;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_FdoInternalDeviceControl(IN PDEVICE_OBJECT FdoDevice,
+                                 IN PIRP Irp)
+{
+    DPRINT1("USBPORT_FdoInternalDeviceControl: UNIMPLEMENTED. FIXME. \n");
+    return 0;
+}
diff --git a/reactos/drivers/usb/usbport/pnp.c b/reactos/drivers/usb/usbport/pnp.c
new file mode 100644 (file)
index 0000000..844e7db
--- /dev/null
@@ -0,0 +1,1792 @@
+#include "usbport.h"
+
+#define NDEBUG
+#include <debug.h>
+
+#define NDEBUG_USBPORT_CORE
+#include "usbdebug.h"
+
+IO_COMPLETION_ROUTINE USBPORT_FdoStartCompletion;
+
+NTSTATUS
+NTAPI
+USBPORT_FdoStartCompletion(IN PDEVICE_OBJECT DeviceObject,
+                           IN PIRP Irp,
+                           IN PVOID Context)
+{
+    KeSetEvent((PKEVENT)Context, EVENT_INCREMENT, FALSE);
+    return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_RegisterDeviceInterface(IN PDEVICE_OBJECT PdoDevice,
+                                IN PDEVICE_OBJECT DeviceObject,
+                                IN CONST GUID *InterfaceClassGuid,
+                                IN BOOLEAN Enable)
+{
+    PUSBPORT_RHDEVICE_EXTENSION DeviceExtension;
+    PUNICODE_STRING SymbolicLinkName;
+    NTSTATUS Status;
+
+    DPRINT("USBPORT_RegisterDeviceInterface: Enable - %x\n", Enable);
+
+    DeviceExtension = DeviceObject->DeviceExtension;
+    SymbolicLinkName = &DeviceExtension->CommonExtension.SymbolicLinkName;
+
+    if (Enable)
+    {
+        Status = IoRegisterDeviceInterface(PdoDevice,
+                                           InterfaceClassGuid,
+                                           NULL,
+                                           SymbolicLinkName);
+
+        if (NT_SUCCESS(Status))
+        {
+            DeviceExtension->CommonExtension.IsInterfaceEnabled = 1;
+
+            Status = USBPORT_SetRegistryKeyValue(PdoDevice,
+                                                 FALSE,
+                                                 REG_SZ,
+                                                 L"SymbolicName",
+                                                 SymbolicLinkName->Buffer,
+                                                 SymbolicLinkName->Length);
+
+            if (NT_SUCCESS(Status))
+            {
+                DPRINT("USBPORT_RegisterDeviceInterface: LinkName  - %wZ\n",
+                       &DeviceExtension->CommonExtension.SymbolicLinkName);
+
+                Status = IoSetDeviceInterfaceState(SymbolicLinkName, TRUE);
+            }
+        }
+    }
+    else
+    {
+        /* Disable device interface */
+        Status = IoSetDeviceInterfaceState(SymbolicLinkName, FALSE);
+
+        if (NT_SUCCESS(Status))
+        {
+            RtlFreeUnicodeString(SymbolicLinkName);
+            DeviceExtension->CommonExtension.IsInterfaceEnabled = 0; // Disabled interface
+        }
+    }
+
+    return Status;
+}
+
+BOOLEAN
+NTAPI
+USBPORT_IsSelectiveSuspendEnabled(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    ULONG Disabled = 0;
+
+    DPRINT("USBPORT_IsSelectiveSuspendEnabled: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
+                                        FdoExtension->CommonExtension.LowerPdoDevice,
+                                        TRUE,
+                                        L"HcDisableSelectiveSuspend",
+                                        sizeof(L"HcDisableSelectiveSuspend"),
+                                        &Disabled,
+                                        sizeof(Disabled));
+
+    return (Disabled == 0);
+}
+
+NTSTATUS
+NTAPI
+USBPORT_GetConfigValue(IN PWSTR ValueName,
+                       IN ULONG ValueType,
+                       IN PVOID ValueData,
+                       IN ULONG ValueLength,
+                       IN PVOID Context,
+                       IN PVOID EntryContext)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    DPRINT("USBPORT_GetConfigValue \n");
+
+    if (ValueType == REG_DWORD)
+    {
+        *(PULONG)EntryContext = *(PULONG)ValueData;
+    }
+    else
+    {
+        Status = STATUS_INVALID_PARAMETER;
+    }
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_GetDefaultBIOSx(IN PDEVICE_OBJECT FdoDevice,
+                         IN PULONG UsbBIOSx,
+                         IN PULONG DisableSelectiveSuspend,
+                         IN PULONG DisableCcDetect,
+                         IN PULONG IdleEpSupport,
+                         IN PULONG IdleEpSupportEx,
+                         IN PULONG SoftRetry)
+{
+    RTL_QUERY_REGISTRY_TABLE QueryTable[7];
+
+    DPRINT("USBPORT_GetDefaultBIOS_X: ... \n");
+
+    RtlZeroMemory(QueryTable, sizeof(QueryTable));
+
+    *UsbBIOSx = 2;
+
+    QueryTable[0].QueryRoutine = USBPORT_GetConfigValue;
+    QueryTable[0].Flags = 0;
+    QueryTable[0].Name = L"UsbBIOSx";
+    QueryTable[0].EntryContext = UsbBIOSx;
+    QueryTable[0].DefaultType = REG_DWORD;
+    QueryTable[0].DefaultData = UsbBIOSx;
+    QueryTable[0].DefaultLength = sizeof(ULONG);
+
+    QueryTable[1].QueryRoutine = USBPORT_GetConfigValue;
+    QueryTable[1].Flags = 0;
+    QueryTable[1].Name = L"DisableSelectiveSuspend";
+    QueryTable[1].EntryContext = DisableSelectiveSuspend;
+    QueryTable[1].DefaultType = REG_DWORD;
+    QueryTable[1].DefaultData = DisableSelectiveSuspend;
+    QueryTable[1].DefaultLength = sizeof(ULONG);
+
+    QueryTable[2].QueryRoutine = USBPORT_GetConfigValue;
+    QueryTable[2].Flags = 0;
+    QueryTable[2].Name = L"DisableCcDetect";
+    QueryTable[2].EntryContext = DisableCcDetect;
+    QueryTable[2].DefaultType = REG_DWORD;
+    QueryTable[2].DefaultData = DisableCcDetect;
+    QueryTable[2].DefaultLength = sizeof(ULONG);
+
+    QueryTable[3].QueryRoutine = USBPORT_GetConfigValue;
+    QueryTable[3].Flags = 0;
+    QueryTable[3].Name = L"EnIdleEndpointSupport";
+    QueryTable[3].EntryContext = IdleEpSupport;
+    QueryTable[3].DefaultType = REG_DWORD;
+    QueryTable[3].DefaultData = IdleEpSupport;
+    QueryTable[3].DefaultLength = sizeof(ULONG);
+
+    QueryTable[4].QueryRoutine = USBPORT_GetConfigValue;
+    QueryTable[4].Flags = 0;
+    QueryTable[4].Name = L"EnIdleEndpointSupportEx";
+    QueryTable[4].EntryContext = IdleEpSupportEx;
+    QueryTable[4].DefaultType = REG_DWORD;
+    QueryTable[4].DefaultData = IdleEpSupportEx;
+    QueryTable[4].DefaultLength = sizeof(ULONG);
+
+    QueryTable[5].QueryRoutine = USBPORT_GetConfigValue;
+    QueryTable[5].Flags = 0;
+    QueryTable[5].Name = L"EnSoftRetry";
+    QueryTable[5].EntryContext = SoftRetry;
+    QueryTable[5].DefaultType = REG_DWORD;
+    QueryTable[5].DefaultData = SoftRetry;
+    QueryTable[5].DefaultLength = sizeof(ULONG);
+
+    return RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
+                                  L"usb",
+                                  QueryTable,
+                                  NULL,
+                                  NULL);
+}
+
+NTSTATUS
+NTAPI
+USBPORT_IsCompanionController(IN PDEVICE_OBJECT DeviceObject,
+                              IN BOOLEAN *IsCompanion)
+{
+    PDEVICE_OBJECT HighestDevice;
+    PIRP Irp;
+    KEVENT Event;
+    PIO_STACK_LOCATION IoStack;
+    PCI_DEVICE_PRESENT_INTERFACE PciInterface = {0};
+    PCI_DEVICE_PRESENCE_PARAMETERS Parameters   = {0};
+    IO_STATUS_BLOCK IoStatusBlock;
+    NTSTATUS Status;
+    BOOLEAN IsPresent;
+
+    DPRINT("USBPORT_IsCompanionController: ... \n");
+
+    *IsCompanion = FALSE;
+
+    KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+
+    HighestDevice = IoGetAttachedDeviceReference(DeviceObject);
+
+    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
+                                       HighestDevice,
+                                       NULL,
+                                       0,
+                                       NULL,
+                                       &Event,
+                                       &IoStatusBlock);
+
+    if (!Irp)
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        ObDereferenceObject(HighestDevice);
+        return Status;
+    }
+
+    IoStack = IoGetNextIrpStackLocation(Irp);
+
+    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+    Irp->IoStatus.Information = 0;
+
+    IoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
+
+    IoStack->Parameters.QueryInterface.InterfaceType = &GUID_PCI_DEVICE_PRESENT_INTERFACE;
+    IoStack->Parameters.QueryInterface.Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
+    IoStack->Parameters.QueryInterface.Version = 1;
+    IoStack->Parameters.QueryInterface.Interface = (PINTERFACE)&PciInterface;
+    IoStack->Parameters.QueryInterface.InterfaceSpecificData = 0;
+
+    Status = IoCallDriver(HighestDevice, Irp);
+
+    if (Status == STATUS_PENDING)
+    {
+        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+        Status = IoStatusBlock.Status;
+    }
+
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("USBPORT_IsCompanionController: query interface failed\\n");
+        ObDereferenceObject(HighestDevice);
+        return Status;
+    }
+
+    DPRINT("USBPORT_IsCompanionController: query interface succeeded\n");
+
+    if (PciInterface.Size < sizeof(PCI_DEVICE_PRESENT_INTERFACE))
+    {
+        DPRINT1("USBPORT_IsCompanionController: old version\n");
+        ObDereferenceObject(HighestDevice);
+        return Status;
+    }
+
+    Parameters.Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
+
+    Parameters.BaseClass = PCI_CLASS_SERIAL_BUS_CTLR;
+    Parameters.SubClass = PCI_SUBCLASS_SB_USB;
+    Parameters.ProgIf = PCI_INTERFACE_USB_ID_EHCI;
+
+    Parameters.Flags = PCI_USE_LOCAL_BUS |
+                       PCI_USE_LOCAL_DEVICE |
+                       PCI_USE_CLASS_SUBCLASS |
+                       PCI_USE_PROGIF;
+
+    IsPresent = (PciInterface.IsDevicePresentEx)(PciInterface.Context,
+                                                 &Parameters);
+
+    if (IsPresent)
+    {
+        DPRINT("USBPORT_IsCompanionController: Present EHCI controller for FDO - %p\n",
+               DeviceObject);
+    }
+    else
+    {
+        DPRINT("USBPORT_IsCompanionController: No EHCI controller for FDO - %p\n",
+               DeviceObject);
+    }
+
+    *IsCompanion = IsPresent;
+
+    (PciInterface.InterfaceDereference)(PciInterface.Context);
+
+    ObDereferenceObject(HighestDevice);
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_QueryPciBusInterface(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PBUS_INTERFACE_STANDARD BusInterface;
+    PIO_STACK_LOCATION IoStack;
+    IO_STATUS_BLOCK IoStatusBlock;
+    PDEVICE_OBJECT HighestDevice;
+    KEVENT Event;
+    PIRP Irp;
+    NTSTATUS Status;
+
+    DPRINT("USBPORT_QueryPciBusInterface: ...  \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    BusInterface = &FdoExtension->BusInterface;
+
+    RtlZeroMemory(BusInterface, sizeof(BUS_INTERFACE_STANDARD));
+    KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+    HighestDevice = IoGetAttachedDeviceReference(FdoDevice);
+
+    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
+                                       HighestDevice,
+                                       NULL,
+                                       0,
+                                       NULL,
+                                       &Event,
+                                       &IoStatusBlock);
+
+    if (Irp)
+    {
+        IoStack = IoGetNextIrpStackLocation(Irp);
+
+        Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+        Irp->IoStatus.Information = 0;
+
+        IoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
+
+        IoStack->Parameters.QueryInterface.InterfaceType = &GUID_BUS_INTERFACE_STANDARD;
+        IoStack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
+        IoStack->Parameters.QueryInterface.Version = 1;
+        IoStack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterface;
+        IoStack->Parameters.QueryInterface.InterfaceSpecificData = 0;
+
+        Status = IoCallDriver(HighestDevice, Irp);
+
+        if (Status == STATUS_PENDING)
+        {
+            KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+            Status = IoStatusBlock.Status;
+        }
+    }
+    else
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    ObDereferenceObject(HighestDevice);
+
+    DPRINT("USBPORT_QueryPciBusInterface: return Status - %x\n", Status);
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_QueryCapabilities(IN PDEVICE_OBJECT FdoDevice,
+                          IN PDEVICE_CAPABILITIES Capabilities)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtention;
+    PIRP Irp;
+    NTSTATUS Status;
+    PIO_STACK_LOCATION IoStack;
+    KEVENT Event;
+
+    DPRINT("USBPORT_QueryCapabilities: ... \n");
+
+    FdoExtention = FdoDevice->DeviceExtension;
+
+    RtlZeroMemory(Capabilities, sizeof(DEVICE_CAPABILITIES));
+
+    Capabilities->Size     = sizeof(DEVICE_CAPABILITIES);
+    Capabilities->Version  = 1;
+    Capabilities->Address  = MAXULONG;
+    Capabilities->UINumber = MAXULONG;
+
+    Irp = IoAllocateIrp(FdoExtention->CommonExtension.LowerDevice->StackSize,
+                        FALSE);
+
+    if (!Irp)
+    {
+        DPRINT1("USBPORT_QueryCapabilities: No resources - IoAllocateIrp!\n");
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+
+    IoStack = IoGetNextIrpStackLocation(Irp);
+    IoStack->MajorFunction = IRP_MJ_PNP;
+    IoStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
+
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+    IoSetCompletionRoutine(Irp,
+                          USBPORT_FdoStartCompletion,
+                          &Event,
+                          TRUE,
+                          TRUE,
+                          TRUE);
+
+    IoStack->Parameters.DeviceCapabilities.Capabilities = Capabilities;
+
+    Status = IoCallDriver(FdoExtention->CommonExtension.LowerDevice, Irp);
+
+    if (Status == STATUS_PENDING)
+    {
+        KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
+        Status = Irp->IoStatus.Status;
+    }
+
+    if (NT_SUCCESS(Status) && Capabilities)
+    {
+        USBPORT_DumpingCapabilities(Capabilities);
+    }
+
+    IoFreeIrp(Irp);
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_CreateLegacySymbolicLink(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    WCHAR CharName[255] = {0};
+    WCHAR CharDosName[255] = {0};
+    UNICODE_STRING DeviceName;
+    NTSTATUS Status;
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    RtlStringCbPrintfW(CharName,
+                       sizeof(CharName),
+                       L"\\Device\\USBFDO-%d",
+                       FdoExtension->FdoNameNumber);
+
+    RtlInitUnicodeString(&DeviceName, CharName);
+
+    RtlStringCbPrintfW(CharDosName,
+                       sizeof(CharDosName),
+                       L"\\DosDevices\\HCD%d",
+                       FdoExtension->FdoNameNumber);
+
+    RtlInitUnicodeString(&FdoExtension->DosDeviceSymbolicName, CharDosName);
+
+    DPRINT("USBPORT_CreateLegacySymbolicLink: DeviceName - %wZ, DosSymbolicName - %wZ\n",
+           &DeviceName,
+           &FdoExtension->DosDeviceSymbolicName);
+
+    Status = IoCreateSymbolicLink(&FdoExtension->DosDeviceSymbolicName,
+                                  &DeviceName);
+
+    if (NT_SUCCESS(Status))
+    {
+        FdoExtension->Flags |= USBPORT_FLAG_DOS_SYMBOLIC_NAME;
+    }
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_StopDevice(IN PDEVICE_OBJECT FdoDevice)
+{
+    DPRINT1("USBPORT_StopDevice: UNIMPLEMENTED. FIXME\n");
+    DbgBreakPoint();
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_StartDevice(IN PDEVICE_OBJECT FdoDevice,
+                    IN PUSBPORT_RESOURCES UsbPortResources)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    NTSTATUS Status;
+    PCI_COMMON_CONFIG PciConfig;
+    ULONG BytesRead;
+    DEVICE_DESCRIPTION DeviceDescription;
+    PDMA_ADAPTER DmaAdapter = NULL;
+    ULONG MiniPortStatus;
+    PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer;
+    ULONG ResultLength;
+    ULONG DisableSelectiveSuspend = 0;
+    ULONG DisableCcDetect = 0;
+    ULONG IdleEpSupport = 0;
+    ULONG IdleEpSupportEx = 0;
+    ULONG SoftRetry = 0;
+    ULONG Limit2GB = 0;
+    ULONG TotalBusBandwidth = 0;
+    BOOLEAN IsCompanion = FALSE;
+    ULONG LegacyBIOS;
+    ULONG MiniportFlags;
+
+    DPRINT("USBPORT_StartDevice: FdoDevice - %p, UsbPortResources - %p\n",
+           FdoDevice,
+           UsbPortResources);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    Status = USBPORT_QueryPciBusInterface(FdoDevice);
+    if (!NT_SUCCESS(Status))
+        goto ExitWithError;
+
+    BytesRead = (*FdoExtension->BusInterface.GetBusData)(FdoExtension->BusInterface.Context,
+                                                         PCI_WHICHSPACE_CONFIG,
+                                                         &PciConfig,
+                                                         0,
+                                                         PCI_COMMON_HDR_LENGTH);
+
+    if (BytesRead != PCI_COMMON_HDR_LENGTH)
+    {
+        DPRINT1("USBPORT_StartDevice: Failed to get pci config information!\n");
+        goto ExitWithError;
+    }
+
+    FdoExtension->VendorID = PciConfig.VendorID;
+    FdoExtension->DeviceID = PciConfig.DeviceID;
+    FdoExtension->RevisionID = PciConfig.RevisionID;
+    FdoExtension->ProgIf = PciConfig.ProgIf;
+    FdoExtension->SubClass = PciConfig.SubClass;
+    FdoExtension->BaseClass = PciConfig.BaseClass;
+
+    RtlZeroMemory(&DeviceDescription, sizeof(DeviceDescription));
+
+    DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
+    DeviceDescription.Master = TRUE;
+    DeviceDescription.ScatterGather = TRUE;
+    DeviceDescription.Dma32BitAddresses = TRUE;
+    DeviceDescription.InterfaceType = PCIBus;
+    DeviceDescription.DmaWidth = Width32Bits;
+    DeviceDescription.DmaSpeed = Compatible;
+    DeviceDescription.MaximumLength = MAXULONG;
+
+    DmaAdapter = IoGetDmaAdapter(FdoExtension->CommonExtension.LowerPdoDevice,
+                                 &DeviceDescription,
+                                 &FdoExtension->NumberMapRegs);
+
+    FdoExtension->DmaAdapter = DmaAdapter;
+
+    if (!DmaAdapter)
+    {
+        DPRINT1("USBPORT_StartDevice: Failed to get DmaAdapter!\n");
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto ExitWithError;
+    }
+
+    Status = USBPORT_CreateWorkerThread(FdoDevice);
+    if (!NT_SUCCESS(Status))
+        goto ExitWithError;
+
+    Status = USBPORT_QueryCapabilities(FdoDevice, &FdoExtension->Capabilities);
+    if (!NT_SUCCESS(Status))
+        goto ExitWithError;
+
+    FdoExtension->PciDeviceNumber = FdoExtension->Capabilities.Address >> 16;
+    FdoExtension->PciFunctionNumber = FdoExtension->Capabilities.Address & 0xFFFF;
+
+    Status = IoGetDeviceProperty(FdoExtension->CommonExtension.LowerPdoDevice,
+                                 DevicePropertyBusNumber,
+                                 sizeof(ULONG),
+                                 &FdoExtension->BusNumber,
+                                 &ResultLength);
+
+    if (!NT_SUCCESS(Status))
+        goto ExitWithError;
+
+    KeInitializeSpinLock(&FdoExtension->EndpointListSpinLock);
+    KeInitializeSpinLock(&FdoExtension->EpStateChangeSpinLock);
+    KeInitializeSpinLock(&FdoExtension->EndpointClosedSpinLock);
+    KeInitializeSpinLock(&FdoExtension->DeviceHandleSpinLock);
+    KeInitializeSpinLock(&FdoExtension->IdleIoCsqSpinLock);
+    KeInitializeSpinLock(&FdoExtension->BadRequestIoCsqSpinLock);
+    KeInitializeSpinLock(&FdoExtension->MapTransferSpinLock);
+    KeInitializeSpinLock(&FdoExtension->FlushTransferSpinLock);
+    KeInitializeSpinLock(&FdoExtension->FlushPendingTransferSpinLock);
+    KeInitializeSpinLock(&FdoExtension->DoneTransferSpinLock);
+    KeInitializeSpinLock(&FdoExtension->WorkerThreadEventSpinLock);
+    KeInitializeSpinLock(&FdoExtension->MiniportSpinLock);
+    KeInitializeSpinLock(&FdoExtension->TimerFlagsSpinLock);
+    KeInitializeSpinLock(&FdoExtension->PowerWakeSpinLock);
+    KeInitializeSpinLock(&FdoExtension->SetPowerD0SpinLock);
+    KeInitializeSpinLock(&FdoExtension->RootHubCallbackSpinLock);
+
+    KeInitializeDpc(&FdoExtension->IsrDpc, USBPORT_IsrDpc, FdoDevice);
+
+    KeInitializeDpc(&FdoExtension->TransferFlushDpc,
+                    USBPORT_TransferFlushDpc,
+                    FdoDevice);
+
+    KeInitializeDpc(&FdoExtension->WorkerRequestDpc,
+                    USBPORT_WorkerRequestDpc,
+                    FdoDevice);
+
+    KeInitializeDpc(&FdoExtension->HcWakeDpc,
+                    USBPORT_HcWakeDpc,
+                    FdoDevice);
+
+    IoCsqInitialize(&FdoExtension->IdleIoCsq,
+                    USBPORT_InsertIdleIrp,
+                    USBPORT_RemoveIdleIrp,
+                    USBPORT_PeekNextIdleIrp,
+                    USBPORT_AcquireIdleLock,
+                    USBPORT_ReleaseIdleLock,
+                    USBPORT_CompleteCanceledIdleIrp);
+
+    IoCsqInitialize(&FdoExtension->BadRequestIoCsq,
+                    USBPORT_InsertBadRequest,
+                    USBPORT_RemoveBadRequest,
+                    USBPORT_PeekNextBadRequest,
+                    USBPORT_AcquireBadRequestLock,
+                    USBPORT_ReleaseBadRequestLock,
+                    USBPORT_CompleteCanceledBadRequest);
+
+    FdoExtension->IsrDpcCounter = -1;
+    FdoExtension->IsrDpcHandlerCounter = -1;
+    FdoExtension->IdleLockCounter = -1;
+    FdoExtension->BadRequestLockCounter = -1;
+    FdoExtension->ChirpRootPortLock = -1;
+
+    FdoExtension->RHInitCallBackLock = 0;
+
+    FdoExtension->UsbAddressBitMap[0] = 1;
+    FdoExtension->UsbAddressBitMap[1] = 0;
+    FdoExtension->UsbAddressBitMap[2] = 0;
+    FdoExtension->UsbAddressBitMap[3] = 0;
+
+    USBPORT_GetDefaultBIOSx(FdoDevice,
+                            &FdoExtension->UsbBIOSx,
+                            &DisableSelectiveSuspend,
+                            &DisableCcDetect,
+                            &IdleEpSupport,
+                            &IdleEpSupportEx,
+                            &SoftRetry);
+
+    if (DisableSelectiveSuspend)
+        FdoExtension->Flags |= USBPORT_FLAG_BIOS_DISABLE_SS;
+
+    if (!DisableSelectiveSuspend &&
+        USBPORT_IsSelectiveSuspendEnabled(FdoDevice))
+    {
+        FdoExtension->Flags |= USBPORT_FLAG_SELECTIVE_SUSPEND;
+    }
+
+    MiniportFlags = Packet->MiniPortFlags;
+
+    if (MiniportFlags & USB_MINIPORT_FLAGS_POLLING)
+        FdoExtension->Flags |= USBPORT_FLAG_HC_POLLING;
+
+    if (MiniportFlags & USB_MINIPORT_FLAGS_WAKE_SUPPORT)
+        FdoExtension->Flags |= USBPORT_FLAG_HC_WAKE_SUPPORT;
+
+    if (MiniportFlags & USB_MINIPORT_FLAGS_DISABLE_SS)
+        FdoExtension->Flags = (FdoExtension->Flags & ~USBPORT_FLAG_SELECTIVE_SUSPEND) |
+                              USBPORT_FLAG_BIOS_DISABLE_SS;
+
+    USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
+                                TRUE,
+                                REG_DWORD,
+                                L"EnIdleEndpointSupport",
+                                &IdleEpSupport,
+                                sizeof(IdleEpSupport));
+
+    USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
+                                TRUE,
+                                REG_DWORD,
+                                L"EnIdleEndpointSupportEx",
+                                &IdleEpSupportEx,
+                                sizeof(IdleEpSupportEx));
+
+    USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
+                                TRUE,
+                                REG_DWORD,
+                                L"EnSoftRetry",
+                                &SoftRetry,
+                                sizeof(SoftRetry));
+
+    USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
+                                        FdoExtension->CommonExtension.LowerPdoDevice,
+                                        TRUE,
+                                        L"CommonBuffer2GBLimit",
+                                        sizeof(L"CommonBuffer2GBLimit"),
+                                        &Limit2GB,
+                                        sizeof(Limit2GB));
+
+    FdoExtension->CommonBufferLimit = (Limit2GB != 0);
+
+    if (FdoExtension->BaseClass == PCI_CLASS_SERIAL_BUS_CTLR &&
+        FdoExtension->SubClass == PCI_SUBCLASS_SB_USB  &&
+        FdoExtension->ProgIf < PCI_INTERFACE_USB_ID_EHCI)
+    {
+        Status = USBPORT_IsCompanionController(FdoDevice, &IsCompanion);
+
+        if (!NT_SUCCESS(Status))
+        {
+            if (IsCompanion)
+            {
+                FdoExtension->Flags |= USBPORT_FLAG_COMPANION_HC;
+            }
+            else
+            {
+                FdoExtension->Flags &= ~USBPORT_FLAG_COMPANION_HC;
+            }
+        }
+    }
+
+    if (DisableCcDetect)
+    {
+        FdoExtension->Flags &= ~USBPORT_FLAG_COMPANION_HC;
+    }
+
+    TotalBusBandwidth = Packet->MiniPortBusBandwidth;
+    FdoExtension->TotalBusBandwidth = TotalBusBandwidth;
+
+    USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
+                                        FdoExtension->CommonExtension.LowerPdoDevice,
+                                        TRUE,
+                                        L"TotalBusBandwidth",
+                                        sizeof(L"TotalBusBandwidth"),
+                                        &TotalBusBandwidth,
+                                        sizeof(TotalBusBandwidth));
+
+    if (TotalBusBandwidth != FdoExtension->TotalBusBandwidth)
+    {
+        FdoExtension->TotalBusBandwidth = TotalBusBandwidth;
+    }
+
+    FdoExtension->ActiveIrpTable = ExAllocatePoolWithTag(NonPagedPool,
+                                                         sizeof(USBPORT_IRP_TABLE),
+                                                         USB_PORT_TAG);
+
+    if (!FdoExtension->ActiveIrpTable)
+    {
+        DPRINT1("USBPORT_StartDevice: Allocate ActiveIrpTable failed!\n");
+        goto ExitWithError;
+    }
+
+    RtlZeroMemory(FdoExtension->ActiveIrpTable, sizeof(USBPORT_IRP_TABLE));
+
+    FdoExtension->PendingIrpTable = ExAllocatePoolWithTag(NonPagedPool,
+                                                          sizeof(USBPORT_IRP_TABLE),
+                                                          USB_PORT_TAG);
+
+    if (!FdoExtension->PendingIrpTable)
+    {
+        DPRINT1("USBPORT_StartDevice: Allocate PendingIrpTable failed!\n");
+        goto ExitWithError;
+    }
+
+    RtlZeroMemory(FdoExtension->PendingIrpTable, sizeof(USBPORT_IRP_TABLE));
+
+    Status = IoConnectInterrupt(&FdoExtension->InterruptObject,
+                                USBPORT_InterruptService,
+                                (PVOID)FdoDevice,
+                                0,
+                                UsbPortResources->InterruptVector,
+                                UsbPortResources->InterruptLevel,
+                                UsbPortResources->InterruptLevel,
+                                UsbPortResources->InterruptMode,
+                                UsbPortResources->ShareVector,
+                                UsbPortResources->InterruptAffinity,
+                                0);
+
+
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("USBPORT_StartDevice: IoConnectInterrupt failed!\n");
+        goto ExitWithError;
+    }
+
+    FdoExtension->Flags &= ~USBPORT_FLAG_INT_CONNECTED;
+
+    if (Packet->MiniPortExtensionSize)
+    {
+        RtlZeroMemory(FdoExtension->MiniPortExt, Packet->MiniPortExtensionSize);
+    }
+
+    if (Packet->MiniPortResourcesSize)
+    {
+        HeaderBuffer = USBPORT_AllocateCommonBuffer(FdoDevice,
+                                                    Packet->MiniPortResourcesSize);
+
+        if (!HeaderBuffer)
+        {
+            DPRINT1("USBPORT_StartDevice: Failed to AllocateCommonBuffer!\n");
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto ExitWithError;
+        }
+
+        UsbPortResources->StartVA = (PVOID)HeaderBuffer->VirtualAddress;
+        UsbPortResources->StartPA = (PVOID)HeaderBuffer->PhysicalAddress;
+
+        FdoExtension->MiniPortCommonBuffer = HeaderBuffer;
+    }
+    else
+    {
+        FdoExtension->MiniPortCommonBuffer = NULL;
+    }
+
+    MiniPortStatus = Packet->StartController(FdoExtension->MiniPortExt,
+                                             UsbPortResources);
+
+    if (UsbPortResources->LegacySupport)
+    {
+        FdoExtension->Flags |= USBPORT_FLAG_LEGACY_SUPPORT;
+        LegacyBIOS = 1;
+    }
+    else
+    {
+        LegacyBIOS = 0;
+    }
+
+    USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
+                                FALSE,
+                                REG_DWORD,
+                                L"DetectedLegacyBIOS",
+                                &LegacyBIOS,
+                                sizeof(LegacyBIOS));
+
+    if (MiniPortStatus)
+    {
+        DPRINT1("USBPORT_StartDevice: Failed to Start MiniPort. MiniPortStatus - %x\n",
+                MiniPortStatus);
+
+        if (FdoExtension->Flags & USBPORT_FLAG_INT_CONNECTED)
+        {
+            IoDisconnectInterrupt(FdoExtension->InterruptObject);
+            FdoExtension->Flags &= ~USBPORT_FLAG_INT_CONNECTED;
+        }
+
+        if (FdoExtension->MiniPortCommonBuffer)
+        {
+            USBPORT_FreeCommonBuffer(FdoDevice, FdoExtension->MiniPortCommonBuffer);
+            FdoExtension->MiniPortCommonBuffer = NULL;
+        }
+
+        goto ExitWithError;
+    }
+    else
+    {
+        FdoExtension->MiniPortFlags |= USBPORT_MPFLAG_INTERRUPTS_ENABLED;
+        USBPORT_MiniportInterrupts(FdoDevice, TRUE);
+    }
+
+    FdoExtension->TimerValue = 500;
+    USBPORT_StartTimer((PVOID)FdoDevice, 500);
+
+    Status = USBPORT_RegisterDeviceInterface(FdoExtension->CommonExtension.LowerPdoDevice,
+                                             FdoDevice,
+                                             &GUID_DEVINTERFACE_USB_HOST_CONTROLLER,
+                                             TRUE);
+
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("USBPORT_StartDevice: RegisterDeviceInterface failed!\n");
+        goto ExitWithError;
+    }
+
+    USBPORT_CreateLegacySymbolicLink(FdoDevice);
+
+    FdoExtension->Flags |= USBPORT_FLAG_HC_STARTED;
+
+    DPRINT("USBPORT_StartDevice: Exit Status - %p\n", Status);
+    return Status;
+
+ExitWithError:
+    USBPORT_StopDevice(FdoDevice);
+
+    DPRINT1("USBPORT_StartDevice: ExitWithError Status - %lx\n", Status);
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_ParseResources(IN PDEVICE_OBJECT FdoDevice,
+                       IN PIRP Irp,
+                       IN PUSBPORT_RESOURCES UsbPortResources)
+{
+    PCM_RESOURCE_LIST AllocatedResourcesTranslated;
+    PCM_PARTIAL_RESOURCE_LIST ResourceList;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR PortDescriptor = NULL;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR MemoryDescriptor = NULL;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR InterruptDescriptor = NULL;
+    PIO_STACK_LOCATION IoStack;
+    ULONG ix;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    DPRINT("USBPORT_ParseResources: ... \n");
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    AllocatedResourcesTranslated = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
+
+    if (AllocatedResourcesTranslated)
+    {
+        RtlZeroMemory(UsbPortResources, sizeof(USBPORT_RESOURCES));
+
+        ResourceList = &AllocatedResourcesTranslated->List[0].PartialResourceList;
+
+        PartialDescriptor = &ResourceList->PartialDescriptors[0];
+
+        for (ix = 0; ix < ResourceList->Count; ++ix)
+        {
+            if (PartialDescriptor->Type == CmResourceTypePort)
+            {
+                if (!PortDescriptor)
+                    PortDescriptor = PartialDescriptor;
+            }
+            else if (PartialDescriptor->Type == CmResourceTypeInterrupt)
+            {
+                if (!InterruptDescriptor)
+                    InterruptDescriptor = PartialDescriptor;
+            }
+            else if (PartialDescriptor->Type == CmResourceTypeMemory)
+            {
+                if (!MemoryDescriptor)
+                    MemoryDescriptor = PartialDescriptor;
+            }
+
+            PartialDescriptor += 1;
+        }
+
+        if (PortDescriptor)
+        {
+            if (PortDescriptor->Flags & CM_RESOURCE_PORT_IO)
+            {
+                UsbPortResources->ResourceBase = (PVOID)PortDescriptor->u.Port.Start.LowPart;
+            }
+            else
+            {
+                UsbPortResources->ResourceBase = MmMapIoSpace(PortDescriptor->u.Port.Start,
+                                                              PortDescriptor->u.Port.Length,
+                                                              0);
+            }
+
+            UsbPortResources->IoSpaceLength = PortDescriptor->u.Port.Length;
+
+            if (UsbPortResources->ResourceBase)
+            {
+                UsbPortResources->ResourcesTypes |= USBPORT_RESOURCES_PORT;
+            }
+            else
+            {
+                Status = STATUS_NONE_MAPPED;
+            }
+        }
+
+        if (MemoryDescriptor && NT_SUCCESS(Status))
+        {
+            UsbPortResources->IoSpaceLength = MemoryDescriptor->u.Memory.Length;
+
+            UsbPortResources->ResourceBase = MmMapIoSpace(MemoryDescriptor->u.Memory.Start,
+                                                          MemoryDescriptor->u.Memory.Length,
+                                                          0);
+
+            if (UsbPortResources->ResourceBase)
+            {
+                UsbPortResources->ResourcesTypes |= USBPORT_RESOURCES_MEMORY;
+            }
+            else
+            {
+                Status = STATUS_NONE_MAPPED;
+            }
+        }
+
+        if (InterruptDescriptor && NT_SUCCESS(Status))
+        {
+            UsbPortResources->ResourcesTypes |= USBPORT_RESOURCES_INTERRUPT;
+
+            UsbPortResources->InterruptVector = InterruptDescriptor->u.Interrupt.Vector;
+            UsbPortResources->InterruptLevel = InterruptDescriptor->u.Interrupt.Level;
+            UsbPortResources->InterruptAffinity = InterruptDescriptor->u.Interrupt.Affinity;
+
+            UsbPortResources->ShareVector = InterruptDescriptor->ShareDisposition ==
+                                            CmResourceShareShared;
+
+            UsbPortResources->InterruptMode = InterruptDescriptor->Flags == 
+                                              CM_RESOURCE_INTERRUPT_LATCHED;
+        }
+    }
+    else
+    {
+        Status = STATUS_NONE_MAPPED;
+    }
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_CreatePdo(IN PDEVICE_OBJECT FdoDevice,
+                  OUT PDEVICE_OBJECT *RootHubPdo)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    UNICODE_STRING DeviceName;
+    ULONG DeviceNumber = 0;
+    PDEVICE_OBJECT DeviceObject = NULL;
+    WCHAR CharDeviceName[64];
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    DPRINT("USBPORT_CreatePdo: FdoDevice - %p, RootHubPdo - %p\n",
+           FdoDevice,
+           RootHubPdo);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    do
+    {
+        RtlStringCbPrintfW(CharDeviceName,
+                           sizeof(CharDeviceName),
+                           L"\\Device\\USBPDO-%d",
+                           DeviceNumber);
+
+        RtlInitUnicodeString(&DeviceName, CharDeviceName);
+
+        DPRINT("USBPORT_CreatePdo: DeviceName - %wZ\n", &DeviceName);
+
+        Status = IoCreateDevice(FdoExtension->MiniPortInterface->DriverObject,
+                                sizeof(USBPORT_RHDEVICE_EXTENSION),
+                                &DeviceName,
+                                FILE_DEVICE_BUS_EXTENDER,
+                                0,
+                                FALSE,
+                                &DeviceObject);
+
+        ++DeviceNumber;
+    }
+    while (Status == STATUS_OBJECT_NAME_COLLISION);
+
+    if (!NT_SUCCESS(Status))
+    {
+        *RootHubPdo = NULL;
+        DPRINT1("USBPORT_CreatePdo: Filed create HubPdo!\n");
+        return Status;
+    }
+
+    if (DeviceObject)
+    {
+        PdoExtension = DeviceObject->DeviceExtension;
+
+        RtlZeroMemory(PdoExtension, sizeof(USBPORT_RHDEVICE_EXTENSION));
+
+        PdoExtension->CommonExtension.SelfDevice = DeviceObject;
+        PdoExtension->CommonExtension.IsPDO = TRUE;
+
+        PdoExtension->FdoDevice = FdoDevice;
+        PdoExtension->PdoNameNumber = DeviceNumber;
+
+        USBPORT_AdjustDeviceCapabilities(FdoDevice, DeviceObject);
+
+        DeviceObject->StackSize = FdoDevice->StackSize;
+
+        DeviceObject->Flags |= DO_POWER_PAGABLE;
+        DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+    }
+    else
+    {
+        Status = STATUS_UNSUCCESSFUL;
+    }
+
+    if (!NT_SUCCESS(Status))
+        *RootHubPdo = NULL;
+    else
+        *RootHubPdo = DeviceObject;
+
+    DPRINT("USBPORT_CreatePdo: HubPdo - %p\n", DeviceObject);
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_FdoPnP(IN PDEVICE_OBJECT FdoDevice,
+               IN PIRP Irp)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_COMMON_DEVICE_EXTENSION FdoCommonExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    PUSBPORT_RESOURCES UsbPortResources;
+    PIO_STACK_LOCATION IoStack;
+    UCHAR Minor;
+    KEVENT Event;
+    NTSTATUS Status;
+    DEVICE_RELATION_TYPE RelationType;
+    PDEVICE_RELATIONS DeviceRelations;
+    PDEVICE_OBJECT RootHubPdo;
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    FdoCommonExtension = &FdoExtension->CommonExtension;
+    UsbPortResources = &FdoExtension->UsbPortResources;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    Minor = IoStack->MinorFunction;
+
+    DPRINT("USBPORT_FdoPnP: FdoDevice - %p, Minor - %x\n", FdoDevice, Minor);
+
+    RelationType = IoStack->Parameters.QueryDeviceRelations.Type;
+
+    switch (Minor)
+    {
+        case IRP_MN_START_DEVICE:
+            DPRINT("IRP_MN_START_DEVICE\n");
+
+            KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+            IoCopyCurrentIrpStackLocationToNext(Irp);
+
+            IoSetCompletionRoutine(Irp,
+                                   USBPORT_FdoStartCompletion,
+                                   &Event,
+                                   TRUE,
+                                   TRUE,
+                                   TRUE);
+
+            Status = IoCallDriver(FdoCommonExtension->LowerDevice,
+                                  Irp);
+
+            if (Status == STATUS_PENDING)
+            {
+                KeWaitForSingleObject(&Event,
+                                      Suspended,
+                                      KernelMode,
+                                      FALSE,
+                                      NULL);
+
+                Status = Irp->IoStatus.Status;
+            }
+
+            if (!NT_SUCCESS(Status))
+            {
+                goto Exit;
+            }
+
+            Status = USBPORT_ParseResources(FdoDevice,
+                                            Irp,
+                                            UsbPortResources);
+
+            if (!NT_SUCCESS(Status))
+            {
+                FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_STOPPED;
+                goto Exit;
+            }
+
+            Status = USBPORT_StartDevice(FdoDevice, UsbPortResources);
+
+            if (!NT_SUCCESS(Status))
+            {
+                FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_STOPPED;
+                goto Exit;
+            }
+
+            FdoCommonExtension->PnpStateFlags &= ~USBPORT_PNP_STATE_NOT_INIT;
+            FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_STARTED;
+
+            FdoCommonExtension->DevicePowerState = PowerDeviceD0;
+
+            if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
+            {
+                USBPORT_AddUSB2Fdo(FdoDevice);
+            }
+            else
+            {
+                USBPORT_AddUSB1Fdo(FdoDevice);
+            }
+
+Exit:
+            Irp->IoStatus.Status = Status;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            return Status;
+
+        case IRP_MN_QUERY_REMOVE_DEVICE:
+            DPRINT("IRP_MN_QUERY_REMOVE_DEVICE\n");
+            if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
+            {
+                DPRINT1("USBPORT_FdoPnP: Haction registry write FIXME\n");
+            }
+
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+            goto ForwardIrp;
+
+        case IRP_MN_REMOVE_DEVICE:
+            DPRINT("USBPORT_FdoPnP: IRP_MN_REMOVE_DEVICE\n");
+            FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_FAILED;
+
+            if (FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_STARTED &&
+               !(FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_NOT_INIT))
+            {
+                DPRINT1("USBPORT_FdoPnP: stop fdo FIXME\n");
+                FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_NOT_INIT;
+            }
+
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+            IoSkipCurrentIrpStackLocation(Irp);
+            Status = IoCallDriver(FdoCommonExtension->LowerDevice, Irp);
+
+            IoDetachDevice(FdoCommonExtension->LowerDevice);
+
+            RootHubPdo = FdoExtension->RootHubPdo;
+
+            IoDeleteDevice(FdoDevice);
+
+            if (RootHubPdo)
+            {
+                IoDeleteDevice(RootHubPdo);
+            }
+
+            return Status;
+
+        case IRP_MN_CANCEL_REMOVE_DEVICE:
+            DPRINT("IRP_MN_CANCEL_REMOVE_DEVICE\n");
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+            goto ForwardIrp;
+
+        case IRP_MN_STOP_DEVICE:
+            DPRINT("IRP_MN_STOP_DEVICE\n");
+            if (FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_STARTED)
+            {
+                DPRINT1("USBPORT_FdoPnP: stop fdo FIXME\n");
+
+                FdoCommonExtension->PnpStateFlags &= ~USBPORT_PNP_STATE_STARTED;
+                FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_NOT_INIT;
+            }
+
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+            goto ForwardIrp;
+
+        case IRP_MN_QUERY_STOP_DEVICE:
+            DPRINT("IRP_MN_QUERY_STOP_DEVICE\n");
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+            goto ForwardIrp;
+
+        case IRP_MN_CANCEL_STOP_DEVICE:
+            DPRINT("IRP_MN_CANCEL_STOP_DEVICE\n");
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+            goto ForwardIrp;
+
+        case IRP_MN_QUERY_DEVICE_RELATIONS:
+            DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n");
+            if (RelationType == BusRelations)
+            {
+                DeviceRelations = ExAllocatePoolWithTag(PagedPool,
+                                                        sizeof(DEVICE_RELATIONS),
+                                                        USB_PORT_TAG);
+
+                if (!DeviceRelations)
+                {
+                    Status = STATUS_INSUFFICIENT_RESOURCES;
+                    Irp->IoStatus.Status = Status;
+                    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                    return Status;
+                }
+
+                DeviceRelations->Count = 0;
+                DeviceRelations->Objects[0] = NULL;
+
+                if (!FdoExtension->RootHubPdo)
+                {
+                    Status = USBPORT_CreatePdo(FdoDevice,
+                                               &FdoExtension->RootHubPdo);
+
+                    if (!NT_SUCCESS(Status))
+                    {
+                        ExFreePoolWithTag(DeviceRelations, USB_PORT_TAG);
+                        goto ForwardIrp;
+                    }
+                }
+                else
+                {
+                    Status = STATUS_SUCCESS;
+                }
+
+                DeviceRelations->Count = 1;
+                DeviceRelations->Objects[0] = FdoExtension->RootHubPdo;
+
+                ObReferenceObject(FdoExtension->RootHubPdo);
+                Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
+            }
+            else
+            {
+                if (RelationType == RemovalRelations)
+                {
+                    DPRINT1("USBPORT_FdoPnP: FIXME IRP_MN_QUERY_DEVICE_RELATIONS/RemovalRelations\n");
+                }
+
+                goto ForwardIrp;
+            }
+
+            Irp->IoStatus.Status = Status;
+            goto ForwardIrp;
+
+        case IRP_MN_QUERY_INTERFACE:
+            DPRINT("IRP_MN_QUERY_INTERFACE\n");
+            goto ForwardIrp;
+
+        case IRP_MN_QUERY_CAPABILITIES:
+            DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
+            goto ForwardIrp;
+
+        case IRP_MN_QUERY_RESOURCES:
+            DPRINT("IRP_MN_QUERY_RESOURCES\n");
+            goto ForwardIrp;
+
+        case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
+            DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
+            goto ForwardIrp;
+
+        case IRP_MN_QUERY_DEVICE_TEXT:
+            DPRINT("IRP_MN_QUERY_DEVICE_TEXT\n");
+            goto ForwardIrp;
+
+        case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
+            DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
+            goto ForwardIrp;
+
+        case IRP_MN_READ_CONFIG:
+            DPRINT("IRP_MN_READ_CONFIG\n");
+            goto ForwardIrp;
+
+        case IRP_MN_WRITE_CONFIG:
+            DPRINT("IRP_MN_WRITE_CONFIG\n");
+            goto ForwardIrp;
+
+        case IRP_MN_EJECT:
+            DPRINT("IRP_MN_EJECT\n");
+            goto ForwardIrp;
+
+        case IRP_MN_SET_LOCK:
+            DPRINT("IRP_MN_SET_LOCK\n");
+            goto ForwardIrp;
+
+        case IRP_MN_QUERY_ID:
+            DPRINT("IRP_MN_QUERY_ID\n");
+            goto ForwardIrp;
+
+        case IRP_MN_QUERY_PNP_DEVICE_STATE:
+            DPRINT("IRP_MN_QUERY_PNP_DEVICE_STATE\n");
+            goto ForwardIrp;
+
+        case IRP_MN_QUERY_BUS_INFORMATION:
+            DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
+            goto ForwardIrp;
+
+        case IRP_MN_DEVICE_USAGE_NOTIFICATION:
+            DPRINT("IRP_MN_DEVICE_USAGE_NOTIFICATION\n");
+            goto ForwardIrp;
+
+        case IRP_MN_SURPRISE_REMOVAL:
+            DPRINT1("IRP_MN_SURPRISE_REMOVAL\n");
+            if (!(FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_FAILED))
+            {
+                USBPORT_InvalidateControllerHandler(FdoDevice,
+                                                    INVALIDATE_CONTROLLER_SURPRISE_REMOVE);
+            }
+            goto ForwardIrp;
+
+        default:
+            DPRINT("unknown IRP_MN_???\n");
+ForwardIrp:
+            /* forward irp to next device object */
+            IoSkipCurrentIrpStackLocation(Irp);
+            break;
+    }
+
+    return IoCallDriver(FdoCommonExtension->LowerDevice, Irp);
+}
+
+PVOID
+NTAPI
+USBPORT_GetDeviceHwIds(IN PDEVICE_OBJECT FdoDevice,
+                       IN USHORT VendorID,
+                       IN USHORT DeviceID,
+                       IN USHORT RevisionID)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    PVOID Id;
+    WCHAR Buffer[300] = {0};
+    ULONG Length = 0;
+    size_t Remaining = sizeof(Buffer);
+    PWCHAR EndBuffer;
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    DPRINT("USBPORT_GetDeviceHwIds: FdoDevice - %p, Packet->MiniPortFlags - %p\n",
+           FdoDevice,
+           Packet->MiniPortFlags);
+
+    if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
+    {
+        RtlStringCbPrintfExW(Buffer,
+                             Remaining,
+                             &EndBuffer,
+                             &Remaining,
+                             0,
+                             L"USB\\ROOT_HUB20&VID%04x&PID%04x&REV%04x",
+                             VendorID,
+                             DeviceID,
+                             RevisionID);
+
+        EndBuffer++;
+        Remaining -= sizeof(UNICODE_NULL);
+
+        RtlStringCbPrintfExW(EndBuffer,
+                             Remaining,
+                             &EndBuffer,
+                             &Remaining,
+                             0,
+                             L"USB\\ROOT_HUB20&VID%04x&PID%04x",
+                             VendorID,
+                             DeviceID);
+
+        EndBuffer++;
+        Remaining -= sizeof(UNICODE_NULL);
+
+        RtlStringCbPrintfExW(EndBuffer,
+                             Remaining,
+                             NULL,
+                             &Remaining,
+                             0,
+                             L"USB\\ROOT_HUB20");
+    }
+    else
+    {
+        RtlStringCbPrintfExW(Buffer,
+                             Remaining,
+                             &EndBuffer,
+                             &Remaining,
+                             0,
+                             L"USB\\ROOT_HUB&VID%04x&PID%04x&REV%04x",
+                             VendorID,
+                             DeviceID,
+                             RevisionID);
+
+        EndBuffer++;
+        Remaining -= sizeof(UNICODE_NULL);
+
+        RtlStringCbPrintfExW(EndBuffer,
+                             Remaining,
+                             &EndBuffer,
+                             &Remaining,
+                             0,
+                             L"USB\\ROOT_HUB&VID%04x&PID%04x",
+                             VendorID,
+                             DeviceID);
+
+        EndBuffer++;
+        Remaining -= sizeof(UNICODE_NULL);
+
+        RtlStringCbPrintfExW(EndBuffer,
+                             Remaining,
+                             NULL,
+                             &Remaining,
+                             0,
+                             L"USB\\ROOT_HUB");
+    }
+
+    Length = (sizeof(Buffer) - Remaining + sizeof(UNICODE_NULL));
+
+     /* for debug only */
+    if (FALSE)
+    {
+        DPRINT("Hardware IDs:\n");
+        USBPORT_DumpingIDs(Buffer);
+    }
+
+    Id = ExAllocatePoolWithTag(PagedPool, Length, USB_PORT_TAG);
+
+    if (!Id)
+        return NULL;
+
+    RtlMoveMemory(Id, Buffer, Length);
+
+    return Id;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_PdoPnP(IN PDEVICE_OBJECT PdoDevice,
+               IN PIRP Irp)
+{
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PUSBPORT_COMMON_DEVICE_EXTENSION PdoCommonExtension;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PIO_STACK_LOCATION IoStack;
+    UCHAR Minor;
+    NTSTATUS Status;
+    PPNP_BUS_INFORMATION BusInformation;
+    PDEVICE_CAPABILITIES DeviceCapabilities;
+
+    PdoExtension = PdoDevice->DeviceExtension;
+    PdoCommonExtension = &PdoExtension->CommonExtension;
+
+    FdoDevice = PdoExtension->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    Minor = IoStack->MinorFunction;
+
+    Status = Irp->IoStatus.Status;
+
+    DPRINT("USBPORT_PdoPnP: PdoDevice - %p, Minor - %x\n", PdoDevice, Minor);
+
+    switch (Minor)
+    {
+        case IRP_MN_START_DEVICE:
+            DPRINT("IRP_MN_START_DEVICE\n");
+
+            Status = USBPORT_RootHubCreateDevice(FdoDevice, PdoDevice);
+
+            if (NT_SUCCESS(Status))
+            {
+                Status = USBPORT_RegisterDeviceInterface(PdoDevice,
+                                                         PdoDevice,
+                                                         &GUID_DEVINTERFACE_USB_HUB,
+                                                         TRUE);
+
+                if (NT_SUCCESS(Status))
+                {
+                    PdoCommonExtension->DevicePowerState = PowerDeviceD0;
+                    PdoCommonExtension->PnpStateFlags = USBPORT_PNP_STATE_STARTED;
+                }
+            }
+
+            break;
+
+        case IRP_MN_QUERY_REMOVE_DEVICE:
+            DPRINT("USBPORT_PdoPnP: IRP_MN_QUERY_REMOVE_DEVICE\n");
+            Status = STATUS_SUCCESS;
+            break;
+
+        case IRP_MN_REMOVE_DEVICE:
+            DPRINT1("USBPORT_PdoPnP: IRP_MN_REMOVE_DEVICE UNIMPLEMENTED. FIXME. \n");
+            //USBPORT_StopRootHub();
+            Status = STATUS_SUCCESS;
+            break;
+
+        case IRP_MN_CANCEL_REMOVE_DEVICE:
+            DPRINT("IRP_MN_CANCEL_REMOVE_DEVICE\n");
+            Status = STATUS_SUCCESS;
+            break;
+
+        case IRP_MN_STOP_DEVICE:
+            DPRINT1("USBPORT_PdoPnP: IRP_MN_STOP_DEVICE UNIMPLEMENTED. FIXME. \n");
+            //USBPORT_StopRootHub();
+            Status = STATUS_SUCCESS;
+            break;
+
+        case IRP_MN_QUERY_STOP_DEVICE:
+            DPRINT("IRP_MN_QUERY_STOP_DEVICE\n");
+            Status = STATUS_SUCCESS;
+            break;
+
+        case IRP_MN_CANCEL_STOP_DEVICE:
+            DPRINT("IRP_MN_CANCEL_STOP_DEVICE\n");
+            Status = STATUS_SUCCESS;
+            break;
+
+        case IRP_MN_QUERY_DEVICE_RELATIONS:
+        {
+            PDEVICE_RELATIONS DeviceRelations;
+
+            DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n");
+            if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
+            {
+                break;
+            }
+
+            DeviceRelations = ExAllocatePoolWithTag(PagedPool,
+                                                    sizeof(DEVICE_RELATIONS),
+                                                    USB_PORT_TAG);
+
+            if (!DeviceRelations)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                Irp->IoStatus.Information = 0;
+                break;
+            }
+
+            DeviceRelations->Count = 1;
+            DeviceRelations->Objects[0] = PdoDevice;
+
+            ObReferenceObject(PdoDevice);
+
+            Status = STATUS_SUCCESS;
+            Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
+            break;
+        }
+
+        case IRP_MN_QUERY_INTERFACE:
+            DPRINT("IRP_MN_QUERY_INTERFACE\n");
+            Status = USBPORT_PdoQueryInterface(FdoDevice, PdoDevice, Irp);
+            break;
+
+        case IRP_MN_QUERY_CAPABILITIES:
+            DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
+
+            DeviceCapabilities = IoStack->Parameters.DeviceCapabilities.Capabilities;
+
+            RtlCopyMemory(DeviceCapabilities,
+                          &PdoExtension->Capabilities,
+                          sizeof(DEVICE_CAPABILITIES));
+
+            Status = STATUS_SUCCESS;
+            break;
+
+        case IRP_MN_QUERY_RESOURCES:
+            DPRINT("USBPORT_PdoPnP: IRP_MN_QUERY_RESOURCES\n");
+            break;
+
+        case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
+            DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
+            break;
+
+        case IRP_MN_QUERY_DEVICE_TEXT:
+            DPRINT("IRP_MN_QUERY_DEVICE_TEXT\n");
+            break;
+
+        case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
+            DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
+            break;
+
+        case IRP_MN_READ_CONFIG:
+            DPRINT("IRP_MN_READ_CONFIG\n");
+            ASSERT(FALSE);
+            break;
+
+        case IRP_MN_WRITE_CONFIG:
+            DPRINT("IRP_MN_WRITE_CONFIG\n");
+            ASSERT(FALSE);
+            break;
+
+        case IRP_MN_EJECT:
+            DPRINT("IRP_MN_EJECT\n");
+            ASSERT(FALSE);
+            break;
+
+        case IRP_MN_SET_LOCK:
+            DPRINT("IRP_MN_SET_LOCK\n");
+            ASSERT(FALSE);
+            break;
+
+        case IRP_MN_QUERY_ID:
+        {
+            ULONG IdType;
+            LONG Length;
+            WCHAR Buffer[64] = {0};
+            PVOID Id;
+
+            Status = STATUS_SUCCESS;
+            IdType = IoStack->Parameters.QueryId.IdType;
+
+            DPRINT("IRP_MN_QUERY_ID/Type %x\n", IdType);
+
+            if (IdType == BusQueryDeviceID)
+            {
+                PUSBPORT_REGISTRATION_PACKET Packet;
+                Packet = &FdoExtension->MiniPortInterface->Packet;
+
+                if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
+                {
+                    RtlStringCbPrintfW(Buffer,
+                                       sizeof(Buffer),
+                                       L"USB\\ROOT_HUB20");
+                }
+                else
+                {
+                    RtlStringCbPrintfW(Buffer,
+                                       sizeof(Buffer),
+                                       L"USB\\ROOT_HUB");
+                }
+
+                Length = (wcslen(Buffer) + 1);
+
+                Id = ExAllocatePoolWithTag(PagedPool,
+                                           Length * sizeof(WCHAR),
+                                           USB_PORT_TAG);
+
+                if (Id)
+                {
+                    RtlZeroMemory(Id, Length * sizeof(WCHAR));
+                    RtlStringCbCopyW(Id, Length * sizeof(WCHAR), Buffer);
+
+                    DPRINT("BusQueryDeviceID - %S, TotalLength - %hu\n",
+                           Id,
+                           Length);
+                }
+
+                Irp->IoStatus.Information = (ULONG_PTR)Id;
+                break;
+            }
+
+            if (IdType == BusQueryHardwareIDs)
+            {
+                Id = USBPORT_GetDeviceHwIds(FdoDevice,
+                                            FdoExtension->VendorID,
+                                            FdoExtension->DeviceID,
+                                            FdoExtension->RevisionID);
+
+                Irp->IoStatus.Information = (ULONG_PTR)Id;
+                break;
+            }
+
+            if (IdType == BusQueryCompatibleIDs ||
+                IdType == BusQueryInstanceID)
+            {
+                Irp->IoStatus.Information = 0;
+                break;
+            }
+
+            /* IdType == BusQueryDeviceSerialNumber */
+            Status = Irp->IoStatus.Status;
+            break;
+        }
+
+        case IRP_MN_QUERY_PNP_DEVICE_STATE:
+            DPRINT("IRP_MN_QUERY_PNP_DEVICE_STATE\n");
+            Status = STATUS_SUCCESS;
+            break;
+
+        case IRP_MN_QUERY_BUS_INFORMATION:
+            DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
+
+            /* Allocate buffer for bus information */
+            BusInformation = ExAllocatePoolWithTag(PagedPool,
+                                                   sizeof(PNP_BUS_INFORMATION),
+                                                   USB_PORT_TAG);
+
+            if (!BusInformation)
+            {
+                /* No memory */
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                break;
+            }
+
+            RtlZeroMemory(BusInformation, sizeof(PNP_BUS_INFORMATION));
+
+            /* 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;
+            break;
+
+        case IRP_MN_DEVICE_USAGE_NOTIFICATION:
+            DPRINT("IRP_MN_DEVICE_USAGE_NOTIFICATION\n");
+            break;
+
+        case IRP_MN_SURPRISE_REMOVAL:
+            DPRINT("USBPORT_PdoPnP: IRP_MN_SURPRISE_REMOVAL\n");
+            Status = STATUS_SUCCESS;
+            break;
+
+        default:
+            DPRINT("unknown IRP_MN_???\n");
+            break;
+    }
+
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    return Status;
+}
diff --git a/reactos/drivers/usb/usbport/power.c b/reactos/drivers/usb/usbport/power.c
new file mode 100644 (file)
index 0000000..2a8c460
--- /dev/null
@@ -0,0 +1,703 @@
+#include "usbport.h"
+
+#define NDEBUG
+#include <debug.h>
+
+VOID
+NTAPI
+USBPORT_CompletePdoWaitWake(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PDEVICE_OBJECT PdoDevice;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PIRP Irp;
+    KIRQL OldIrql;
+
+    DPRINT("USBPORT_CompletePdoWaitWake: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    PdoDevice = FdoExtension->RootHubPdo;
+    PdoExtension = PdoDevice->DeviceExtension;
+
+    KeAcquireSpinLock(&FdoExtension->PowerWakeSpinLock, &OldIrql);
+
+    Irp = PdoExtension->WakeIrp;
+
+    if (Irp && IoSetCancelRoutine(Irp, NULL))
+    {
+        PdoExtension->WakeIrp = NULL;
+        KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
+
+        DPRINT("USBPORT_CompletePdoWaitWake: Complete Irp - %p\n", Irp);
+
+        Irp->IoStatus.Status = STATUS_SUCCESS;
+        Irp->IoStatus.Information = 0;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+        return;
+    }
+
+    KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
+}
+
+VOID
+NTAPI
+USBPORT_HcWakeDpc(IN PRKDPC Dpc,
+                  IN PVOID DeferredContext,
+                  IN PVOID SystemArgument1,
+                  IN PVOID SystemArgument2)
+{
+    DPRINT("USBPORT_HcWakeDpc: ... \n");
+    USBPORT_CompletePdoWaitWake((PDEVICE_OBJECT)DeferredContext);
+}
+
+VOID
+NTAPI
+USBPORT_HcQueueWakeDpc(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT("USBPORT_HcQueueWakeDpc: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    KeInsertQueueDpc(&FdoExtension->HcWakeDpc, NULL, NULL);
+}
+
+VOID
+NTAPI
+USBPORT_CompletePendingIdleIrp(IN PDEVICE_OBJECT PdoDevice)
+{
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PIRP Irp;
+
+    DPRINT("USBPORT_CompletePendingIdleIrp: ... \n");
+
+    PdoExtension = PdoDevice->DeviceExtension;
+    FdoDevice = PdoExtension->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    Irp = IoCsqRemoveNextIrp(&FdoExtension->IdleIoCsq, 0);
+
+    if (Irp)
+    {
+        InterlockedDecrement(&FdoExtension->IdleLockCounter);
+
+        DPRINT("USBPORT_CompletePendingIdleIrp: Complete Irp - %p\n", Irp);
+
+        Irp->IoStatus.Status = STATUS_CANCELLED;
+        Irp->IoStatus.Information = 0;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    }
+}
+
+VOID
+NTAPI
+USBPORT_DoSetPowerD0(IN PDEVICE_OBJECT FdoDevice)
+{
+    DPRINT("USBPORT_DoSetPowerD0: FIXME!\n");
+    return;
+    DbgBreakPoint();
+    //ASSERT(FALSE);
+}
+
+VOID
+NTAPI
+USBPORT_SuspendController(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION  FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+
+    DPRINT1("USBPORT_SuspendController \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    FdoExtension->TimerFlags |= USBPORT_TMFLAG_RH_SUSPENDED;
+
+    USBPORT_FlushController(FdoDevice);
+
+    if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND)
+    {
+        return;
+    }
+
+    FdoExtension->TimerFlags |= USBPORT_TMFLAG_HC_SUSPENDED;
+
+    if (FdoExtension->MiniPortFlags & USBPORT_MPFLAG_INTERRUPTS_ENABLED)
+    {
+        FdoExtension->MiniPortFlags |= USBPORT_MPFLAG_SUSPENDED;
+
+        USBPORT_Wait(FdoDevice, 10);
+        Packet->SuspendController(FdoExtension->MiniPortExt);
+    }
+
+    FdoExtension->Flags |= USBPORT_FLAG_HC_SUSPEND;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_ResumeController(IN PDEVICE_OBJECT FdoDevice)
+{
+    NTSTATUS Status = STATUS_UNSUCCESSFUL;
+    PUSBPORT_DEVICE_EXTENSION  FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    KIRQL OldIrql;
+    MPSTATUS MpStatus;
+
+    DPRINT1("USBPORT_ResumeController: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    if (!(FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND))
+    {
+        return Status;
+    }
+
+    KeAcquireSpinLock(&FdoExtension->TimerFlagsSpinLock, &OldIrql);
+
+    FdoExtension->TimerFlags &= ~(USBPORT_TMFLAG_HC_SUSPENDED |
+                                  USBPORT_TMFLAG_RH_SUSPENDED);
+
+    KeReleaseSpinLock(&FdoExtension->TimerFlagsSpinLock, OldIrql);
+
+    if (!(FdoExtension->MiniPortFlags & USBPORT_MPFLAG_SUSPENDED))
+    {
+        FdoExtension->Flags &= ~USBPORT_FLAG_HC_SUSPEND;
+        return Status;
+    }
+
+    FdoExtension->MiniPortFlags &= ~USBPORT_MPFLAG_SUSPENDED;
+
+    if (!Packet->ResumeController(FdoExtension->MiniPortExt))
+    {
+        Status = USBPORT_Wait(FdoDevice, 100);
+
+        FdoExtension->Flags &= ~USBPORT_FLAG_HC_SUSPEND;
+        return Status;
+    }
+
+    KeAcquireSpinLock(&FdoExtension->TimerFlagsSpinLock, &OldIrql);
+    FdoExtension->TimerFlags |= (USBPORT_TMFLAG_HC_SUSPENDED |
+                                 USBPORT_TMFLAG_HC_RESUME);
+    KeReleaseSpinLock(&FdoExtension->TimerFlagsSpinLock, OldIrql);
+
+    USBPORT_MiniportInterrupts(FdoDevice, FALSE);
+
+    Packet->StopController(FdoExtension->MiniPortExt, 1);
+
+    USBPORT_NukeAllEndpoints(FdoDevice);
+
+    RtlZeroMemory(FdoExtension->MiniPortExt, Packet->MiniPortExtensionSize);
+
+    RtlZeroMemory(FdoExtension->UsbPortResources.StartVA,
+                  Packet->MiniPortResourcesSize);
+
+    FdoExtension->UsbPortResources.IsChirpHandled = TRUE;
+
+    MpStatus = Packet->StartController(FdoExtension->MiniPortExt,
+                                       &FdoExtension->UsbPortResources);
+
+    FdoExtension->UsbPortResources.IsChirpHandled = FALSE;
+
+    if (!MpStatus)
+    {
+        USBPORT_MiniportInterrupts(FdoDevice, TRUE);
+    }
+
+    KeAcquireSpinLock(&FdoExtension->TimerFlagsSpinLock, &OldIrql);
+
+    FdoExtension->TimerFlags &= ~(USBPORT_TMFLAG_HC_SUSPENDED |
+                                  USBPORT_TMFLAG_HC_RESUME |
+                                  USBPORT_TMFLAG_RH_SUSPENDED);
+
+    KeReleaseSpinLock(&FdoExtension->TimerFlagsSpinLock, OldIrql);
+
+    Status = USBPORT_Wait(FdoDevice, 100);
+
+    FdoExtension->Flags &= ~USBPORT_FLAG_HC_SUSPEND;
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_PdoDevicePowerState(IN PDEVICE_OBJECT PdoDevice,
+                            IN PIRP Irp)
+{
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PIO_STACK_LOCATION IoStack;
+    NTSTATUS Status = STATUS_SUCCESS;
+    POWER_STATE State;
+
+    PdoExtension = PdoDevice->DeviceExtension;
+    FdoDevice = PdoExtension->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    State = IoStack->Parameters.Power.State;
+
+    DPRINT1("USBPORT_PdoDevicePowerState: Irp - %p, State - %x\n",
+            Irp,
+            State.DeviceState);
+
+    if (State.DeviceState == PowerDeviceD0)
+    {
+        if (FdoExtension->CommonExtension.DevicePowerState == PowerDeviceD0)
+        {
+            // FIXME FdoExtension->Flags
+            while (FdoExtension->SetPowerLockCounter)
+            {
+                USBPORT_Wait(FdoDevice, 10);
+            }
+
+            USBPORT_ResumeController(FdoDevice);
+
+            PdoExtension->CommonExtension.DevicePowerState = PowerDeviceD0;
+
+            USBPORT_CompletePdoWaitWake(FdoDevice);
+            USBPORT_CompletePendingIdleIrp(PdoDevice);
+        }
+        else
+        {
+            DPRINT1("USBPORT_PdoDevicePowerState: FdoExtension->Flags - %lx\n",
+                    FdoExtension->Flags);
+
+            DbgBreakPoint();
+            Status = STATUS_UNSUCCESSFUL;
+        }
+    }
+    else if (State.DeviceState  == PowerDeviceD1 ||
+             State.DeviceState  == PowerDeviceD2 ||
+             State.DeviceState  == PowerDeviceD3)
+    {
+        FdoExtension->TimerFlags |= USBPORT_TMFLAG_WAKE;
+        USBPORT_SuspendController(FdoDevice);
+        PdoExtension->CommonExtension.DevicePowerState = State.DeviceState;
+    }
+
+    return Status;
+}
+
+VOID
+NTAPI
+USBPORT_CancelPendingWakeIrp(IN PDEVICE_OBJECT PdoDevice,
+                             IN PIRP Irp)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    KIRQL OldIrql;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+
+    DPRINT("USBPORT_CancelPendingWakeIrp: ... \n");
+
+    IoReleaseCancelSpinLock(Irp->CancelIrql);
+    PdoExtension = PdoDevice->DeviceExtension;
+    FdoExtension = PdoExtension->FdoDevice->DeviceExtension;
+
+    KeAcquireSpinLock(&FdoExtension->PowerWakeSpinLock, &OldIrql);
+
+    if (PdoExtension->WakeIrp == Irp)
+    {
+        PdoExtension->WakeIrp = NULL;
+    }
+
+    KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
+
+    Irp->IoStatus.Status = STATUS_CANCELLED;
+    Irp->IoStatus.Information = 0;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+}
+
+NTSTATUS
+NTAPI
+USBPORT_PdoPower(IN PDEVICE_OBJECT PdoDevice,
+                 IN PIRP Irp)
+{
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PDEVICE_OBJECT FdoDevice;
+    PIO_STACK_LOCATION IoStack;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    NTSTATUS Status;
+    KIRQL OldIrql;
+
+    DPRINT("USBPORT_PdoPower: Irp - %p\n", Irp);
+
+    PdoExtension = PdoDevice->DeviceExtension;
+    FdoDevice = PdoExtension->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    Status = Irp->IoStatus.Status;
+
+    switch (IoStack->MinorFunction)
+    {
+      case IRP_MN_WAIT_WAKE:
+          DPRINT("USBPORT_PdoPower: IRP_MN_WAIT_WAKE\n");
+
+          if (!(FdoExtension->Flags & USBPORT_FLAG_HC_STARTED))
+          {
+              /* The device does not support wake-up */
+              Status = STATUS_NOT_SUPPORTED;
+              break;
+          }
+
+          KeAcquireSpinLock(&FdoExtension->PowerWakeSpinLock, &OldIrql);
+
+          IoSetCancelRoutine(Irp, USBPORT_CancelPendingWakeIrp);
+
+          /* Check if the IRP has been cancelled */
+          if (Irp->Cancel)
+          {
+              if (IoSetCancelRoutine(Irp, NULL))
+              {
+                  /* IRP has been cancelled, release cancel spinlock */
+                  KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
+
+                  DPRINT("USBPORT_PdoPower: IRP_MN_WAIT_WAKE - STATUS_CANCELLED\n");
+
+                  /* IRP is cancelled */
+                  Status = STATUS_CANCELLED;
+                  break;
+              }
+          }
+
+          if (!PdoExtension->WakeIrp)
+          {
+              /* The driver received the IRP
+                 and is waiting for the device to signal wake-up. */
+
+              DPRINT("USBPORT_PdoPower: IRP_MN_WAIT_WAKE - No WakeIrp\n");
+
+              IoMarkIrpPending(Irp);
+              PdoExtension->WakeIrp = Irp;
+
+              KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
+              return STATUS_PENDING;
+          }
+          else
+          {
+              /* An IRP_MN_WAIT_WAKE request is already pending and must be
+                 completed or canceled before another IRP_MN_WAIT_WAKE request
+                 can be issued. */
+
+              if (IoSetCancelRoutine(Irp, NULL))
+              {
+                  DPRINT("USBPORT_PdoPower: IRP_MN_WAIT_WAKE - STATUS_DEVICE_BUSY\n");
+
+                  KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
+                  PoStartNextPowerIrp(Irp);
+                  Status = STATUS_DEVICE_BUSY;
+                  break;
+              }
+              else
+              {
+                  ASSERT(FALSE);
+                  KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
+                  return Status;
+              }
+          }
+
+      case IRP_MN_POWER_SEQUENCE:
+          DPRINT("USBPORT_PdoPower: IRP_MN_POWER_SEQUENCE\n");
+          PoStartNextPowerIrp(Irp);
+          break;
+
+      case IRP_MN_SET_POWER:
+          DPRINT("USBPORT_PdoPower: IRP_MN_SET_POWER\n");
+
+          if (IoStack->Parameters.Power.Type == DevicePowerState)
+          {
+              DPRINT("USBPORT_PdoPower: IRP_MN_SET_POWER/DevicePowerState\n");
+              Status = USBPORT_PdoDevicePowerState(PdoDevice, Irp);
+              PoStartNextPowerIrp(Irp);
+              break;
+          }
+
+          DPRINT("USBPORT_PdoPower: IRP_MN_SET_POWER/SystemPowerState \n");
+
+          if (IoStack->Parameters.Power.State.SystemState == PowerSystemWorking)
+          {
+              FdoExtension->TimerFlags |= USBPORT_TMFLAG_WAKE;
+          }
+          else
+          {
+              FdoExtension->TimerFlags &= ~USBPORT_TMFLAG_WAKE;
+          }
+
+          Status = STATUS_SUCCESS;
+
+          PoStartNextPowerIrp(Irp);
+          break;
+
+      case IRP_MN_QUERY_POWER:
+          DPRINT("USBPORT_PdoPower: IRP_MN_QUERY_POWER\n");
+          Status = STATUS_SUCCESS;
+          PoStartNextPowerIrp(Irp);
+          break;
+
+      default:
+          DPRINT1("USBPORT_PdoPower: unknown IRP_MN_POWER!\n");
+          PoStartNextPowerIrp(Irp);
+          break;
+    }
+
+    Irp->IoStatus.Status = Status;
+    Irp->IoStatus.Information = 0;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_HcWake(IN PDEVICE_OBJECT FdoDevice,
+               IN PIRP Irp)
+{
+    DPRINT1("USBPORT_HcWake: UNIMPLEMENTED. FIXME. \n");
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_DevicePowerState(IN PDEVICE_OBJECT FdoDevice,
+                         IN PIRP Irp)
+{
+    DPRINT1("USBPORT_DevicePowerState: UNIMPLEMENTED. FIXME. \n");
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_SystemPowerState(IN PDEVICE_OBJECT FdoDevice,
+                         IN PIRP Irp)
+{
+    DPRINT1("USBPORT_SystemPowerState: UNIMPLEMENTED. FIXME. \n");
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_FdoPower(IN PDEVICE_OBJECT FdoDevice,
+                 IN PIRP Irp)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PIO_STACK_LOCATION IoStack;
+    NTSTATUS Status;
+
+    DPRINT("USBPORT_FdoPower: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    switch (IoStack->MinorFunction)
+    {
+      case IRP_MN_WAIT_WAKE:
+          DPRINT("USBPORT_FdoPower: IRP_MN_WAIT_WAKE\n");
+          Status = USBPORT_HcWake(FdoDevice, Irp);
+          return Status;
+
+      case IRP_MN_POWER_SEQUENCE:
+          DPRINT("USBPORT_FdoPower: IRP_MN_POWER_SEQUENCE\n");
+          break;
+
+      case IRP_MN_SET_POWER:
+          DPRINT("USBPORT_FdoPower: IRP_MN_SET_POWER\n");
+          if (IoStack->Parameters.Power.Type == DevicePowerState)
+          {
+              Status = USBPORT_DevicePowerState(FdoDevice, Irp);
+          }
+          else
+          {
+              Status = USBPORT_SystemPowerState(FdoDevice, Irp);
+          }
+      
+          if (Status != STATUS_PENDING)
+              break;
+
+          return Status;
+
+      case IRP_MN_QUERY_POWER:
+          DPRINT("USBPORT_FdoPower: IRP_MN_QUERY_POWER\n");
+          Irp->IoStatus.Status = STATUS_SUCCESS;
+          break;
+
+      default:
+          DPRINT1("USBPORT_FdoPower: unknown IRP_MN_POWER!\n");
+          break;
+    }
+
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+    PoStartNextPowerIrp(Irp);
+    return PoCallDriver(FdoExtension->CommonExtension.LowerDevice, Irp);
+}
+
+VOID
+NTAPI
+USBPORT_DoIdleNotificationCallback(IN PVOID Context)
+{
+    PIO_STACK_LOCATION IoStack;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PIRP NextIrp;
+    LARGE_INTEGER CurrentTime = {{0, 0}};
+    PTIMER_WORK_QUEUE_ITEM IdleQueueItem;
+    PDEVICE_OBJECT PdoDevice;
+    PUSB_IDLE_CALLBACK_INFO IdleCallbackInfo;
+    KIRQL OldIrql;
+
+    DPRINT("USBPORT_DoIdleNotificationCallback \n");
+
+    IdleQueueItem = Context;
+
+    FdoDevice = IdleQueueItem->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+    PdoDevice = FdoExtension->RootHubPdo;
+    PdoExtension = PdoDevice->DeviceExtension;
+
+    KeQuerySystemTime(&CurrentTime);
+
+    if ((FdoExtension->IdleTime.QuadPart == 0) ||
+        (((CurrentTime.QuadPart - FdoExtension->IdleTime.QuadPart) / 10000) >= 500))
+    {
+        if (PdoExtension->CommonExtension.DevicePowerState == PowerDeviceD0 &&
+            FdoExtension->CommonExtension.DevicePowerState == PowerDeviceD0)
+        {
+            NextIrp = IoCsqRemoveNextIrp(&FdoExtension->IdleIoCsq, NULL);
+
+            if (NextIrp)
+            {
+                IoStack = IoGetCurrentIrpStackLocation(NextIrp);
+                IdleCallbackInfo = IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+
+                if (IdleCallbackInfo && IdleCallbackInfo->IdleCallback)
+                {
+                    IdleCallbackInfo->IdleCallback(IdleCallbackInfo->IdleContext);
+                }
+
+                if (NextIrp->Cancel)
+                {
+                    InterlockedDecrement(&FdoExtension->IdleLockCounter);
+
+                    NextIrp->IoStatus.Status = STATUS_CANCELLED;
+                    NextIrp->IoStatus.Information = 0;
+                    IoCompleteRequest(NextIrp, IO_NO_INCREMENT);
+                }
+                else
+                {
+                    IoCsqInsertIrp(&FdoExtension->IdleIoCsq, NextIrp, NULL);
+                }
+            }
+        }
+    }
+
+    KeAcquireSpinLock(&FdoExtension->TimerFlagsSpinLock, &OldIrql);
+    FdoExtension->TimerFlags &= ~USBPORT_TMFLAG_IDLE_QUEUEITEM_ON;
+    KeReleaseSpinLock(&FdoExtension->TimerFlagsSpinLock, OldIrql);
+
+    ExFreePoolWithTag(IdleQueueItem, USB_PORT_TAG);
+}
+
+NTSTATUS
+NTAPI
+USBPORT_IdleNotification(IN PDEVICE_OBJECT PdoDevice,
+                         IN PIRP Irp)
+{
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    LONG LockCounter;
+    NTSTATUS Status = STATUS_PENDING;
+
+    DPRINT("USBPORT_IdleNotification: Irp - %p\n", Irp);
+
+    PdoExtension = PdoDevice->DeviceExtension;
+    FdoDevice = PdoExtension->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    LockCounter = InterlockedIncrement(&FdoExtension->IdleLockCounter);
+
+    if (LockCounter != 0)
+    {
+        if (Status != STATUS_PENDING)
+        {
+            InterlockedDecrement(&FdoExtension->IdleLockCounter);
+
+            Irp->IoStatus.Status = Status;
+            Irp->IoStatus.Information = 0;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+            return Status;
+        }
+
+        Status = STATUS_DEVICE_BUSY;
+    }
+
+    if (Status != STATUS_PENDING)
+    {
+        InterlockedDecrement(&FdoExtension->IdleLockCounter);
+
+        Irp->IoStatus.Status = Status;
+        Irp->IoStatus.Information = 0;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+        return Status;
+    }
+
+    Irp->IoStatus.Status = STATUS_PENDING;
+    IoMarkIrpPending(Irp);
+
+    KeQuerySystemTime(&FdoExtension->IdleTime);
+
+    IoCsqInsertIrp(&FdoExtension->IdleIoCsq, Irp, 0);
+
+    return Status;
+}
+
+VOID
+NTAPI
+USBPORT_AdjustDeviceCapabilities(IN PDEVICE_OBJECT FdoDevice,
+                                 IN PDEVICE_OBJECT PdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PDEVICE_CAPABILITIES Capabilities;
+
+    DPRINT("USBPORT_AdjustDeviceCapabilities: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    PdoExtension = PdoDevice->DeviceExtension;
+    Capabilities = &PdoExtension->Capabilities;
+
+    RtlCopyMemory(Capabilities,
+                  &FdoExtension->Capabilities,
+                  sizeof(DEVICE_CAPABILITIES));
+
+    Capabilities->DeviceD1 = FALSE;
+    Capabilities->DeviceD2 = TRUE;
+
+    Capabilities->Removable = FALSE;
+    Capabilities->UniqueID = FALSE;
+
+    Capabilities->WakeFromD0 = TRUE;
+    Capabilities->WakeFromD1 = FALSE;
+    Capabilities->WakeFromD2 = TRUE;
+    Capabilities->WakeFromD3 = FALSE;
+
+    Capabilities->Address = 0;
+    Capabilities->UINumber = 0;
+
+    if (Capabilities->SystemWake == PowerSystemUnspecified)
+        Capabilities->SystemWake = PowerSystemWorking;
+
+    Capabilities->DeviceWake = PowerDeviceD2;
+
+    Capabilities->DeviceState[PowerSystemSleeping1] = PowerDeviceD3;
+    Capabilities->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;
+    Capabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
+    Capabilities->DeviceState[PowerSystemHibernate] = PowerDeviceD3;
+}
diff --git a/reactos/drivers/usb/usbport/queue.c b/reactos/drivers/usb/usbport/queue.c
new file mode 100644 (file)
index 0000000..3ef29a9
--- /dev/null
@@ -0,0 +1,1389 @@
+#include "usbport.h"
+
+#define NDEBUG
+#include <debug.h>
+
+#define NDEBUG_USBPORT_CORE
+#define NDEBUG_USBPORT_QUEUE
+#define NDEBUG_USBPORT_URB
+#include "usbdebug.h"
+
+VOID
+NTAPI
+USBPORT_InsertIdleIrp(IN PIO_CSQ Csq,
+                      IN PIRP Irp)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT_QUEUE("USBPORT_InsertIdleIrp: Irp - %p\n", Irp);
+
+    FdoExtension = CONTAINING_RECORD(Csq,
+                                     USBPORT_DEVICE_EXTENSION,
+                                     IdleIoCsq);
+
+    InsertTailList(&FdoExtension->IdleIrpList,
+                   &Irp->Tail.Overlay.ListEntry);
+}
+
+VOID
+NTAPI
+USBPORT_RemoveIdleIrp(IN PIO_CSQ Csq,
+                      IN PIRP Irp)
+{
+    DPRINT_QUEUE("USBPORT_RemoveIdleIrp: Irp - %p\n", Irp);
+    RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+}
+
+PIRP
+NTAPI
+USBPORT_PeekNextIdleIrp(IN PIO_CSQ Csq,
+                        IN PIRP Irp,
+                        IN PVOID PeekContext)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PLIST_ENTRY NextEntry;
+    PLIST_ENTRY ListHead;
+    PIRP NextIrp = NULL;
+
+    DPRINT_QUEUE("USBPORT_PeekNextIdleIrp: Irp - %p, PeekContext - %p\n",
+                 Irp,
+                 PeekContext);
+
+    FdoExtension = CONTAINING_RECORD(Csq,
+                                     USBPORT_DEVICE_EXTENSION,
+                                     IdleIoCsq);
+
+    ListHead = &FdoExtension->IdleIrpList;
+
+    if (Irp)
+    {
+        NextEntry = Irp->Tail.Overlay.ListEntry.Flink;
+    }
+    else
+    {
+        NextEntry = ListHead->Flink;
+    }
+
+    while (NextEntry != ListHead)
+    {
+        NextIrp = CONTAINING_RECORD(NextEntry,
+                                    IRP,
+                                    Tail.Overlay.ListEntry);
+
+        if (!PeekContext)
+            break;
+
+        NextEntry = NextEntry->Flink;
+    }
+
+    return NextIrp;
+}
+
+VOID
+NTAPI
+USBPORT_AcquireIdleLock(IN PIO_CSQ Csq,
+                        IN PKIRQL Irql)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT_QUEUE("USBPORT_AcquireIdleLock: ... \n");
+
+    FdoExtension = CONTAINING_RECORD(Csq,
+                                     USBPORT_DEVICE_EXTENSION,
+                                     IdleIoCsq);
+
+    KeAcquireSpinLock(&FdoExtension->IdleIoCsqSpinLock, Irql);
+}
+
+VOID
+NTAPI
+USBPORT_ReleaseIdleLock(IN PIO_CSQ Csq,
+                        IN KIRQL Irql)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT_QUEUE("USBPORT_ReleaseIdleLock: ... \n");
+
+    FdoExtension = CONTAINING_RECORD(Csq,
+                                     USBPORT_DEVICE_EXTENSION,
+                                     IdleIoCsq);
+
+    KeReleaseSpinLock(&FdoExtension->IdleIoCsqSpinLock, Irql);
+}
+
+VOID
+NTAPI
+USBPORT_CompleteCanceledIdleIrp(IN PIO_CSQ Csq,
+                                IN PIRP Irp)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT_QUEUE("USBPORT_CompleteCanceledIdleIrp: ... \n");
+
+    FdoExtension = CONTAINING_RECORD(Csq,
+                                     USBPORT_DEVICE_EXTENSION,
+                                     IdleIoCsq);
+
+    InterlockedDecrement(&FdoExtension->IdleLockCounter);
+
+    Irp->IoStatus.Status = STATUS_CANCELLED;
+    Irp->IoStatus.Information = 0;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+}
+
+VOID
+NTAPI
+USBPORT_InsertBadRequest(IN PIO_CSQ Csq,
+                         IN PIRP Irp)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT_QUEUE("USBPORT_InsertBadRequest: Irp - %p\n", Irp);
+
+    FdoExtension = CONTAINING_RECORD(Csq,
+                                     USBPORT_DEVICE_EXTENSION,
+                                     BadRequestIoCsq);
+
+    InsertTailList(&FdoExtension->BadRequestList,
+                   &Irp->Tail.Overlay.ListEntry);
+}
+
+VOID
+NTAPI
+USBPORT_RemoveBadRequest(IN PIO_CSQ Csq,
+                         IN PIRP Irp)
+{
+    DPRINT_QUEUE("USBPORT_RemoveBadRequest: Irp - %p\n", Irp);
+    RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+}
+
+PIRP
+NTAPI
+USBPORT_PeekNextBadRequest(IN PIO_CSQ Csq,
+                           IN PIRP Irp,
+                           IN PVOID PeekContext)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PLIST_ENTRY NextEntry;
+    PLIST_ENTRY ListHead;
+    PIRP NextIrp = NULL;
+
+    DPRINT_QUEUE("USBPORT_PeekNextBadRequest: Irp - %p, PeekContext - %p\n",
+                 Irp,
+                 PeekContext);
+
+    FdoExtension = CONTAINING_RECORD(Csq,
+                                     USBPORT_DEVICE_EXTENSION,
+                                     BadRequestIoCsq);
+
+    ListHead = &FdoExtension->BadRequestList;
+
+    if (Irp)
+    {
+        NextEntry = Irp->Tail.Overlay.ListEntry.Flink;
+    }
+    else
+    {
+        NextEntry = ListHead->Flink;
+    }
+
+    while (NextEntry != ListHead)
+    {
+        NextIrp = CONTAINING_RECORD(NextEntry,
+                                    IRP,
+                                    Tail.Overlay.ListEntry);
+
+        if (!PeekContext)
+            break;
+
+        NextEntry = NextEntry->Flink;
+    }
+
+    return NextIrp;
+}
+
+VOID
+NTAPI
+USBPORT_AcquireBadRequestLock(IN PIO_CSQ Csq,
+                              IN PKIRQL Irql)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT_QUEUE("USBPORT_AcquireBadRequestLock: ... \n");
+
+    FdoExtension = CONTAINING_RECORD(Csq,
+                                     USBPORT_DEVICE_EXTENSION,
+                                     BadRequestIoCsq);
+
+    KeAcquireSpinLock(&FdoExtension->BadRequestIoCsqSpinLock, Irql);
+}
+
+VOID
+NTAPI
+USBPORT_ReleaseBadRequestLock(IN PIO_CSQ Csq,
+                              IN KIRQL Irql)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT_QUEUE("USBPORT_ReleaseBadRequestLock: ... \n");
+
+    FdoExtension = CONTAINING_RECORD(Csq,
+                                     USBPORT_DEVICE_EXTENSION,
+                                     BadRequestIoCsq);
+
+    KeReleaseSpinLock(&FdoExtension->BadRequestIoCsqSpinLock, Irql);
+}
+
+VOID
+NTAPI
+USBPORT_CompleteCanceledBadRequest(IN PIO_CSQ Csq,
+                                   IN PIRP Irp)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT_QUEUE("USBPORT_CompleteCanceledBadRequest: Irp - %p\n", Irp);
+
+    FdoExtension = CONTAINING_RECORD(Csq,
+                                     USBPORT_DEVICE_EXTENSION,
+                                     BadRequestIoCsq);
+
+    InterlockedDecrement(&FdoExtension->BadRequestLockCounter);
+
+    Irp->IoStatus.Status = STATUS_CANCELLED;
+    Irp->IoStatus.Information = 0;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+}
+
+VOID
+NTAPI
+USBPORT_InsertIrpInTable(IN PUSBPORT_IRP_TABLE IrpTable,
+                         IN PIRP Irp)
+{
+    ULONG ix;
+
+    DPRINT_CORE("USBPORT_InsertIrpInTable: IrpTable - %p, Irp - %p\n",
+                IrpTable,
+                Irp);
+
+    ASSERT(IrpTable != NULL);
+
+    while (TRUE)
+    {
+        for (ix = 0; ix < 0x200; ix++)
+        {
+            if (IrpTable->irp[ix] == NULL)
+            {
+                IrpTable->irp[ix] = Irp;
+
+                if (ix > 0)
+                {
+                    DPRINT_CORE("USBPORT_InsertIrpInTable: ix - %x\n", ix);
+                }
+
+                return;
+            }
+        }
+
+        if (ix != 0x200)
+        {
+            KeBugCheckEx(BUGCODE_USB_DRIVER, 1, 0, 0, 0);
+        }
+
+        IrpTable->LinkNextTable = ExAllocatePoolWithTag(NonPagedPool,
+                                                        sizeof(USBPORT_IRP_TABLE),
+                                                        USB_PORT_TAG);
+
+        if (IrpTable->LinkNextTable == NULL)
+        {
+            KeBugCheckEx(BUGCODE_USB_DRIVER, 1, 0, 0, 0);
+        }
+
+        RtlZeroMemory(IrpTable->LinkNextTable, sizeof(USBPORT_IRP_TABLE));
+
+        IrpTable = IrpTable->LinkNextTable;
+    }
+}
+
+PIRP
+NTAPI
+USBPORT_RemoveIrpFromTable(IN PUSBPORT_IRP_TABLE IrpTable,
+                           IN PIRP Irp)
+{
+    ULONG ix;
+
+    DPRINT_CORE("USBPORT_RemoveIrpFromTable: IrpTable - %p, Irp - %p\n",
+                IrpTable,
+                Irp);
+
+    ASSERT(IrpTable != NULL);
+
+    while (TRUE)
+    {
+        for (ix = 0; ix < 0x200; ix++)
+        {
+            if (IrpTable->irp[ix] == Irp)
+            {
+                IrpTable->irp[ix] = NULL;
+
+                if (ix > 0)
+                {
+                    DPRINT_CORE("USBPORT_RemoveIrpFromTable: ix - %x\n", ix);
+                }
+
+                return Irp;
+            }
+        }
+
+        if (IrpTable->LinkNextTable == NULL)
+            break;
+
+        IrpTable = IrpTable->LinkNextTable;
+        continue;
+    }
+
+    DPRINT1("USBPORT_RemoveIrpFromTable: return NULL. ix - %x\n", ix);
+    return NULL;
+}
+
+PIRP
+NTAPI
+USBPORT_RemoveActiveTransferIrp(IN PDEVICE_OBJECT FdoDevice,
+                                IN PIRP Irp)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT_CORE("USBPORT_RemoveActiveTransferIrp: Irp - %p\n", Irp);
+    FdoExtension = FdoDevice->DeviceExtension;
+    return USBPORT_RemoveIrpFromTable(FdoExtension->ActiveIrpTable, Irp);
+}
+
+PIRP
+NTAPI
+USBPORT_RemovePendingTransferIrp(IN PDEVICE_OBJECT FdoDevice,
+                                 IN PIRP Irp)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT_CORE("USBPORT_RemovePendingTransferIrp: Irp - %p\n", Irp);
+    FdoExtension = FdoDevice->DeviceExtension;
+    return USBPORT_RemoveIrpFromTable(FdoExtension->PendingIrpTable, Irp);
+}
+
+VOID
+NTAPI
+USBPORT_FindUrbInIrpTable(IN PUSBPORT_IRP_TABLE IrpTable,
+                          IN PURB Urb,
+                          IN PIRP Irp)
+{
+    ULONG ix;
+    PIRP irp;
+    PURB urbIn;
+
+    DPRINT_CORE("USBPORT_FindUrbInIrpTable: IrpTable - %p, Urb - %p, Irp - %p\n",
+                IrpTable,
+                Urb,
+                Irp);
+
+    ASSERT(IrpTable != NULL);
+
+    do
+    {
+        for (ix = 0; ix < 0x200; ix++)
+        {
+            irp = IrpTable->irp[ix];
+
+            if (irp)
+            {
+                urbIn = URB_FROM_IRP(irp);
+
+                if (urbIn == Urb)
+                {
+                    if (irp == Irp)
+                    {
+                        KeBugCheckEx(BUGCODE_USB_DRIVER,
+                                     4,
+                                     (ULONG_PTR)irp,
+                                     (ULONG_PTR)urbIn,
+                                     0);
+                    }
+
+                    KeBugCheckEx(BUGCODE_USB_DRIVER,
+                                 2,
+                                 (ULONG_PTR)irp,
+                                 (ULONG_PTR)Irp,
+                                 (ULONG_PTR)urbIn);
+                }
+            }
+        }
+
+        IrpTable = IrpTable->LinkNextTable;
+    }
+    while (IrpTable);
+}
+
+PIRP
+NTAPI
+USBPORT_FindIrpInTable(IN PUSBPORT_IRP_TABLE IrpTable,
+                       IN PIRP Irp)
+{
+    ULONG ix;
+    PIRP irp;
+
+    DPRINT_CORE("USBPORT_FindIrpInTable: IrpTable - %p, Irp - %p\n",
+                IrpTable,
+                Irp);
+
+    ASSERT(IrpTable != NULL);
+
+    do
+    {
+        for (ix = 0; ix < 0x200; ix++)
+        {
+            irp = IrpTable->irp[ix];
+
+            if (irp && irp == Irp)
+            {
+                return irp;
+            }
+        }
+
+        IrpTable = IrpTable->LinkNextTable;
+    }
+    while (IrpTable->LinkNextTable);
+
+    DPRINT_CORE("USBPORT_FindIrpInTable: Not found!!!\n");
+    return NULL;
+}
+
+PIRP
+NTAPI
+USBPORT_FindActiveTransferIrp(IN PDEVICE_OBJECT FdoDevice,
+                              IN PIRP Irp)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT_CORE("USBPORT_FindActiveTransferIrp: Irp - %p\n", Irp);
+    FdoExtension = FdoDevice->DeviceExtension;
+    return USBPORT_FindIrpInTable(FdoExtension->ActiveIrpTable, Irp);
+}
+
+VOID
+NTAPI
+USBPORT_CancelPendingTransferIrp(IN PDEVICE_OBJECT DeviceObject,
+                                 IN PIRP Irp)
+{
+    PURB Urb;
+    PUSBPORT_TRANSFER Transfer;
+    PUSBPORT_ENDPOINT Endpoint;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    KIRQL OldIrql;
+    PIRP irp;
+
+    DPRINT_CORE("USBPORT_CancelPendingTransferIrp: DeviceObject - %p, Irp - %p\n",
+                DeviceObject,
+                Irp);
+
+    Urb = URB_FROM_IRP(Irp);
+    Transfer = Urb->UrbControlTransfer.hca.Reserved8[0];
+    Endpoint = Transfer->Endpoint;
+
+    FdoDevice = Endpoint->FdoDevice;
+    FdoExtension = DeviceObject->DeviceExtension;
+
+    IoReleaseCancelSpinLock(Irp->CancelIrql);
+
+    KeAcquireSpinLock(&FdoExtension->FlushPendingTransferSpinLock, &OldIrql);
+
+    irp = USBPORT_RemovePendingTransferIrp(FdoDevice, Irp);
+
+    if (!irp)
+    {
+        KeReleaseSpinLock(&FdoExtension->FlushPendingTransferSpinLock,
+                          OldIrql);
+        return;
+    }
+
+    KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock);
+
+    RemoveEntryList(&Transfer->TransferLink);
+
+    Transfer->TransferLink.Flink = NULL;
+    Transfer->TransferLink.Blink = NULL;
+
+    KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
+    KeReleaseSpinLock(&FdoExtension->FlushPendingTransferSpinLock, OldIrql);
+
+    USBPORT_CompleteTransfer(Transfer->Urb, USBD_STATUS_CANCELED);
+}
+
+VOID
+NTAPI
+USBPORT_CancelActiveTransferIrp(IN PDEVICE_OBJECT DeviceObject,
+                                IN PIRP Irp)
+{
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PURB Urb;
+    PUSBPORT_TRANSFER Transfer;
+    PUSBPORT_ENDPOINT Endpoint;
+    PIRP irp;
+    KIRQL OldIrql;
+
+    DPRINT_CORE("USBPORT_CancelTransferIrp: Irp - %p\n", Irp);
+
+    PdoExtension = DeviceObject->DeviceExtension;
+    FdoDevice = PdoExtension->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    IoReleaseCancelSpinLock(Irp->CancelIrql);
+
+    KeAcquireSpinLock(&FdoExtension->FlushTransferSpinLock, &OldIrql);
+
+    irp = USBPORT_FindActiveTransferIrp(FdoDevice, Irp);
+
+    if (irp)
+    {
+        Urb = URB_FROM_IRP(irp);
+        Transfer = Urb->UrbControlTransfer.hca.Reserved8[0];
+        Endpoint = Transfer->Endpoint;
+
+        DPRINT_CORE("USBPORT_CancelTransferIrp: irp - %p, Urb - %p, Transfer - %p\n",
+                    irp,
+                    Urb,
+                    Transfer);
+
+        KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock);
+        Transfer->Flags |= TRANSFER_FLAG_CANCELED;
+        KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
+
+        KeReleaseSpinLock(&FdoExtension->FlushTransferSpinLock, OldIrql);
+
+        USBPORT_InvalidateEndpointHandler(FdoDevice,
+                                          Endpoint,
+                                          INVALIDATE_ENDPOINT_WORKER_THREAD);
+        return;
+    }
+
+    KeReleaseSpinLock(&FdoExtension->FlushTransferSpinLock, OldIrql);
+}
+
+VOID
+NTAPI
+USBPORT_FlushAbortList(IN PUSBPORT_ENDPOINT Endpoint)
+{
+    PLIST_ENTRY Entry;
+    PUSBPORT_TRANSFER Transfer;
+    PLIST_ENTRY AbortList;
+    LIST_ENTRY List;
+    NTSTATUS Status;
+    PIRP Irp;
+    PURB Urb;
+    PUSBPORT_DEVICE_HANDLE DeviceHandle = NULL;
+
+    DPRINT_CORE("USBPORT_FlushAbortList: Endpoint - %p\n", Endpoint);
+
+    InitializeListHead(&List);
+
+    KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
+
+    if (IsListEmpty(&Endpoint->AbortList))
+    {
+        KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
+                          Endpoint->EndpointOldIrql);
+        return;
+    }
+
+    Entry = Endpoint->PendingTransferList.Flink;
+
+    while (Entry && Entry != &Endpoint->PendingTransferList)
+    {
+        Transfer = CONTAINING_RECORD(Entry,
+                                     USBPORT_TRANSFER,
+                                     TransferLink);
+
+        if (Transfer->Flags & TRANSFER_FLAG_ABORTED)
+        {
+            DPRINT_CORE("USBPORT_FlushAbortList: Aborted PendingTransfer  - %p\n",
+                        Transfer);
+
+            KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
+                              Endpoint->EndpointOldIrql);
+            return;
+        }
+
+        Entry = Transfer->TransferLink.Flink;
+    }
+
+    Entry = Endpoint->TransferList.Flink;
+
+    while (Entry && Entry != &Endpoint->TransferList)
+    {
+        Transfer = CONTAINING_RECORD(Entry,
+                                     USBPORT_TRANSFER,
+                                     TransferLink);
+
+        if (Transfer->Flags & TRANSFER_FLAG_ABORTED)
+        {
+            DPRINT_CORE("USBPORT_FlushAbortList: Aborted ActiveTransfer - %p\n",
+                        Transfer);
+
+            KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
+                              Endpoint->EndpointOldIrql);
+            return;
+        }
+
+        Entry = Transfer->TransferLink.Flink;
+    }
+
+    AbortList = &Endpoint->AbortList;
+
+    while (!IsListEmpty(AbortList))
+    {
+        //DbgBreakPoint();
+
+        Irp = CONTAINING_RECORD(AbortList->Flink,
+                                IRP,
+                                Tail.Overlay.ListEntry);
+
+        RemoveHeadList(AbortList);
+        InsertTailList(&List, &Irp->Tail.Overlay.ListEntry);
+    }
+
+    KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
+
+    while (!IsListEmpty(&List))
+    {
+        //DbgBreakPoint();
+
+        Irp = CONTAINING_RECORD(List.Flink,
+                                IRP,
+                                Tail.Overlay.ListEntry);
+
+        RemoveHeadList(&List);
+
+        Urb = URB_FROM_IRP(Irp);
+
+        DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
+        InterlockedDecrement(&DeviceHandle->DeviceHandleLock);
+
+        Status = USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_SUCCESS);
+
+        DPRINT_CORE("USBPORT_FlushAbortList: complete Irp - %p\n", Irp);
+
+        Irp->IoStatus.Status = Status;
+        Irp->IoStatus.Information = 0;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    }
+}
+
+VOID
+NTAPI
+USBPORT_FlushCancelList(IN PUSBPORT_ENDPOINT Endpoint)
+{
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION  FdoExtension;
+    PUSBPORT_TRANSFER Transfer;
+    PIRP Irp;
+    KIRQL OldIrql;
+    KIRQL PrevIrql;
+
+    DPRINT_CORE("USBPORT_FlushCancelList: ... \n");
+
+    FdoDevice = Endpoint->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    KeAcquireSpinLock(&FdoExtension->FlushTransferSpinLock, &OldIrql);
+    KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock);
+
+    while (!IsListEmpty(&Endpoint->CancelList))
+    {
+        Transfer = CONTAINING_RECORD(Endpoint->CancelList.Flink,
+                                     USBPORT_TRANSFER,
+                                     TransferLink);
+
+        RemoveHeadList(&Endpoint->CancelList);
+
+        Irp = Transfer->Irp;
+
+        if (Irp)
+        {
+            DPRINT("USBPORT_FlushCancelList: Irp - %p\n", Irp);
+
+            IoAcquireCancelSpinLock(&PrevIrql);
+            IoSetCancelRoutine(Irp, NULL);
+            IoReleaseCancelSpinLock(PrevIrql);
+
+            USBPORT_RemoveActiveTransferIrp(FdoDevice, Irp);
+        }
+
+        KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
+        KeReleaseSpinLock(&FdoExtension->FlushTransferSpinLock, OldIrql);
+
+        if (Endpoint->Flags & ENDPOINT_FLAG_NUKE)
+        {
+            USBPORT_CompleteTransfer(Transfer->Urb, USBD_STATUS_DEVICE_GONE);
+        }
+        else
+        {
+            if (Transfer->Flags & TRANSFER_FLAG_DEVICE_GONE)
+            {
+                USBPORT_CompleteTransfer(Transfer->Urb,
+                                         USBD_STATUS_DEVICE_GONE);
+            }
+            else
+            {
+                USBPORT_CompleteTransfer(Transfer->Urb,
+                                         USBD_STATUS_CANCELED);
+            }
+        }
+
+        KeAcquireSpinLock(&FdoExtension->FlushTransferSpinLock, &OldIrql);
+        KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock);
+    }
+
+    KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
+    KeReleaseSpinLock(&FdoExtension->FlushTransferSpinLock, OldIrql);
+
+    USBPORT_FlushAbortList(Endpoint);
+}
+
+VOID
+NTAPI
+USBPORT_FlushPendingTransfers(IN PUSBPORT_ENDPOINT Endpoint)
+{
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    BOOLEAN IsMapTransfer;
+    BOOLEAN IsEnd = FALSE;
+    PLIST_ENTRY List;
+    PUSBPORT_TRANSFER Transfer;
+    KIRQL PrevIrql;
+    PURB Urb;
+    PIRP Irp;
+    PIRP irp;
+    KIRQL OldIrql;
+    BOOLEAN Result;
+
+    DPRINT_CORE("USBPORT_FlushPendingTransfers: Endpoint - %p\n", Endpoint);
+
+    FdoDevice = Endpoint->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    if (InterlockedCompareExchange(&Endpoint->FlushPendingLock, 1, 0))
+    {
+        DPRINT_CORE("USBPORT_FlushPendingTransfers: Endpoint Locked \n");
+        return;
+    }
+
+    while (TRUE)
+    {
+        IsMapTransfer = 0;
+
+        KeAcquireSpinLock(&FdoExtension->FlushPendingTransferSpinLock,
+                          &OldIrql);
+
+        KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock);
+
+        if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND)
+        {
+            IsEnd = TRUE;
+
+            KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
+            KeReleaseSpinLock(&FdoExtension->FlushPendingTransferSpinLock,
+                              OldIrql);
+            goto Next;
+        }
+
+        if (!(Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0))
+        {
+            if (!IsListEmpty(&Endpoint->TransferList))
+            {
+                List = Endpoint->TransferList.Flink;
+
+                while (List && List != &Endpoint->TransferList)
+                {
+                    Transfer = CONTAINING_RECORD(List,
+                                                 USBPORT_TRANSFER,
+                                                 TransferLink);
+
+                    if (!(Transfer->Flags & TRANSFER_FLAG_SUBMITED))
+                    {
+                        KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
+                        KeReleaseSpinLock(&FdoExtension->FlushPendingTransferSpinLock,
+                                          OldIrql);
+
+                        IsEnd = TRUE;
+                        goto Worker;
+                    }
+
+                    List = Transfer->TransferLink.Flink;
+                }
+            }
+        }
+
+        List = Endpoint->PendingTransferList.Flink;
+
+        if (List == NULL || IsListEmpty(&Endpoint->PendingTransferList))
+        {
+            KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
+            KeReleaseSpinLock(&FdoExtension->FlushPendingTransferSpinLock,
+                              OldIrql);
+
+            IsEnd = TRUE;
+            goto Worker;
+        }
+
+        Transfer = CONTAINING_RECORD(List,
+                                     USBPORT_TRANSFER,
+                                     TransferLink);
+
+        if (Transfer->Irp)
+        {
+            DPRINT_CORE("USBPORT_FlushPendingTransfers: Transfer->Irp->CancelRoutine - %p\n",
+                        Transfer->Irp->CancelRoutine);
+        }
+
+        if (Transfer->Irp &&
+            (IoSetCancelRoutine(Transfer->Irp, NULL) == NULL))
+        {
+            DPRINT_CORE("USBPORT_FlushPendingTransfers: Transfer->Irp - %p\n",
+                        Transfer->Irp);
+
+            Transfer = NULL;
+            IsEnd = TRUE;
+        }
+
+        if (!Transfer)
+        {
+            KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
+            KeReleaseSpinLock(&FdoExtension->FlushPendingTransferSpinLock,
+                              OldIrql);
+
+            if (IsMapTransfer)
+            {
+                USBPORT_FlushMapTransfers(FdoDevice);
+                goto Next;
+            }
+
+            goto Worker;
+        }
+
+        Irp = Transfer->Irp;
+        Urb = Transfer->Urb;
+
+        RemoveEntryList(&Transfer->TransferLink);
+        Transfer->TransferLink.Flink = NULL;
+        Transfer->TransferLink.Blink = NULL;
+
+        irp = Irp;
+
+        if (Irp)
+        {
+            irp = USBPORT_RemovePendingTransferIrp(FdoDevice, Irp);
+        }
+
+        KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
+        KeReleaseSpinLock(&FdoExtension->FlushPendingTransferSpinLock,
+                          OldIrql);
+
+        KeAcquireSpinLock(&FdoExtension->FlushTransferSpinLock, &OldIrql);
+
+        if (irp)
+        {
+            IoSetCancelRoutine(irp, USBPORT_CancelActiveTransferIrp);
+
+            if (Irp->Cancel && IoSetCancelRoutine(irp, NULL))
+            {
+                DPRINT_CORE("USBPORT_FlushPendingTransfers: irp - %p\n", irp);
+
+                KeReleaseSpinLock(&FdoExtension->FlushTransferSpinLock,
+                                  OldIrql);
+
+                USBPORT_CompleteTransfer(Transfer->Urb, USBD_STATUS_CANCELED);
+                goto Worker;
+            }
+
+            USBPORT_FindUrbInIrpTable(FdoExtension->ActiveIrpTable, Urb, irp);
+            USBPORT_InsertIrpInTable(FdoExtension->ActiveIrpTable, irp);
+        }
+
+        IsMapTransfer = USBPORT_QueueActiveUrbToEndpoint(Endpoint, Urb);
+
+        KeReleaseSpinLock(&FdoExtension->FlushTransferSpinLock, OldIrql);
+
+        if (IsMapTransfer)
+        {
+            USBPORT_FlushMapTransfers(FdoDevice);
+            goto Next;
+        }
+
+Worker:
+        KeRaiseIrql(DISPATCH_LEVEL, &PrevIrql);
+        Result = USBPORT_EndpointWorker(Endpoint, FALSE);
+        KeLowerIrql(PrevIrql);
+
+        if (Result)
+            USBPORT_InvalidateEndpointHandler(FdoDevice,
+                                              Endpoint,
+                                              INVALIDATE_ENDPOINT_WORKER_THREAD);
+
+Next:
+        if (IsEnd)
+        {
+            InterlockedDecrement(&Endpoint->FlushPendingLock);
+            DPRINT_CORE("USBPORT_FlushPendingTransfers: Endpoint Unlocked. Exit\n");
+            return;
+        }
+    }
+}
+
+VOID
+NTAPI
+USBPORT_QueuePendingUrbToEndpoint(IN PUSBPORT_ENDPOINT Endpoint,
+                                  IN PURB Urb)
+{
+    PUSBPORT_TRANSFER Transfer;
+
+    DPRINT_CORE("USBPORT_QueuePendingUrbToEndpoint: Endpoint - %p, Urb - %p\n",
+                Endpoint,
+                Urb);
+
+    Transfer = Urb->UrbControlTransfer.hca.Reserved8[0];
+    //FIXME USBPORT_ResetEndpointIdle();
+    InsertTailList(&Endpoint->PendingTransferList, &Transfer->TransferLink);
+    Urb->UrbHeader.Status = USBD_STATUS_PENDING;
+}
+
+BOOLEAN
+NTAPI
+USBPORT_QueueActiveUrbToEndpoint(IN PUSBPORT_ENDPOINT Endpoint,
+                                 IN PURB Urb)
+{
+    PUSBPORT_TRANSFER Transfer;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_DEVICE_HANDLE DeviceHandle;
+    KIRQL OldIrql;
+
+    DPRINT_CORE("USBPORT_QueueActiveUrbToEndpoint: Endpoint - %p, Urb - %p\n",
+                Endpoint,
+                Urb);
+
+    Transfer = Urb->UrbControlTransfer.hca.Reserved8[0];
+    FdoDevice = Endpoint->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
+                      &Endpoint->EndpointOldIrql);
+
+    if ((Endpoint->Flags & ENDPOINT_FLAG_NUKE) ||
+        (Transfer->Flags & TRANSFER_FLAG_ABORTED))
+    {
+        InsertTailList(&Endpoint->CancelList, &Transfer->TransferLink);
+
+        KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
+                          Endpoint->EndpointOldIrql);
+
+        //DPRINT_CORE("USBPORT_QueueActiveUrbToEndpoint: return FALSE\n");
+        return FALSE;
+    }
+
+    if (Transfer->TransferParameters.TransferBufferLength == 0 ||
+        !(Endpoint->Flags & ENDPOINT_FLAG_DMA_TYPE))
+    {
+        InsertTailList(&Endpoint->TransferList, &Transfer->TransferLink);
+
+        KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
+                          Endpoint->EndpointOldIrql);
+
+        //DPRINT_CORE("USBPORT_QueueActiveUrbToEndpoint: return FALSE\n");
+        return FALSE;
+    }
+
+    KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
+
+    KeAcquireSpinLock(&FdoExtension->MapTransferSpinLock, &OldIrql);
+
+    InsertTailList(&FdoExtension->MapTransferList, &Transfer->TransferLink);
+
+    DeviceHandle = Transfer->Urb->UrbHeader.UsbdDeviceHandle;
+    InterlockedIncrement(&DeviceHandle->DeviceHandleLock);
+
+    KeReleaseSpinLock(&FdoExtension->MapTransferSpinLock, OldIrql);
+
+    //DPRINT_CORE("USBPORT_QueueActiveUrbToEndpoint: return TRUE\n");
+    return TRUE;
+}
+
+VOID
+NTAPI
+USBPORT_QueuePendingTransferIrp(IN PIRP Irp)
+{
+    PURB Urb;
+    PUSBPORT_TRANSFER Transfer;
+    PUSBPORT_ENDPOINT Endpoint;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT_CORE("USBPORT_QueuePendingTransferIrp: Irp - %p\n", Irp);
+
+    Urb = URB_FROM_IRP(Irp);
+
+    Transfer = Urb->UrbControlTransfer.hca.Reserved8[0];
+    Endpoint = Transfer->Endpoint;
+
+    FdoDevice = Endpoint->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    Irp->IoStatus.Status = STATUS_PENDING;
+    IoMarkIrpPending(Irp);
+
+    IoSetCancelRoutine(Irp, USBPORT_CancelPendingTransferIrp);
+
+    if (Irp->Cancel && !IoSetCancelRoutine(Irp, NULL))
+    {
+        USBPORT_CompleteTransfer(Urb, USBD_STATUS_CANCELED);
+    }
+    else
+    {
+        USBPORT_InsertIrpInTable(FdoExtension->PendingIrpTable, Irp);
+        USBPORT_QueuePendingUrbToEndpoint(Endpoint, Urb);
+    }
+}
+
+VOID
+NTAPI
+USBPORT_QueueTransferUrb(IN PURB Urb)
+{
+    PUSBPORT_TRANSFER Transfer;
+    PUSBPORT_ENDPOINT Endpoint;
+    PIRP Irp;
+    PUSBPORT_DEVICE_HANDLE DeviceHandle;
+    PUSBPORT_TRANSFER_PARAMETERS Parameters;
+
+    DPRINT_CORE("USBPORT_QueueTransferUrb: Urb - %p\n", Urb);
+
+    if (Urb->UrbControlTransfer.TransferFlags & USBD_DEFAULT_PIPE_TRANSFER)
+        Urb->UrbHeader.Function = URB_FUNCTION_CONTROL_TRANSFER;
+
+    Transfer = Urb->UrbControlTransfer.hca.Reserved8[0];
+    Parameters = &Transfer->TransferParameters;
+
+    Endpoint = Transfer->Endpoint;
+    Endpoint->Flags &= ~ENDPOINT_FLAG_QUEUENE_EMPTY;
+
+    Parameters->TransferBufferLength = Urb->UrbControlTransfer.TransferBufferLength;
+    Parameters->TransferFlags = Urb->UrbControlTransfer.TransferFlags;
+
+    Transfer->TransferBufferMDL = Urb->UrbControlTransfer.TransferBufferMDL;
+
+    if (Urb->UrbControlTransfer.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
+    {
+        Transfer->Direction = USBPORT_DMA_DIRECTION_FROM_DEVICE;
+    }
+    else
+    {
+        Transfer->Direction = USBPORT_DMA_DIRECTION_TO_DEVICE;
+    }
+
+    if (Endpoint->EndpointProperties.TransferType == USBPORT_TRANSFER_TYPE_CONTROL)
+    {
+        RtlCopyMemory(&Parameters->SetupPacket,
+                      Urb->UrbControlTransfer.SetupPacket,
+                      sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+    }
+
+    DPRINT_URB("... URB TransferBufferLength - %x\n",
+           Urb->UrbControlTransfer.TransferBufferLength);
+
+    Urb->UrbControlTransfer.TransferBufferLength = 0;
+
+    Irp = Transfer->Irp;
+
+    if (Irp)
+    {
+        USBPORT_QueuePendingTransferIrp(Irp);
+    }
+    else
+    {
+        USBPORT_QueuePendingUrbToEndpoint(Endpoint, Urb);
+    }
+
+    DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
+    InterlockedDecrement(&DeviceHandle->DeviceHandleLock);
+
+    USBPORT_FlushPendingTransfers(Endpoint);
+
+    DPRINT_URB("... URB TransferBufferLength - %x\n",
+           Urb->UrbControlTransfer.TransferBufferLength);
+
+    if (Urb->UrbControlTransfer.TransferBufferLength)
+    {
+        PULONG Buffer;
+        ULONG BufferLength;
+        ULONG_PTR BufferEnd;
+        ULONG ix;
+
+        Buffer = Urb->UrbControlTransfer.TransferBuffer;
+        BufferLength = Urb->UrbControlTransfer.TransferBufferLength;
+        BufferEnd = (ULONG_PTR)Buffer + BufferLength;
+
+        DPRINT_URB("URB TransferBuffer - %p\n", Buffer);
+
+        for (ix = 0; (ULONG_PTR)(Buffer + ix) < BufferEnd; ix++)
+        {
+            DPRINT_URB("Buffer[%02X] - %p\n", ix, Buffer[ix]);
+        }
+    }
+}
+
+VOID
+NTAPI
+USBPORT_FlushAllEndpoints(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION  FdoExtension;
+    PLIST_ENTRY Entry;
+    PUSBPORT_ENDPOINT Endpoint;
+    LIST_ENTRY List;
+    KIRQL OldIrql;
+
+    DPRINT_CORE("USBPORT_FlushAllEndpoints: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql);
+
+    InitializeListHead(&List);
+
+    Entry = FdoExtension->EndpointList.Flink;
+
+    while (Entry && Entry != &FdoExtension->EndpointList)
+    {
+        Endpoint = CONTAINING_RECORD(Entry,
+                                     USBPORT_ENDPOINT,
+                                     EndpointLink);
+
+        if (USBPORT_GetEndpointState(Endpoint) != USBPORT_ENDPOINT_CLOSED)
+        {
+            InsertTailList(&List, &Endpoint->FlushLink);
+        }
+
+        Entry = Endpoint->EndpointLink.Flink;
+    }
+
+    KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql);
+
+    while (!IsListEmpty(&List))
+    {
+        Endpoint = CONTAINING_RECORD(List.Flink,
+                                     USBPORT_ENDPOINT,
+                                     FlushLink);
+
+        RemoveHeadList(&List);
+
+        Endpoint->FlushLink.Flink = NULL;
+        Endpoint->FlushLink.Blink = NULL;
+
+        if (!IsListEmpty(&Endpoint->PendingTransferList))
+        {
+            USBPORT_FlushPendingTransfers(Endpoint);
+        }
+    }
+
+    DPRINT_CORE("USBPORT_FlushAllEndpoints: exit\n");
+}
+
+ULONG
+NTAPI
+USBPORT_KillEndpointActiveTransfers(IN PDEVICE_OBJECT FdoDevice,
+                                    IN PUSBPORT_ENDPOINT Endpoint)
+{
+    PLIST_ENTRY ActiveList;
+    PUSBPORT_TRANSFER Transfer;
+    ULONG KilledTransfers = 0;
+
+    DPRINT_CORE("USBPORT_KillEndpointActiveTransfers \n");
+
+    ActiveList = Endpoint->TransferList.Flink;
+
+    while (ActiveList && ActiveList != &Endpoint->TransferList)
+    {
+        ++KilledTransfers;
+
+        Transfer = CONTAINING_RECORD(ActiveList,
+                                     USBPORT_TRANSFER,
+                                     TransferLink);
+
+        Transfer->Flags |= TRANSFER_FLAG_ABORTED;
+
+        ActiveList = Transfer->TransferLink.Flink;
+    }
+
+    USBPORT_FlushPendingTransfers(Endpoint);
+    USBPORT_FlushCancelList(Endpoint);
+
+    return KilledTransfers;
+}
+
+VOID
+NTAPI
+USBPORT_FlushController(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION  FdoExtension;
+    PLIST_ENTRY Entry;
+    PUSBPORT_ENDPOINT Endpoint;
+    ULONG KilledTransfers = 0;
+    PLIST_ENTRY EndpointList;
+    KIRQL OldIrql;
+    LIST_ENTRY FlushList;
+
+    DPRINT_CORE("USBPORT_FlushController \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    EndpointList = &FdoExtension->EndpointList;
+
+    while (TRUE)
+    {
+        KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql);
+
+        InitializeListHead(&FlushList);
+
+        Entry = EndpointList->Flink;
+
+        if (!IsListEmpty(EndpointList))
+        {
+            while (Entry && Entry != EndpointList)
+            {
+                Endpoint = CONTAINING_RECORD(Entry,
+                                             USBPORT_ENDPOINT,
+                                             EndpointLink);
+
+                if (Endpoint->StateLast != USBPORT_ENDPOINT_REMOVE &&
+                    Endpoint->StateLast != USBPORT_ENDPOINT_CLOSED)
+                {
+                    InterlockedIncrement(&Endpoint->LockCounter);
+                    InsertTailList(&FlushList, &Endpoint->FlushControllerLink);
+                }
+
+                Entry = Endpoint->EndpointLink.Flink;
+            }
+        }
+
+        KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql);
+
+        while (!IsListEmpty(&FlushList))
+        {
+            Endpoint = CONTAINING_RECORD(FlushList.Flink,
+                                         USBPORT_ENDPOINT,
+                                         FlushControllerLink);
+
+            RemoveHeadList(&FlushList);
+
+            KilledTransfers += USBPORT_KillEndpointActiveTransfers(FdoDevice,
+                                                                   Endpoint);
+
+            InterlockedDecrement(&Endpoint->LockCounter);
+        }
+
+        if (!KilledTransfers)
+            break;
+
+        USBPORT_Wait(FdoDevice, 100);
+    }
+}
+
+VOID
+NTAPI
+USBPORT_BadRequestFlush(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PIRP Irp;
+
+    DPRINT_QUEUE("USBPORT_BadRequestFlush: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    while (TRUE)
+    {
+        Irp = IoCsqRemoveNextIrp(&FdoExtension->BadRequestIoCsq, 0);
+
+        if (!Irp)
+            break;
+
+        DPRINT1("USBPORT_BadRequestFlush: Irp - %p\n", Irp);
+
+        Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
+        Irp->IoStatus.Information = 0;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    }
+}
+
+VOID
+NTAPI
+USBPORT_AbortEndpoint(IN PDEVICE_OBJECT FdoDevice,
+                      IN PUSBPORT_ENDPOINT Endpoint,
+                      IN PIRP Irp)
+{
+    PLIST_ENTRY PendingList;
+    PUSBPORT_TRANSFER PendingTransfer; 
+    PLIST_ENTRY ActiveList;
+    PUSBPORT_TRANSFER ActiveTransfer;
+
+    DPRINT_CORE("USBPORT_AbortEndpoint: Irp - %p\n", Irp);
+
+    KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
+
+    if (Irp)
+    {
+        InsertTailList(&Endpoint->AbortList, &Irp->Tail.Overlay.ListEntry);
+    }
+
+    PendingList = Endpoint->PendingTransferList.Flink;
+
+    while (PendingList && PendingList != &Endpoint->PendingTransferList)
+    {
+        PendingTransfer = CONTAINING_RECORD(PendingList,
+                                            USBPORT_TRANSFER,
+                                            TransferLink);
+
+        DPRINT_CORE("USBPORT_AbortEndpoint: Abort PendingTransfer - %p\n",
+                    PendingTransfer);
+
+        PendingTransfer->Flags |= TRANSFER_FLAG_ABORTED;
+
+        PendingList = PendingTransfer->TransferLink.Flink;
+    }
+
+    ActiveList = Endpoint->TransferList.Flink;
+
+    while (ActiveList && ActiveList != &Endpoint->TransferList)
+    {
+        ActiveTransfer = CONTAINING_RECORD(ActiveList,
+                                           USBPORT_TRANSFER,
+                                           TransferLink);
+
+        DPRINT_CORE("USBPORT_AbortEndpoint: Abort ActiveTransfer - %p\n",
+                    ActiveTransfer);
+
+        ActiveTransfer->Flags |= TRANSFER_FLAG_ABORTED;
+
+        if (Endpoint->Flags & ENDPOINT_FLAG_ABORTING)
+        {
+            ActiveTransfer->Flags |= TRANSFER_FLAG_DEVICE_GONE;
+        }
+
+        ActiveList = ActiveTransfer->TransferLink.Flink;
+    }
+
+    KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
+
+    USBPORT_InvalidateEndpointHandler(FdoDevice,
+                                      Endpoint,
+                                      INVALIDATE_ENDPOINT_INT_NEXT_SOF);
+
+    USBPORT_FlushPendingTransfers(Endpoint);
+    USBPORT_FlushCancelList(Endpoint);
+}
\ No newline at end of file
diff --git a/reactos/drivers/usb/usbport/roothub.c b/reactos/drivers/usb/usbport/roothub.c
new file mode 100644 (file)
index 0000000..5dd44f5
--- /dev/null
@@ -0,0 +1,1019 @@
+#include "usbport.h"
+
+#define NDEBUG
+#include <debug.h>
+
+#define NDEBUG_USBPORT_CORE
+#include "usbdebug.h"
+
+RHSTATUS
+NTAPI
+USBPORT_MPStatusToRHStatus(IN MPSTATUS MPStatus)
+{
+    RHSTATUS RHStatus = RH_STATUS_SUCCESS;
+
+    //DPRINT("USBPORT_MPStatusToRHStatus: MPStatus - %x\n", MPStatus);
+
+    if (MPStatus)
+    {
+        RHStatus = (MPStatus != MP_STATUS_FAILURE);
+        ++RHStatus;
+    }
+
+    return RHStatus;
+}
+
+MPSTATUS
+NTAPI
+USBPORT_RH_SetFeatureUSB2PortPower(IN PDEVICE_OBJECT FdoDevice,
+                                   IN USHORT Port)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    PDEVICE_RELATIONS CompanionControllersList;
+    PUSBPORT_REGISTRATION_PACKET CompanionPacket;
+    PDEVICE_OBJECT CompanionFdoDevice;
+    PUSBPORT_DEVICE_EXTENSION CompanionFdoExtension;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    USHORT ix;
+    PDEVICE_OBJECT * Entry;
+    ULONG NumController = 0;
+
+    DPRINT("USBPORT_RootHub_PowerUsb2Port: FdoDevice - %p, Port - %p\n",
+           FdoDevice,
+           Port);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    CompanionControllersList = USBPORT_FindCompanionControllers(FdoDevice,
+                                                                FALSE,
+                                                                TRUE);
+
+    if (!CompanionControllersList)
+    {
+        Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt, Port);
+        return MP_STATUS_SUCCESS;
+    }
+
+    Entry = &CompanionControllersList->Objects[0];
+
+    while (NumController < CompanionControllersList->Count)
+    {
+        CompanionFdoDevice = *Entry;
+
+        CompanionFdoExtension = CompanionFdoDevice->DeviceExtension;
+        CompanionPacket = &CompanionFdoExtension->MiniPortInterface->Packet;
+
+        PdoExtension = CompanionFdoExtension->RootHubPdo->DeviceExtension;
+
+        for (ix = 0;
+             (PdoExtension->CommonExtension.PnpStateFlags & USBPORT_PNP_STATE_STARTED) &&
+              ix < PdoExtension->RootHubDescriptors->Descriptor.bNumberOfPorts;
+             ++ix)
+        {
+            CompanionPacket->RH_SetFeaturePortPower(CompanionFdoExtension->MiniPortExt,
+                                                    ix + 1);
+        }
+
+        ++NumController;
+        ++Entry;
+    }
+
+    Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt, Port);
+
+    if (CompanionControllersList)
+    {
+        ExFreePoolWithTag(CompanionControllersList, USB_PORT_TAG);
+    }
+
+    return MP_STATUS_SUCCESS;
+}
+
+RHSTATUS
+NTAPI
+USBPORT_RootHubClassCommand(IN PDEVICE_OBJECT FdoDevice,
+                            IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
+                            IN PVOID Buffer,
+                            IN PULONG BufferLength)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    USHORT Port;
+    USHORT Feature;
+    MPSTATUS MPStatus;
+    RHSTATUS RHStatus = RH_STATUS_UNSUCCESSFUL;
+    KIRQL OldIrql;
+
+    DPRINT("USBPORT_RootHubClassCommand: USB command - %x, *BufferLength - %x\n",
+           SetupPacket->bRequest,
+           *BufferLength);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    PdoExtension = FdoExtension->RootHubPdo->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    Port = SetupPacket->wIndex.W;
+
+    switch (SetupPacket->bRequest)
+    {
+        case USB_REQUEST_GET_STATUS:
+        {
+            if (!Buffer)
+            {
+                return RHStatus;
+            }
+
+            *(PULONG)Buffer = 0;
+
+            if (SetupPacket->bmRequestType.Recipient == BMREQUEST_TO_OTHER)
+            {
+                ASSERT(*BufferLength >= 4);
+
+                if (Port > PdoExtension->RootHubDescriptors->Descriptor.bNumberOfPorts ||
+                    Port <= 0  ||
+                    SetupPacket->wLength < 4)
+                {
+                    return RHStatus;
+                }
+  
+                KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+
+                MPStatus = Packet->RH_GetPortStatus(FdoExtension->MiniPortExt,
+                                                    SetupPacket->wIndex.W,
+                                                    Buffer);
+
+                KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+            }
+            else
+            {
+                KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+
+                MPStatus = Packet->RH_GetHubStatus(FdoExtension->MiniPortExt,
+                                                   Buffer);
+
+                KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+            }
+
+            RHStatus = USBPORT_MPStatusToRHStatus(MPStatus);
+            break;
+        }
+
+        case USB_REQUEST_CLEAR_FEATURE:
+            Feature = SetupPacket->wValue.W;
+
+            if ((SetupPacket->bmRequestType.Recipient) != USBPORT_RECIPIENT_ROOT_PORT)
+            {
+                if (Feature == FEATURE_C_HUB_LOCAL_POWER)
+                {
+                    RHStatus = RH_STATUS_SUCCESS;
+                    return RHStatus;
+                }
+            
+                if (Feature == FEATURE_C_HUB_OVER_CURRENT)
+                {
+                    MPStatus = Packet->RH_ClearFeaturePortOvercurrentChange(FdoExtension->MiniPortExt,
+                                                                            0);
+                    RHStatus = USBPORT_MPStatusToRHStatus(MPStatus);
+                    return RHStatus;
+                }
+            
+                DbgBreakPoint();
+                return RHStatus;
+            }
+
+            switch (Feature)
+            {
+                case FEATURE_PORT_ENABLE:
+                    MPStatus = Packet->RH_ClearFeaturePortEnable(FdoExtension->MiniPortExt,
+                                                                 Port);
+                    break;
+
+                case FEATURE_PORT_SUSPEND:
+                    MPStatus = Packet->RH_ClearFeaturePortSuspend(FdoExtension->MiniPortExt,
+                                                                  Port);
+                    break;
+
+                case FEATURE_PORT_POWER:
+                    MPStatus = Packet->RH_ClearFeaturePortPower(FdoExtension->MiniPortExt,
+                                                                Port);
+                    break;
+
+                case FEATURE_C_PORT_CONNECTION:
+                    MPStatus = Packet->RH_ClearFeaturePortConnectChange(FdoExtension->MiniPortExt,
+                                                                        Port);
+                    break;
+
+                case FEATURE_C_PORT_ENABLE:
+                     MPStatus = Packet->RH_ClearFeaturePortEnableChange(FdoExtension->MiniPortExt,
+                                                                        Port);
+                    break;
+
+                case FEATURE_C_PORT_SUSPEND:
+                    MPStatus = Packet->RH_ClearFeaturePortSuspendChange(FdoExtension->MiniPortExt,
+                                                                        Port);
+                    break;
+
+                case FEATURE_C_PORT_OVER_CURRENT:
+                    MPStatus = Packet->RH_ClearFeaturePortOvercurrentChange(FdoExtension->MiniPortExt,
+                                                                            Port);
+                    break;
+
+                case FEATURE_C_PORT_RESET:
+                    MPStatus = Packet->RH_ClearFeaturePortResetChange(FdoExtension->MiniPortExt,
+                                                                      Port);
+                    break;
+
+                default:
+                    DPRINT1("USBPORT_RootHubClassCommand: Not supported feature - %x\n",
+                            Feature);
+                    return RHStatus;
+            }
+
+            RHStatus = USBPORT_MPStatusToRHStatus(MPStatus);
+            break;
+
+        case USB_REQUEST_SET_FEATURE:
+            if (SetupPacket->bmRequestType.Recipient != USBPORT_RECIPIENT_ROOT_PORT)
+            {
+                return RHStatus;
+            }
+
+            Feature = SetupPacket->wValue.W;
+
+            switch (Feature)
+            {
+                case FEATURE_PORT_ENABLE:
+                    MPStatus = Packet->RH_SetFeaturePortEnable(FdoExtension->MiniPortExt,
+                                                               Port);
+                    break;
+
+                case FEATURE_PORT_SUSPEND:
+                    MPStatus = Packet->RH_SetFeaturePortSuspend(FdoExtension->MiniPortExt,
+                                                                Port);
+                    break;
+
+                case FEATURE_PORT_RESET:
+                    MPStatus = Packet->RH_SetFeaturePortReset(FdoExtension->MiniPortExt,
+                                                              Port);
+                    break;
+
+                case FEATURE_PORT_POWER:
+                    if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
+                    {
+                        MPStatus = USBPORT_RH_SetFeatureUSB2PortPower(FdoDevice, Port);
+                    }
+                    else
+                    {
+                        MPStatus = Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt,
+                                                                  Port);
+                    }
+
+                    break;
+
+                default:
+                    DPRINT1("USBPORT_RootHubClassCommand: Not supported feature - %x\n",
+                            Feature);
+                    return RHStatus;
+            }
+
+            RHStatus = USBPORT_MPStatusToRHStatus(MPStatus);
+            break;
+
+        case USB_REQUEST_GET_DESCRIPTOR:
+            if (Buffer &&
+                SetupPacket->wValue.W == 0 &&
+                SetupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST)
+            {
+                SIZE_T DescriptorLength;
+
+                DescriptorLength = PdoExtension->RootHubDescriptors->Descriptor.bDescriptorLength;
+
+                if (*BufferLength < DescriptorLength)
+                    DescriptorLength = *BufferLength;
+
+                RtlCopyMemory(Buffer,
+                              &PdoExtension->RootHubDescriptors->Descriptor,
+                              DescriptorLength);
+
+                *BufferLength = DescriptorLength;
+                RHStatus = RH_STATUS_SUCCESS;
+            }
+
+            break;
+
+        default:
+            DPRINT1("USBPORT_RootHubClassCommand: Not supported USB request - %x\n",
+                    SetupPacket->bRequest);
+            //USB_REQUEST_SET_ADDRESS                   0x05
+            //USB_REQUEST_SET_DESCRIPTOR                0x07
+            //USB_REQUEST_GET_CONFIGURATION             0x08
+            //USB_REQUEST_SET_CONFIGURATION             0x09
+            //USB_REQUEST_GET_INTERFACE                 0x0A
+            //USB_REQUEST_SET_INTERFACE                 0x0B
+            //USB_REQUEST_SYNC_FRAME                    0x0C
+            break;
+    }
+
+    return RHStatus;
+}
+
+RHSTATUS
+NTAPI
+USBPORT_RootHubStandardCommand(IN PDEVICE_OBJECT FdoDevice,
+                               IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
+                               IN PVOID Buffer,
+                               IN OUT PULONG TransferLength)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    SIZE_T Length;
+    PVOID Descriptor;
+    SIZE_T DescriptorLength;
+    MPSTATUS MPStatus;
+    RHSTATUS RHStatus = RH_STATUS_UNSUCCESSFUL;
+    KIRQL OldIrql;
+
+    DPRINT("USBPORT_RootHubStandardCommand: USB command - %x, TransferLength - %p\n",
+           SetupPacket->bRequest,
+           TransferLength);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    PdoExtension = FdoExtension->RootHubPdo->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    switch (SetupPacket->bRequest)
+    {
+        case USB_REQUEST_GET_DESCRIPTOR:
+            if (SetupPacket->wValue.LowByte ||
+                !(SetupPacket->bmRequestType.Dir))
+            {
+                return RHStatus;
+            }
+
+            switch (SetupPacket->wValue.HiByte)
+            {
+                case USB_DEVICE_DESCRIPTOR_TYPE:
+                    Descriptor = &PdoExtension->RootHubDescriptors->DeviceDescriptor;
+                    DescriptorLength = sizeof(USB_DEVICE_DESCRIPTOR);
+                    break;
+
+                case USB_CONFIGURATION_DESCRIPTOR_TYPE:
+                    Descriptor = &PdoExtension->RootHubDescriptors->ConfigDescriptor;
+                    DescriptorLength = sizeof(USB_CONFIGURATION_DESCRIPTOR) +
+                                       sizeof(USB_INTERFACE_DESCRIPTOR) +
+                                       sizeof(USB_ENDPOINT_DESCRIPTOR);
+                    break;
+
+                default:
+                    DPRINT1("USBPORT_RootHubStandardCommand: Not supported Descriptor Type - %x\n",
+                            SetupPacket->wValue.HiByte);
+                    return RHStatus;
+            }
+
+            if (!Descriptor)
+            {
+                return RHStatus;
+            }
+
+            if (*TransferLength >= DescriptorLength)
+                Length = DescriptorLength;
+            else
+                Length = *TransferLength;
+
+            RtlCopyMemory(Buffer, Descriptor, Length);
+            *TransferLength = Length;
+
+            RHStatus = RH_STATUS_SUCCESS;
+            break;
+
+        case USB_REQUEST_GET_STATUS:
+            if (!SetupPacket->wValue.W &&
+                 SetupPacket->wLength == sizeof(USHORT) &&
+                 !SetupPacket->wIndex.W &&
+                 SetupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST)
+            {
+                KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+
+                MPStatus = Packet->RH_GetStatus(FdoExtension->MiniPortExt,
+                                                Buffer);
+
+                KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+
+                *TransferLength = sizeof(USHORT);
+                RHStatus = USBPORT_MPStatusToRHStatus(MPStatus);
+            }
+
+            break;
+
+        case USB_REQUEST_GET_CONFIGURATION:
+            if (SetupPacket->wValue.W ||
+                SetupPacket->wIndex.W ||
+                SetupPacket->wLength != 1 ||
+                SetupPacket->bmRequestType.Dir == BMREQUEST_HOST_TO_DEVICE)
+            {
+                return RHStatus;
+            }
+
+            Length = 0;
+
+            if (*TransferLength >= 1)
+            {
+                Length = 1;
+                RtlCopyMemory(Buffer, &PdoExtension->ConfigurationValue, Length);
+            }
+
+            *TransferLength = Length;
+
+            RHStatus = RH_STATUS_SUCCESS;
+            break;
+
+        case USB_REQUEST_SET_CONFIGURATION:
+            if (!SetupPacket->wIndex.W &&
+                !SetupPacket->wLength &&
+                !(SetupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST))
+            {
+                if (SetupPacket->wValue.W == 0 ||
+                    SetupPacket->wValue.W == 
+                        PdoExtension->RootHubDescriptors->ConfigDescriptor.bConfigurationValue)
+                {
+                  PdoExtension->ConfigurationValue = SetupPacket->wValue.LowByte;
+                  RHStatus = RH_STATUS_SUCCESS;
+                }
+            }
+
+            break;
+
+        case USB_REQUEST_SET_ADDRESS:
+            if (!SetupPacket->wIndex.W &&
+                !SetupPacket->wLength &&
+                !(SetupPacket->bmRequestType.Dir))
+            {
+                PdoExtension->DeviceHandle.DeviceAddress = SetupPacket->wValue.LowByte;
+                RHStatus = RH_STATUS_SUCCESS;
+                break;
+            }
+
+            break;
+
+        default:
+            DPRINT1("USBPORT_RootHubStandardCommand: Not supported USB request - %x\n",
+                    SetupPacket->bRequest);
+            //USB_REQUEST_CLEAR_FEATURE                 0x01
+            //USB_REQUEST_SET_FEATURE                   0x03
+            //USB_REQUEST_SET_DESCRIPTOR                0x07
+            //USB_REQUEST_GET_INTERFACE                 0x0A
+            //USB_REQUEST_SET_INTERFACE                 0x0B
+            //USB_REQUEST_SYNC_FRAME                    0x0C
+            break;
+    }
+
+    return RHStatus;
+}
+
+RHSTATUS
+NTAPI
+USBPORT_RootHubEndpoint0(IN PUSBPORT_TRANSFER Transfer)
+{
+    PDEVICE_OBJECT FdoDevice;
+    SIZE_T TransferLength;
+    PVOID Buffer;
+    PURB Urb;
+    PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
+    UCHAR Type;
+    RHSTATUS RHStatus;
+
+    DPRINT("USBPORT_RootHubEndpoint0: Transfer - %p\n", Transfer);
+
+    TransferLength = Transfer->TransferParameters.TransferBufferLength;
+    Urb = Transfer->Urb;
+    FdoDevice = Transfer->Endpoint->FdoDevice;
+
+    if (TransferLength > 0)
+        Buffer = Urb->UrbControlTransfer.TransferBufferMDL->MappedSystemVa;
+    else
+        Buffer = NULL;
+
+    SetupPacket = (PUSB_DEFAULT_PIPE_SETUP_PACKET)Urb->UrbControlTransfer.SetupPacket;
+
+    Type = SetupPacket->bmRequestType.Type;
+
+    if (Type == BMREQUEST_STANDARD)
+    {
+        RHStatus = USBPORT_RootHubStandardCommand(FdoDevice,
+                                                  SetupPacket,
+                                                  Buffer,
+                                                  &TransferLength);
+    }
+    else if (Type == BMREQUEST_CLASS)
+    {
+        RHStatus = USBPORT_RootHubClassCommand(FdoDevice,
+                                               SetupPacket,
+                                               Buffer,
+                                               &TransferLength);
+    }
+    else
+    {
+        return RH_STATUS_UNSUCCESSFUL;
+    }
+
+    if (RHStatus == RH_STATUS_SUCCESS)
+        Transfer->CompletedTransferLen = TransferLength;
+
+    return RHStatus;
+}
+
+RHSTATUS
+NTAPI
+USBPORT_RootHubSCE(IN PUSBPORT_TRANSFER Transfer)
+{
+    PUSBPORT_ENDPOINT Endpoint;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    ULONG TransferLength;
+    USBHUB_PORT_STATUS PortStatus;
+    USB_HUB_STATUS HubStatus;
+    PVOID Buffer;
+    PULONG AddressBitMap;
+    ULONG Port;
+    PURB Urb;
+    RHSTATUS RHStatus = RH_STATUS_NO_CHANGES;
+    PUSB_HUB_DESCRIPTOR HubDescriptor;
+    UCHAR NumberOfPorts;
+
+    DPRINT("USBPORT_RootHubSCE: Transfer - %p\n", Transfer);
+
+    Endpoint = Transfer->Endpoint;
+
+    FdoExtension = Endpoint->FdoDevice->DeviceExtension;
+    PdoExtension = FdoExtension->RootHubPdo->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    HubDescriptor = &PdoExtension->RootHubDescriptors->Descriptor;
+    NumberOfPorts = HubDescriptor->bNumberOfPorts;
+
+    PortStatus.AsULONG = 0;
+    HubStatus.AsUshort16 = 0;
+
+    Urb = Transfer->Urb;
+    TransferLength = Transfer->TransferParameters.TransferBufferLength;
+
+    if (TransferLength)
+    {
+        Buffer = Urb->UrbControlTransfer.TransferBufferMDL->MappedSystemVa;
+    }
+    else
+    {
+        Buffer = NULL;
+    }
+
+    /* Check parameters */
+
+    if (!Buffer)
+    {
+        /* Not valid parameter */
+        DPRINT1("USBPORT_RootHubSCE: Error! Buffer is NULL\n");
+        return RH_STATUS_UNSUCCESSFUL;
+    }
+
+    if ((TransferLength < (NumberOfPorts / 8 + 1)))
+    {
+        /* Not valid parameters */
+        DPRINT1("USBPORT_RootHubSCE: Error! TransferLength - %x, NumberOfPorts - %x\n",
+                TransferLength,
+                NumberOfPorts);
+
+        return RH_STATUS_UNSUCCESSFUL;
+    }
+
+    RtlZeroMemory(Buffer, TransferLength);
+
+    AddressBitMap = Buffer;
+
+    /* Scan all the ports for changes */
+    for (Port = 1; Port <= NumberOfPorts; Port++)
+    {
+        DPRINT_CORE("USBPORT_RootHubSCE: Port - %p\n", Port);
+
+        /* Request the port status from miniport */
+        if (Packet->RH_GetPortStatus(FdoExtension->MiniPortExt,
+                                     Port,
+                                     &PortStatus))
+        {
+            /* Miniport returned an error */ 
+            DPRINT1("USBPORT_RootHubSCE: RH_GetPortStatus failed\n");
+            return RH_STATUS_UNSUCCESSFUL;
+        }
+
+        if (PortStatus.UsbPortStatusChange.ConnectStatusChange ||
+            PortStatus.UsbPortStatusChange.PortEnableDisableChange ||
+            PortStatus.UsbPortStatusChange.SuspendChange ||
+            PortStatus.UsbPortStatusChange.OverCurrentIndicatorChange ||
+            PortStatus.UsbPortStatusChange.ResetChange)
+        {
+            /* At the port status there is a change */
+            AddressBitMap[Port >> 5] |= 1 << (Port & 0x1F);
+            RHStatus = RH_STATUS_SUCCESS;
+        }
+    }
+
+    /* Request the hub status from miniport */
+    if (!Packet->RH_GetHubStatus(FdoExtension->MiniPortExt, &HubStatus))
+    {
+        if (HubStatus.AsUshort16 & (HUB_STATUS_CHANGE_LOCAL_POWER |
+                                    HUB_STATUS_CHANGE_OVERCURRENT))
+        {
+            /* At the hub status there is a change */
+            AddressBitMap[0] |= 1;
+        &nb