[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(usbehci)
 add_subdirectory(usbhub)
 add_subdirectory(usbohci)
+add_subdirectory(usbport)
 add_subdirectory(usbstor)
 add_subdirectory(usbuhci)
 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;
+            RHStatus = RH_STATUS_SUCCESS;
+        }
+
+        if (RHStatus == RH_STATUS_SUCCESS)
+        {
+            /* Done */
+            Urb->UrbControlTransfer.TransferBufferLength = TransferLength;
+            return RH_STATUS_SUCCESS;
+        }
+
+        if (RHStatus == RH_STATUS_NO_CHANGES)
+        {
+            /* No changes. Enable IRQs for miniport root hub */
+            Packet->RH_EnableIrq(FdoExtension->MiniPortExt);
+        }
+
+        return RHStatus;
+    }
+
+    /* Miniport returned an error */ 
+    DPRINT1("USBPORT_RootHubSCE: RH_GetHubStatus failed\n");
+    return RH_STATUS_UNSUCCESSFUL;
+}
+
+VOID
+NTAPI
+USBPORT_RootHubEndpointWorker(IN PUSBPORT_ENDPOINT Endpoint)
+{
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    PUSBPORT_TRANSFER Transfer;
+    RHSTATUS RHStatus;
+    USBD_STATUS USBDStatus;
+    KIRQL OldIrql;
+
+    DPRINT_CORE("USBPORT_RootHubEndpointWorker: Endpoint - %p\n", Endpoint);
+
+    FdoDevice = Endpoint->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+    if (!(FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND))
+    {
+        Packet->CheckController(FdoExtension->MiniPortExt);
+    }
+    KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+
+    KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
+
+    Transfer = CONTAINING_RECORD(Endpoint->TransferList.Flink,
+                                 USBPORT_TRANSFER,
+                                 TransferLink);
+
+    if (IsListEmpty(&Endpoint->TransferList) ||
+        Endpoint->TransferList.Flink == NULL ||
+        !Transfer)
+    {
+        if (Endpoint->StateLast == USBPORT_ENDPOINT_REMOVE)
+        {
+            ExInterlockedInsertTailList(&FdoExtension->EndpointClosedList,
+                                        &Endpoint->CloseLink,
+                                        &FdoExtension->EndpointClosedSpinLock);
+       }
+
+        KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
+
+        USBPORT_FlushCancelList(Endpoint);
+        return;
+    }
+
+    if (Transfer->Flags & (TRANSFER_FLAG_ABORTED | TRANSFER_FLAG_CANCELED))
+    {
+        RemoveEntryList(&Transfer->TransferLink);
+        InsertTailList(&Endpoint->CancelList, &Transfer->TransferLink);
+
+        KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
+        USBPORT_FlushCancelList(Endpoint);
+        return;
+    }
+
+    KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
+
+    if (Endpoint->EndpointProperties.TransferType == USBPORT_TRANSFER_TYPE_CONTROL)
+        RHStatus = USBPORT_RootHubEndpoint0(Transfer);
+    else
+        RHStatus = USBPORT_RootHubSCE(Transfer);
+
+    if (RHStatus != RH_STATUS_NO_CHANGES)
+    {
+        if (RHStatus == RH_STATUS_SUCCESS)
+            USBDStatus = USBD_STATUS_SUCCESS;
+        else
+            USBDStatus = USBD_STATUS_STALL_PID;
+
+        KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
+        USBPORT_QueueDoneTransfer(Transfer, USBDStatus);
+        KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
+
+        USBPORT_FlushCancelList(Endpoint);
+        return;
+    }
+
+    USBPORT_FlushCancelList(Endpoint);
+}
+
+NTSTATUS
+NTAPI
+USBPORT_RootHubCreateDevice(IN PDEVICE_OBJECT FdoDevice,
+                            IN PDEVICE_OBJECT PdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    PUSBPORT_DEVICE_HANDLE DeviceHandle;
+    USBPORT_ROOT_HUB_DATA RootHubData;
+    ULONG NumMaskByte;
+    ULONG DescriptorsLength;
+    PUSBPORT_RH_DESCRIPTORS Descriptors;
+    PUSB_DEVICE_DESCRIPTOR RH_DeviceDescriptor;
+    PUSB_CONFIGURATION_DESCRIPTOR RH_ConfigurationDescriptor;
+    PUSB_INTERFACE_DESCRIPTOR RH_InterfaceDescriptor;
+    PUSB_ENDPOINT_DESCRIPTOR RH_EndPointDescriptor;
+    PUSB_HUB_DESCRIPTOR RH_HubDescriptor;
+    ULONG ix;
+    PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+    NTSTATUS Status;
+
+    DPRINT("USBPORT_RootHubCreateDevice: FdoDevice - %p, PdoDevice - %p\n",
+           FdoDevice,
+           PdoDevice);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    PdoExtension = PdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    DeviceHandle = &PdoExtension->DeviceHandle;
+    USBPORT_AddDeviceHandle(FdoDevice, DeviceHandle);
+
+    InitializeListHead(&DeviceHandle->PipeHandleList);
+
+    DeviceHandle->IsRootHub = TRUE;
+    DeviceHandle->DeviceSpeed = UsbFullSpeed;
+    DeviceHandle->Flags = DEVICE_HANDLE_FLAG_ROOTHUB;
+
+    RtlZeroMemory(&RootHubData, sizeof(RootHubData));
+
+    Packet->RH_GetRootHubData(FdoExtension->MiniPortExt, &RootHubData);
+
+    ASSERT(RootHubData.NumberOfPorts != 0);
+    NumMaskByte = ((RootHubData.NumberOfPorts - 1) >> 3) + 1;
+
+    DescriptorsLength = sizeof(USB_DEVICE_DESCRIPTOR) +
+                        sizeof(USB_CONFIGURATION_DESCRIPTOR) +
+                        sizeof(USB_INTERFACE_DESCRIPTOR) +
+                        sizeof(USB_ENDPOINT_DESCRIPTOR) +
+                        (sizeof(USB_HUB_DESCRIPTOR) + 2 * NumMaskByte);
+
+    Descriptors = ExAllocatePoolWithTag(NonPagedPool,
+                                        DescriptorsLength,
+                                        USB_PORT_TAG);
+
+    if (Descriptors)
+    {
+        RtlZeroMemory(Descriptors, DescriptorsLength);
+
+        PdoExtension->RootHubDescriptors = Descriptors;
+
+        RH_DeviceDescriptor = &PdoExtension->RootHubDescriptors->DeviceDescriptor;
+
+        RH_DeviceDescriptor->bLength = sizeof(USB_DEVICE_DESCRIPTOR);
+        RH_DeviceDescriptor->bDescriptorType = USB_DEVICE_DESCRIPTOR_TYPE;
+        RH_DeviceDescriptor->bcdUSB = 0x100;
+        RH_DeviceDescriptor->bDeviceClass = USB_DEVICE_CLASS_HUB;
+        RH_DeviceDescriptor->bDeviceSubClass = 0x01;
+        RH_DeviceDescriptor->bDeviceProtocol = 0x00;
+        RH_DeviceDescriptor->bMaxPacketSize0 = 0x08;
+        RH_DeviceDescriptor->idVendor = FdoExtension->VendorID;
+        RH_DeviceDescriptor->idProduct = FdoExtension->DeviceID;
+        RH_DeviceDescriptor->bcdDevice = FdoExtension->RevisionID;
+        RH_DeviceDescriptor->iManufacturer = 0x00;
+        RH_DeviceDescriptor->iProduct = 0x00;
+        RH_DeviceDescriptor->iSerialNumber = 0x00;
+        RH_DeviceDescriptor->bNumConfigurations = 0x01;
+
+        RH_ConfigurationDescriptor = &PdoExtension->RootHubDescriptors->ConfigDescriptor;
+
+        RH_ConfigurationDescriptor->bLength = sizeof(USB_CONFIGURATION_DESCRIPTOR);
+        RH_ConfigurationDescriptor->bDescriptorType = USB_CONFIGURATION_DESCRIPTOR_TYPE;
+
+        RH_ConfigurationDescriptor->wTotalLength = sizeof(USB_CONFIGURATION_DESCRIPTOR) +
+                                                   sizeof(USB_INTERFACE_DESCRIPTOR) +
+                                                   sizeof(USB_ENDPOINT_DESCRIPTOR);
+
+        RH_ConfigurationDescriptor->bNumInterfaces = 0x01;
+        RH_ConfigurationDescriptor->bConfigurationValue = 0x01;
+        RH_ConfigurationDescriptor->iConfiguration = 0x00;
+        RH_ConfigurationDescriptor->bmAttributes = USB_CONFIG_SELF_POWERED;
+        RH_ConfigurationDescriptor->MaxPower = 0x00;
+
+        RH_InterfaceDescriptor = &PdoExtension->RootHubDescriptors->InterfaceDescriptor;
+
+        RH_InterfaceDescriptor->bLength = sizeof(USB_INTERFACE_DESCRIPTOR);
+        RH_InterfaceDescriptor->bDescriptorType = USB_INTERFACE_DESCRIPTOR_TYPE;
+        RH_InterfaceDescriptor->bInterfaceNumber = 0x00;
+        RH_InterfaceDescriptor->bAlternateSetting = 0x00;
+        RH_InterfaceDescriptor->bNumEndpoints = 0x01;
+        RH_InterfaceDescriptor->bInterfaceClass = USB_DEVICE_CLASS_HUB;
+        RH_InterfaceDescriptor->bInterfaceSubClass = 0x01;
+        RH_InterfaceDescriptor->bInterfaceProtocol = 0x00;
+        RH_InterfaceDescriptor->iInterface = 0x00;
+
+        RH_EndPointDescriptor = &PdoExtension->RootHubDescriptors->EndPointDescriptor;
+
+        RH_EndPointDescriptor->bLength = sizeof(USB_ENDPOINT_DESCRIPTOR);
+        RH_EndPointDescriptor->bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE;
+        RH_EndPointDescriptor->bEndpointAddress = 0x81;
+        RH_EndPointDescriptor->bmAttributes = USB_ENDPOINT_TYPE_INTERRUPT; // SCE endpoint
+        RH_EndPointDescriptor->wMaxPacketSize = 0x0008;
+        RH_EndPointDescriptor->bInterval = 0x0C; // 12 msec
+
+        RH_HubDescriptor = &PdoExtension->RootHubDescriptors->Descriptor;
+
+        RH_HubDescriptor->bDescriptorLength = sizeof(USB_HUB_DESCRIPTOR) + 2 * NumMaskByte;
+        RH_HubDescriptor->bDescriptorType = 0x29; // USB_20_HUB_DESCRIPTOR_TYPE - need add in .h file
+        RH_HubDescriptor->bNumberOfPorts = RootHubData.NumberOfPorts;
+        RH_HubDescriptor->wHubCharacteristics = RootHubData.HubCharacteristics;
+        RH_HubDescriptor->bPowerOnToPowerGood = RootHubData.PowerOnToPowerGood;
+        RH_HubDescriptor->bHubControlCurrent = RootHubData.HubControlCurrent;
+
+        for (ix = 0; ix < NumMaskByte; ix += 2)
+        {
+            RH_HubDescriptor->bRemoveAndPowerMask[ix] = 0;
+            RH_HubDescriptor->bRemoveAndPowerMask[ix + 1] = -1;
+        }
+
+        EndpointDescriptor = &DeviceHandle->PipeHandle.EndpointDescriptor;
+
+        EndpointDescriptor->bLength = sizeof(USB_ENDPOINT_DESCRIPTOR);
+        EndpointDescriptor->bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE;
+        EndpointDescriptor->bEndpointAddress = 0x00;
+        EndpointDescriptor->bmAttributes = USB_ENDPOINT_TYPE_CONTROL;
+        EndpointDescriptor->wMaxPacketSize = 0x0040;
+        EndpointDescriptor->bInterval = 0x00;
+
+        Status = USBPORT_OpenPipe(FdoDevice,
+                                  DeviceHandle,
+                                  &DeviceHandle->PipeHandle,
+                                  NULL);
+    }
+    else
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    return Status;
+}
+
+ULONG
+NTAPI
+USBPORT_InvalidateRootHub(PVOID Context)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PDEVICE_OBJECT FdoDevice;
+    PDEVICE_OBJECT PdoDevice;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PUSBPORT_ENDPOINT Endpoint = NULL;
+
+    DPRINT("USBPORT_InvalidateRootHub ... \n");
+
+    FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)Context -
+                                               sizeof(USBPORT_DEVICE_EXTENSION));
+
+    FdoDevice = FdoExtension->CommonExtension.SelfDevice;
+
+    if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND && 
+         FdoExtension->Flags & USBPORT_FLAG_HC_WAKE_SUPPORT &&
+         FdoExtension->MiniPortFlags & USBPORT_MPFLAG_SUSPENDED &&
+         FdoExtension->TimerFlags & USBPORT_TMFLAG_WAKE)
+    {
+        USBPORT_HcQueueWakeDpc(FdoDevice);
+        return 0;
+    }
+    
+    FdoExtension->MiniPortInterface->Packet.RH_DisableIrq(FdoExtension->MiniPortExt);
+
+    PdoDevice = FdoExtension->RootHubPdo;
+
+    if (PdoDevice)
+    {
+        PdoExtension = PdoDevice->DeviceExtension;
+        Endpoint = PdoExtension->Endpoint;
+
+        if (Endpoint)
+        {
+            USBPORT_InvalidateEndpointHandler(FdoDevice,
+                                              PdoExtension->Endpoint,
+                                              INVALIDATE_ENDPOINT_WORKER_THREAD);
+        }
+    }
+
+    return 0;
+}
+
+VOID
+NTAPI
+USBPORT_RootHubPowerAndChirpAllCcPorts(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    USBPORT_ROOT_HUB_DATA RootHubData;
+    ULONG Port;
+    PDEVICE_RELATIONS CompanionControllersList;
+    PUSBPORT_DEVICE_EXTENSION CompanionFdoExtension;
+    PUSBPORT_REGISTRATION_PACKET CompanionPacket;
+    ULONG CompanionPorts;
+    ULONG NumController;
+    PDEVICE_OBJECT * Entry;
+    ULONG NumPorts;
+
+    DPRINT("USBPORT_RootHub_PowerAndChirpAllCcPorts: FdoDevice - %p\n",
+           FdoDevice);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    RtlZeroMemory(&RootHubData, sizeof(RootHubData));
+
+    Packet->RH_GetRootHubData(FdoExtension->MiniPortExt,
+                              &RootHubData);
+
+    NumPorts = RootHubData.NumberOfPorts;
+
+    for (Port = 1; Port <= NumPorts; ++Port)
+    {
+        Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt, Port);
+    }
+
+    USBPORT_Wait(FdoDevice, 10);
+
+    CompanionControllersList = USBPORT_FindCompanionControllers(FdoDevice,
+                                                                FALSE,
+                                                                TRUE);
+
+    if (CompanionControllersList)
+    {
+        Entry = &CompanionControllersList->Objects[0];
+
+        for (NumController = 0;
+             NumController < CompanionControllersList->Count;
+             NumController++)
+        {
+            CompanionPacket = &FdoExtension->MiniPortInterface->Packet;
+
+            CompanionFdoExtension = (*Entry)->DeviceExtension;
+
+            CompanionPacket->RH_GetRootHubData(CompanionFdoExtension->MiniPortExt,
+                                               &RootHubData);
+
+            CompanionPorts = RootHubData.NumberOfPorts;
+
+            for (Port = 1; Port <= CompanionPorts; ++Port)
+            {
+                CompanionPacket->RH_SetFeaturePortPower(CompanionFdoExtension->MiniPortExt,
+                                                        Port);
+            }
+
+            ++Entry;
+        }
+
+        ExFreePoolWithTag(CompanionControllersList, USB_PORT_TAG);
+    }
+
+    USBPORT_Wait(FdoDevice, 100);
+
+    for (Port = 1; Port <= NumPorts; ++Port)
+    {
+        if (FdoExtension->MiniPortInterface->Version < 200)
+        {
+            break;
+        }
+
+        InterlockedIncrement((PLONG)&FdoExtension->ChirpRootPortLock);
+        Packet->RH_ChirpRootPort(FdoExtension->MiniPortExt, Port);
+        InterlockedDecrement((PLONG)&FdoExtension->ChirpRootPortLock);
+    }
+}
diff --git a/reactos/drivers/usb/usbport/urb.c b/reactos/drivers/usb/usbport/urb.c
new file mode 100644 (file)
index 0000000..5067f96
--- /dev/null
@@ -0,0 +1,1061 @@
+#include "usbport.h"
+
+#define NDEBUG
+#include <debug.h>
+
+#define NDEBUG_USBPORT_URB
+#include "usbdebug.h"
+
+NTSTATUS
+NTAPI
+USBPORT_HandleGetConfiguration(IN PURB Urb)
+{
+    PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
+
+    DPRINT_URB("USBPORT_HandleGetConfiguration: Urb - %p\n", Urb);
+
+    SetupPacket = (PUSB_DEFAULT_PIPE_SETUP_PACKET)
+                   &Urb->UrbControlGetConfigurationRequest.Reserved1;
+
+    SetupPacket->bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
+    SetupPacket->bRequest = USB_REQUEST_GET_CONFIGURATION;
+    SetupPacket->wValue.W = 0;
+    SetupPacket->wIndex.W = 0;
+    SetupPacket->wLength = Urb->UrbControlGetConfigurationRequest.TransferBufferLength;
+
+    Urb->UrbControlGetConfigurationRequest.Reserved0 |= USBD_TRANSFER_DIRECTION_IN; // 1;
+    Urb->UrbControlGetConfigurationRequest.Reserved0 |= USBD_SHORT_TRANSFER_OK; // 2
+
+    USBPORT_DumpingSetupPacket(SetupPacket);
+
+    USBPORT_QueueTransferUrb(Urb);
+
+    return STATUS_PENDING;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_HandleGetCurrentFrame(IN PDEVICE_OBJECT FdoDevice,
+                              IN PIRP Irp,
+                              IN PURB Urb)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    ULONG FrameNumber;
+    KIRQL OldIrql;
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+    FrameNumber = Packet->Get32BitFrameNumber(FdoExtension->MiniPortExt);
+    KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+
+    Urb->UrbGetCurrentFrameNumber.FrameNumber = FrameNumber;
+
+    DPRINT_URB("USBPORT_HandleGetCurrentFrame: FrameNumber - %p\n",
+               FrameNumber);
+
+    return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_SUCCESS);
+}
+
+NTSTATUS
+NTAPI
+USBPORT_AbortPipe(IN PDEVICE_OBJECT FdoDevice,
+                  IN PIRP Irp,
+                  IN PURB Urb)
+{
+    PUSBPORT_ENDPOINT Endpoint;
+    PUSBPORT_PIPE_HANDLE PipeHandle;
+    PUSBPORT_DEVICE_HANDLE DeviceHandle;
+    NTSTATUS Status;
+
+    DPRINT_URB("USBPORT_AbortPipe: ... \n");
+
+    PipeHandle = Urb->UrbPipeRequest.PipeHandle;
+    DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
+
+    if (USBPORT_ValidatePipeHandle(DeviceHandle, PipeHandle))
+    {
+        if (!(PipeHandle->Flags & PIPE_HANDLE_FLAG_NULL_PACKET_SIZE))
+        {
+            Endpoint = PipeHandle->Endpoint;
+
+            Status = STATUS_PENDING;
+
+            Irp->IoStatus.Status = Status;
+            IoMarkIrpPending(Irp);
+
+            USBPORT_AbortEndpoint(FdoDevice, Endpoint, Irp);
+
+            return Status;
+        }
+
+        Status = USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_SUCCESS);
+    }
+    else
+    {
+        Status = USBPORT_USBDStatusToNtStatus(Urb,
+                                              USBD_STATUS_INVALID_PIPE_HANDLE);
+    }
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_ResetPipe(IN PDEVICE_OBJECT FdoDevice,
+                  IN PIRP Irp,
+                  IN PURB Urb)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    PUSBPORT_PIPE_HANDLE PipeHandle;
+    PUSBPORT_ENDPOINT Endpoint;
+    NTSTATUS Status;
+
+    DPRINT_URB("USBPORT_ResetPipe: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    PipeHandle = Urb->UrbPipeRequest.PipeHandle;
+
+    if (!USBPORT_ValidatePipeHandle((PUSBPORT_DEVICE_HANDLE)Urb->UrbHeader.UsbdDeviceHandle,
+                                    PipeHandle))
+    {
+        return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_INVALID_PIPE_HANDLE);
+    }
+
+    Endpoint = PipeHandle->Endpoint;
+
+    KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
+
+    if (IsListEmpty(&Endpoint->TransferList))
+    {
+        if (Urb->UrbHeader.UsbdFlags & USBD_FLAG_NOT_ISO_TRANSFER)
+        {
+            KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
+
+            Packet->SetEndpointDataToggle(FdoExtension->MiniPortExt,
+                                          Endpoint + 1,
+                                          0);
+
+            KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
+        }
+
+        Status = USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_SUCCESS);
+    }
+    else
+    {
+        Status = USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_ERROR_BUSY);
+    }
+
+    Endpoint->Flags |= ENDPOINT_FLAG_QUEUENE_EMPTY;
+
+    KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
+
+    Packet->SetEndpointStatus(FdoExtension->MiniPortExt,
+                              Endpoint + 1,
+                              USBPORT_ENDPOINT_RUN);
+
+    KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
+    KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_ClearStall(IN PDEVICE_OBJECT FdoDevice,
+                   IN PIRP Irp,
+                   IN PURB Urb)
+{
+    PUSBPORT_DEVICE_HANDLE DeviceHandle;
+    PUSBPORT_PIPE_HANDLE PipeHandle;
+    USBD_STATUS USBDStatus;
+    PUSBPORT_ENDPOINT Endpoint;
+    NTSTATUS Status;
+    USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
+
+    DPRINT_URB("USBPORT_ClearStall: ... \n");
+
+    PipeHandle = Urb->UrbPipeRequest.PipeHandle;
+    DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
+
+    if (!USBPORT_ValidatePipeHandle(DeviceHandle, PipeHandle))
+    {
+        return USBPORT_USBDStatusToNtStatus(Urb,
+                                            USBD_STATUS_INVALID_PIPE_HANDLE);
+    }
+
+    Endpoint = PipeHandle->Endpoint;
+
+    RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+
+    SetupPacket.bmRequestType.Recipient = BMREQUEST_TO_ENDPOINT;
+    SetupPacket.bRequest = USB_REQUEST_CLEAR_FEATURE;
+    SetupPacket.wValue.W = 0;
+    SetupPacket.wIndex.W = Endpoint->EndpointProperties.EndpointAddress;
+    SetupPacket.wLength = 0;
+
+    USBPORT_SendSetupPacket(DeviceHandle,
+                            FdoDevice,
+                            &SetupPacket,
+                            NULL,
+                            0,
+                            NULL,
+                            &USBDStatus);
+
+    Status = USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_SyncResetPipeAndClearStall(IN PDEVICE_OBJECT FdoDevice,
+                                   IN PIRP Irp,
+                                   IN PURB Urb)
+{
+    PUSBPORT_DEVICE_HANDLE DeviceHandle;
+    PUSBPORT_PIPE_HANDLE PipeHandle;
+    PUSBPORT_ENDPOINT Endpoint;
+    ULONG EndpointState;
+    NTSTATUS Status;
+
+    DPRINT_URB("USBPORT_SyncResetPipeAndClearStall: ... \n");
+
+    ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
+    ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
+    ASSERT(Urb->UrbPipeRequest.PipeHandle);
+
+    DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
+    PipeHandle = Urb->UrbPipeRequest.PipeHandle;
+
+    if (!USBPORT_ValidatePipeHandle(DeviceHandle, PipeHandle))
+    {
+        return USBPORT_USBDStatusToNtStatus(Urb,
+                                            USBD_STATUS_INVALID_PIPE_HANDLE);
+    }
+
+    if (PipeHandle->Flags & PIPE_HANDLE_FLAG_NULL_PACKET_SIZE)
+    {
+        return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_SUCCESS);
+    }
+
+    Endpoint = PipeHandle->Endpoint;
+    InterlockedIncrement(&DeviceHandle->DeviceHandleLock);
+
+    if (Endpoint->EndpointProperties.TransferType != USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+    {
+        Urb->UrbHeader.UsbdFlags |= USBD_FLAG_NOT_ISO_TRANSFER;
+        Status = USBPORT_ClearStall(FdoDevice, Irp, Urb);
+    }
+    else
+    {
+        Status = USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_SUCCESS);
+    }
+
+    if (NT_SUCCESS(Status))
+    {
+        Status = USBPORT_ResetPipe(FdoDevice, Irp, Urb);
+
+        if (Endpoint->EndpointProperties.TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+        {
+            while (TRUE)
+            {
+                KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
+                                  &Endpoint->EndpointOldIrql);
+
+                EndpointState = USBPORT_GetEndpointState(Endpoint);
+
+                if (EndpointState == USBPORT_ENDPOINT_PAUSED &&
+                    IsListEmpty(&Endpoint->TransferList))
+                {
+                    USBPORT_SetEndpointState(Endpoint,
+                                             USBPORT_ENDPOINT_ACTIVE);
+                }
+
+                KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
+                                  Endpoint->EndpointOldIrql);
+
+                if (EndpointState == USBPORT_ENDPOINT_ACTIVE)
+                {
+                    break;
+                }
+
+                USBPORT_Wait(FdoDevice, 1);
+            }
+        }
+    }
+
+    InterlockedDecrement(&DeviceHandle->DeviceHandleLock);
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_HandleSetOrClearFeature(IN PURB Urb)
+{
+    PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
+
+    DPRINT_URB("USBPORT_HandleSetOrClearFeature: Urb - %p\n", Urb);
+
+    SetupPacket = (PUSB_DEFAULT_PIPE_SETUP_PACKET)
+                  &Urb->UrbControlFeatureRequest.Reserved0;
+
+    SetupPacket->wLength = 0;
+    Urb->UrbControlFeatureRequest.Reserved3 = 0; // TransferBufferLength
+
+    SetupPacket->bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
+
+    switch (Urb->UrbHeader.Function)
+    {
+        case URB_FUNCTION_SET_FEATURE_TO_DEVICE:
+            DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n");
+            SetupPacket->bRequest = USB_REQUEST_SET_FEATURE;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_DEVICE;
+            break;
+
+        case URB_FUNCTION_SET_FEATURE_TO_INTERFACE:
+            DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE\n");
+            SetupPacket->bRequest = USB_REQUEST_SET_FEATURE;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
+            break;
+
+        case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT:
+            DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE\n");
+            SetupPacket->bRequest = USB_REQUEST_SET_FEATURE;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_ENDPOINT;
+            break;
+
+        case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE:
+            DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT\n");
+            SetupPacket->bRequest = USB_REQUEST_CLEAR_FEATURE;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_DEVICE;
+            break;
+
+        case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE:
+            DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT\n");
+            SetupPacket->bRequest = USB_REQUEST_CLEAR_FEATURE;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
+            break;
+
+        case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT:
+            DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE\n");
+            SetupPacket->bRequest = USB_REQUEST_CLEAR_FEATURE;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_ENDPOINT;
+            break;
+
+        case URB_FUNCTION_CLEAR_FEATURE_TO_OTHER:
+            DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE\n");
+            SetupPacket->bRequest = USB_REQUEST_CLEAR_FEATURE;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_OTHER;
+            break;
+
+        case URB_FUNCTION_SET_FEATURE_TO_OTHER:
+            DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE\n");
+            SetupPacket->bRequest = USB_REQUEST_SET_FEATURE;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_OTHER;
+            break;
+    }
+
+    Urb->UrbControlFeatureRequest.Reserved2 &= ~USBD_TRANSFER_DIRECTION_IN;
+    Urb->UrbControlFeatureRequest.Reserved2 |= USBD_SHORT_TRANSFER_OK;
+
+    USBPORT_DumpingSetupPacket(SetupPacket);
+
+    USBPORT_QueueTransferUrb(Urb);
+
+    return STATUS_PENDING;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_HandleDataTransfers(IN PURB Urb)
+{
+    PUSBPORT_ENDPOINT Endpoint;
+
+    DPRINT_URB("USBPORT_HandleDataTransfers: Urb - %p\n", Urb);
+
+    Endpoint = ((PUSBPORT_PIPE_HANDLE)
+                (Urb->UrbBulkOrInterruptTransfer.PipeHandle))->Endpoint;
+
+    if (Endpoint->EndpointProperties.TransferType != USBPORT_TRANSFER_TYPE_CONTROL)
+    {
+        if (Endpoint->EndpointProperties.Direction)
+        {
+            Urb->UrbBulkOrInterruptTransfer.TransferFlags |= USBD_TRANSFER_DIRECTION_IN;
+        }
+        else
+        {
+            Urb->UrbBulkOrInterruptTransfer.TransferFlags &= ~USBD_TRANSFER_DIRECTION_IN;
+        }
+    }
+
+    USBPORT_QueueTransferUrb(Urb);
+
+    return STATUS_PENDING;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_HandleGetStatus(IN PIRP Irp,
+                        IN PURB Urb)
+{
+    PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
+    NTSTATUS Status;
+
+    SetupPacket = (PUSB_DEFAULT_PIPE_SETUP_PACKET)
+                   &Urb->UrbControlDescriptorRequest.Reserved1;
+
+    SetupPacket->bmRequestType.B = 0;
+    SetupPacket->bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
+    SetupPacket->bRequest = USB_REQUEST_GET_STATUS;
+    SetupPacket->wLength = Urb->UrbControlDescriptorRequest.TransferBufferLength;
+    SetupPacket->wValue.W = 0;
+
+    switch (Urb->UrbHeader.Function)
+    {
+        case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
+            DPRINT_URB("USBPORT_HandleGetStatus: URB_FUNCTION_GET_STATUS_FROM_DEVICE\n");
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_DEVICE;
+            break;
+
+        case URB_FUNCTION_GET_STATUS_FROM_INTERFACE:
+            DPRINT_URB("USBPORT_HandleGetStatus: URB_FUNCTION_GET_STATUS_FROM_INTERFACE\n");
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
+            break;
+
+        case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:
+            DPRINT_URB("USBPORT_HandleGetStatus: URB_FUNCTION_GET_STATUS_FROM_ENDPOINT\n");
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_ENDPOINT;
+            break;
+
+        case URB_FUNCTION_GET_STATUS_FROM_OTHER:
+            DPRINT_URB("USBPORT_HandleGetStatus: URB_FUNCTION_GET_STATUS_FROM_OTHER\n");
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_OTHER;
+            break;
+    }
+
+    if (SetupPacket->wLength == 2)
+    {
+        Urb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
+
+        if (SetupPacket->bmRequestType.Dir)
+            Urb->UrbControlTransfer.TransferFlags |= USBD_TRANSFER_DIRECTION_IN;
+        else
+            Urb->UrbControlTransfer.TransferFlags &= ~USBD_TRANSFER_DIRECTION_IN;
+
+        //USBPORT_DumpingSetupPacket(SetupPacket);
+
+        USBPORT_QueueTransferUrb(Urb);
+
+        Status = STATUS_PENDING;
+    }
+    else
+    {
+        Status = USBPORT_USBDStatusToNtStatus(Urb,
+                                              USBD_STATUS_INVALID_PARAMETER);
+
+        DPRINT1("USBPORT_HandleGetStatus: Bad wLength\n");
+        USBPORT_DumpingSetupPacket(SetupPacket);
+    }
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_HandleVendorOrClass(IN PIRP Irp,
+                            IN PURB Urb)
+{
+    PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
+
+    /*
+        Specifies a value, from 4 to 31 inclusive,
+        that becomes part of the request type code in the USB-defined setup packet.
+        This value is defined by USB for a class request or the vendor for a vendor request.
+    */
+
+    SetupPacket = (PUSB_DEFAULT_PIPE_SETUP_PACKET)
+                   &Urb->UrbControlDescriptorRequest.Reserved1;
+
+    SetupPacket->bmRequestType.Dir = USBD_TRANSFER_DIRECTION_FLAG
+                                     (Urb->UrbControlTransfer.TransferFlags);
+
+    SetupPacket->wLength = Urb->UrbControlDescriptorRequest.TransferBufferLength;
+
+    Urb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
+
+    switch (Urb->UrbHeader.Function)
+    {
+        case URB_FUNCTION_VENDOR_DEVICE:
+            DPRINT_URB("USBPORT_HandleVendorOrClass: URB_FUNCTION_VENDOR_DEVICE\n");
+            SetupPacket->bmRequestType.Type = BMREQUEST_VENDOR;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_DEVICE;
+            break;
+
+        case URB_FUNCTION_VENDOR_INTERFACE:
+            DPRINT_URB("USBPORT_HandleVendorOrClass: URB_FUNCTION_VENDOR_INTERFACE\n");
+            SetupPacket->bmRequestType.Type = BMREQUEST_VENDOR;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
+            break;
+
+        case URB_FUNCTION_VENDOR_ENDPOINT:
+            DPRINT_URB("USBPORT_HandleVendorOrClass: URB_FUNCTION_VENDOR_ENDPOINT\n");
+            SetupPacket->bmRequestType.Type = BMREQUEST_VENDOR;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_ENDPOINT;
+            break;
+
+        case URB_FUNCTION_CLASS_DEVICE:
+            DPRINT_URB("USBPORT_HandleVendorOrClass: URB_FUNCTION_CLASS_DEVICE\n");
+            SetupPacket->bmRequestType.Type = BMREQUEST_CLASS;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_DEVICE;
+            break;
+
+        case URB_FUNCTION_CLASS_INTERFACE:
+            DPRINT_URB("USBPORT_HandleVendorOrClass: URB_FUNCTION_CLASS_INTERFACE\n");
+            SetupPacket->bmRequestType.Type = BMREQUEST_CLASS;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
+            break;
+
+        case URB_FUNCTION_CLASS_ENDPOINT:
+            DPRINT_URB("USBPORT_HandleVendorOrClass: URB_FUNCTION_CLASS_ENDPOINT\n");
+            SetupPacket->bmRequestType.Type = BMREQUEST_CLASS;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_ENDPOINT;
+            break;
+
+        case URB_FUNCTION_CLASS_OTHER:
+            DPRINT_URB("USBPORT_HandleVendorOrClass: URB_FUNCTION_CLASS_OTHER\n");
+            SetupPacket->bmRequestType.Type = BMREQUEST_CLASS;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_OTHER;
+            break;
+
+        case URB_FUNCTION_VENDOR_OTHER:
+            DPRINT_URB("USBPORT_HandleVendorOrClass: URB_FUNCTION_VENDOR_OTHER\n");
+            SetupPacket->bmRequestType.Type = BMREQUEST_VENDOR;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_OTHER;
+            break;
+    }
+
+    USBPORT_DumpingSetupPacket(SetupPacket);
+
+    USBPORT_QueueTransferUrb(Urb);
+
+    return STATUS_PENDING;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_HandleGetSetDescriptor(IN PIRP Irp,
+                               IN PURB Urb)
+{
+    PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
+
+    SetupPacket = (PUSB_DEFAULT_PIPE_SETUP_PACKET)
+                   &Urb->UrbControlDescriptorRequest.Reserved1;
+
+    SetupPacket->wLength = Urb->UrbControlDescriptorRequest.TransferBufferLength;
+    SetupPacket->bmRequestType.B = 0; // Clear bmRequestType
+    SetupPacket->bmRequestType.Type = BMREQUEST_STANDARD;
+
+    switch (Urb->UrbHeader.Function)
+    {
+        case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
+            DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n");
+            SetupPacket->bRequest = USB_REQUEST_GET_DESCRIPTOR;
+            SetupPacket->bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_DEVICE;
+            break;
+
+        case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE:
+            DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE\n");
+            SetupPacket->bRequest = USB_REQUEST_SET_DESCRIPTOR;
+            SetupPacket->bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_DEVICE;
+            break;
+
+        case URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT:
+            DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT\n");
+            SetupPacket->bRequest = USB_REQUEST_GET_DESCRIPTOR;
+            SetupPacket->bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_ENDPOINT;
+            break;
+
+        case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT:
+            DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT\n");
+            SetupPacket->bRequest = USB_REQUEST_SET_DESCRIPTOR;
+            SetupPacket->bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_ENDPOINT;
+            break;
+
+        case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
+            DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE\n");
+            SetupPacket->bRequest = USB_REQUEST_GET_DESCRIPTOR;
+            SetupPacket->bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
+            break;
+
+        case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE:
+            DPRINT_URB("USBPORT_HandleGetSetDescriptor: URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE\n");
+            SetupPacket->bRequest = USB_REQUEST_SET_DESCRIPTOR;
+            SetupPacket->bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
+            SetupPacket->bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
+            break;
+    }
+
+    Urb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
+
+    if (SetupPacket->bmRequestType.Dir)
+        Urb->UrbControlTransfer.TransferFlags |= USBD_TRANSFER_DIRECTION_IN;
+    else
+        Urb->UrbControlTransfer.TransferFlags &= ~USBD_TRANSFER_DIRECTION_IN;
+
+    USBPORT_DumpingSetupPacket(SetupPacket);
+
+    USBPORT_QueueTransferUrb(Urb);
+
+    return STATUS_PENDING;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_ValidateTransferParametersURB(IN PURB Urb)
+{
+    struct _URB_CONTROL_TRANSFER *UrbRequest;
+    PMDL Mdl;
+
+    DPRINT_URB("USBPORT_ValidateTransferParametersURB: Urb - %p\n", Urb);
+
+    UrbRequest = &Urb->UrbControlTransfer;
+
+    if (UrbRequest->TransferBuffer == NULL &&
+        UrbRequest->TransferBufferMDL == NULL &&
+        UrbRequest->TransferBufferLength > 0)
+    {
+        DPRINT1("USBPORT_ValidateTransferParametersURB: Not valid parameter\n");
+        USBPORT_DumpingURB(Urb);
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if ((UrbRequest->TransferBuffer != NULL) &&
+        (UrbRequest->TransferBufferMDL != NULL) &&
+        UrbRequest->TransferBufferLength == 0)
+    {
+        DPRINT1("USBPORT_ValidateTransferParametersURB: Not valid parameter\n");
+        USBPORT_DumpingURB(Urb);
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if (UrbRequest->TransferBuffer != NULL &&
+        UrbRequest->TransferBufferMDL == NULL &&
+        UrbRequest->TransferBufferLength != 0)
+    {
+        DPRINT_URB("USBPORT_ValidateTransferParametersURB: TransferBuffer - %p, TransferBufferLength - %x\n",
+                   UrbRequest->TransferBuffer,
+                   UrbRequest->TransferBufferLength);
+
+        Mdl = IoAllocateMdl(UrbRequest->TransferBuffer,
+                            UrbRequest->TransferBufferLength,
+                            FALSE,
+                            FALSE,
+                            NULL);
+
+        if (!Mdl)
+        {
+            DPRINT1("USBPORT_ValidateTransferParametersURB: Not allocated Mdl\n");
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
+
+        MmBuildMdlForNonPagedPool(Mdl);
+
+        UrbRequest->TransferBufferMDL = Mdl;
+        Urb->UrbHeader.UsbdFlags |= USBD_FLAG_ALLOCATED_MDL;
+
+        DPRINT_URB("USBPORT_ValidateTransferParametersURB: Mdl - %p\n", Mdl);
+    }
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_ValidateURB(IN PDEVICE_OBJECT FdoDevice,
+                    IN PIRP Irp,
+                    IN PURB Urb,
+                    IN BOOLEAN IsControlTransfer,
+                    IN BOOLEAN IsNullTransfer)
+{
+    struct _URB_CONTROL_TRANSFER *UrbRequest;
+    PUSBPORT_DEVICE_HANDLE DeviceHandle;
+    NTSTATUS Status;
+    USBD_STATUS USBDStatus;
+
+    UrbRequest = &Urb->UrbControlTransfer;
+
+    if (UrbRequest->UrbLink)
+    {
+        Status = USBPORT_USBDStatusToNtStatus(Urb,
+                                              USBD_STATUS_INVALID_PARAMETER);
+
+        DPRINT1("USBPORT_ValidateURB: Not valid parameter\n");
+
+        USBPORT_DumpingURB(Urb);
+        return Status;
+    }
+
+    DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
+
+    if (IsControlTransfer)
+    {
+        UrbRequest->TransferFlags |= USBD_DEFAULT_PIPE_TRANSFER;
+        UrbRequest->PipeHandle = &DeviceHandle->PipeHandle;
+    }
+
+    if (UrbRequest->TransferFlags & USBD_DEFAULT_PIPE_TRANSFER)
+    {
+        if (UrbRequest->TransferBufferLength > 0x1000)
+        {
+            Status = USBPORT_USBDStatusToNtStatus(Urb,
+                                                  USBD_STATUS_INVALID_PARAMETER);
+
+            DPRINT1("USBPORT_ValidateURB: Not valid parameter\n");
+
+            USBPORT_DumpingURB(Urb);
+            return Status;
+        }
+
+        if (Urb->UrbHeader.Function == URB_FUNCTION_CONTROL_TRANSFER)
+        {
+            UrbRequest->PipeHandle = &DeviceHandle->PipeHandle;
+        }
+    }
+
+    if (!USBPORT_ValidatePipeHandle(DeviceHandle, UrbRequest->PipeHandle))
+    {
+        Status = USBPORT_USBDStatusToNtStatus(Urb,
+                                              USBD_STATUS_INVALID_PIPE_HANDLE);
+
+        DPRINT1("USBPORT_ValidateURB: Not valid pipe handle\n");
+
+        USBPORT_DumpingURB(Urb);
+        return Status;
+    }
+
+    UrbRequest->hca.Reserved8[0] = NULL; // Transfer
+
+    if (IsNullTransfer)
+    {
+        UrbRequest->TransferBuffer = 0;
+        UrbRequest->TransferBufferMDL = NULL;
+        UrbRequest->TransferBufferLength = 0;
+    }
+    else
+    {
+        Status = USBPORT_ValidateTransferParametersURB(Urb);
+
+        if (!NT_SUCCESS(Status))
+        {
+            return Status;
+        }
+    }
+
+    USBDStatus = USBPORT_AllocateTransfer(FdoDevice,
+                                          Urb,
+                                          DeviceHandle,
+                                          Irp,
+                                          NULL);
+
+    Status = USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
+
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("USBPORT_ValidateURB: Not allocated transfer\n");
+    }
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_HandleSubmitURB(IN PDEVICE_OBJECT PdoDevice,
+                        IN PIRP Irp,
+                        IN PURB Urb)
+{
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    USHORT Function;
+    PUSBPORT_DEVICE_HANDLE DeviceHandle;
+    NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
+
+    ASSERT(Urb);
+
+    PdoExtension = PdoDevice->DeviceExtension;
+    FdoDevice = PdoExtension->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
+    Urb->UrbHeader.UsbdFlags = 0;
+
+    Function = Urb->UrbHeader.Function;
+
+    if (Function > URB_FUNCTION_MAX)
+    {
+        Status = USBPORT_USBDStatusToNtStatus(Urb,
+                                              USBD_STATUS_INVALID_URB_FUNCTION);
+
+        DPRINT1("USBPORT_HandleSubmitURB: Unknown URB function - %x !!!\n",
+               Function);
+
+        return Status;
+    }
+
+    if (FdoExtension->TimerFlags & USBPORT_TMFLAG_RH_SUSPENDED)
+    {
+        DPRINT1("USBPORT_HandleSubmitURB: Bad Request\n");
+
+        USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_DEVICE_GONE);
+
+        Irp->IoStatus.Status = STATUS_PENDING;
+        IoMarkIrpPending(Irp);
+        IoCsqInsertIrp(&FdoExtension->BadRequestIoCsq, Irp, NULL);
+
+        return STATUS_PENDING;
+    }
+
+    DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
+
+    if (!DeviceHandle)
+    {
+        DeviceHandle = &PdoExtension->DeviceHandle;
+        Urb->UrbHeader.UsbdDeviceHandle = DeviceHandle;
+    }
+
+    if (!USBPORT_ValidateDeviceHandle(PdoExtension->FdoDevice,
+                                      DeviceHandle))
+    {
+        DPRINT1("USBPORT_HandleSubmitURB: Not valid device handle\n");
+
+        Irp->IoStatus.Status = STATUS_PENDING;
+        IoMarkIrpPending(Irp);
+        IoCsqInsertIrp(&FdoExtension->BadRequestIoCsq, Irp, NULL);
+
+        return STATUS_PENDING;
+    }
+
+    InterlockedIncrement(&DeviceHandle->DeviceHandleLock);
+
+    DPRINT_URB("USBPORT_HandleSubmitURB: Function - 0x%02X, DeviceHandle - %p\n",
+               Function,
+               Urb->UrbHeader.UsbdDeviceHandle);
+
+    switch (Function)
+    {
+        case URB_FUNCTION_ISOCH_TRANSFER:
+            DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_ISOCH_TRANSFER UNIMPLEMENTED. FIXME. \n");
+            break;
+
+        case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
+        case URB_FUNCTION_CONTROL_TRANSFER:
+            Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, FALSE, FALSE);
+
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n");
+                break;
+            }
+
+            Status = USBPORT_HandleDataTransfers(Urb);
+            break;
+
+        case URB_FUNCTION_VENDOR_DEVICE:
+        case URB_FUNCTION_VENDOR_INTERFACE:
+        case URB_FUNCTION_VENDOR_ENDPOINT:
+        case URB_FUNCTION_CLASS_DEVICE:
+        case URB_FUNCTION_CLASS_INTERFACE:
+        case URB_FUNCTION_CLASS_ENDPOINT:
+        case URB_FUNCTION_CLASS_OTHER:
+        case URB_FUNCTION_VENDOR_OTHER:
+            Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, FALSE);
+
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n");
+                break;
+            }
+
+            Status = USBPORT_HandleVendorOrClass(Irp, Urb);
+            break;
+
+        case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
+        case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE:
+        case URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT:
+        case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT:
+        case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
+        case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE:
+            Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, FALSE);
+
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n");
+                break;
+            }
+
+            Status = USBPORT_HandleGetSetDescriptor(Irp, Urb);
+            break;
+
+        case URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR:
+            DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR (0x2A) NOT_SUPPORTED\n");
+            return USBPORT_USBDStatusToNtStatus(Urb,
+                                                USBD_STATUS_INVALID_URB_FUNCTION);
+
+        case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
+        case URB_FUNCTION_GET_STATUS_FROM_INTERFACE:
+        case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:
+        case URB_FUNCTION_GET_STATUS_FROM_OTHER:
+            Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, FALSE);
+
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n");
+                break;
+            }
+
+            Status = USBPORT_HandleGetStatus(Irp, Urb);
+            break;
+
+        case URB_FUNCTION_SELECT_CONFIGURATION:
+            Status = USBPORT_HandleSelectConfiguration(PdoExtension->FdoDevice,
+                                                       Irp,
+                                                       Urb);
+            break;
+
+        case URB_FUNCTION_SELECT_INTERFACE:
+            Status = USBPORT_HandleSelectInterface(PdoExtension->FdoDevice,
+                                                   Irp,
+                                                   Urb);
+            break;
+
+        case URB_FUNCTION_GET_CONFIGURATION:
+            Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, FALSE);
+
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n");
+                break;
+            }
+
+            Status = USBPORT_HandleGetConfiguration(Urb);
+            break;
+
+        case URB_FUNCTION_GET_INTERFACE:
+            DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_GET_INTERFACE (0x27) NOT_SUPPORTED\n");
+            return USBPORT_USBDStatusToNtStatus(Urb,
+                                                USBD_STATUS_INVALID_URB_FUNCTION);
+
+        case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
+            Status = USBPORT_SyncResetPipeAndClearStall(PdoExtension->FdoDevice,
+                                                        Irp,
+                                                        Urb);
+            break;
+
+        case URB_FUNCTION_SYNC_RESET_PIPE:
+            Status = USBPORT_ResetPipe(PdoExtension->FdoDevice,
+                                       Irp,
+                                       Urb);
+            break;
+
+        case URB_FUNCTION_SYNC_CLEAR_STALL:
+            Status = USBPORT_ClearStall(PdoExtension->FdoDevice,
+                                        Irp,
+                                        Urb);
+            break;
+
+        case URB_FUNCTION_ABORT_PIPE:
+            Status = USBPORT_AbortPipe(PdoExtension->FdoDevice,
+                                       Irp,
+                                       Urb);
+            break;
+
+        case URB_FUNCTION_SET_FEATURE_TO_DEVICE:
+        case URB_FUNCTION_SET_FEATURE_TO_INTERFACE:
+        case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT:
+        case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE:
+        case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT:
+        case URB_FUNCTION_CLEAR_FEATURE_TO_OTHER:
+        case URB_FUNCTION_SET_FEATURE_TO_OTHER:
+            Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, TRUE);
+
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n");
+                break;
+            }
+
+            Status = USBPORT_HandleSetOrClearFeature(Urb);
+            break;
+
+        case URB_FUNCTION_GET_CURRENT_FRAME_NUMBER:
+            Status = USBPORT_HandleGetCurrentFrame(PdoExtension->FdoDevice,
+                                                   Irp,
+                                                   Urb);
+            break;
+
+        case URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL:
+            DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL (0x03) NOT_SUPPORTED\n");
+            return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_NOT_SUPPORTED);
+
+        case URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL:
+            DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL (0x04) NOT_SUPPORTED\n");
+            return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_NOT_SUPPORTED);
+
+        case URB_FUNCTION_GET_FRAME_LENGTH:
+            DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_GET_FRAME_LENGTH (0x05) NOT_SUPPORTED\n");
+            return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_NOT_SUPPORTED);
+
+        case URB_FUNCTION_SET_FRAME_LENGTH:
+            DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_SET_FRAME_LENGTH (0x06) NOT_SUPPORTED\n");
+            return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_NOT_SUPPORTED);
+
+        default:
+            DPRINT1("USBPORT_HandleSubmitURB: Unknown URB Function - %x\n",
+                    Function);
+            //URB_FUNCTION_RESERVED_0X0016
+            //URB_FUNCTION_RESERVE_0X001D
+            //URB_FUNCTION_RESERVE_0X002B
+            //URB_FUNCTION_RESERVE_0X002C
+            //URB_FUNCTION_RESERVE_0X002D
+            //URB_FUNCTION_RESERVE_0X002E
+            //URB_FUNCTION_RESERVE_0X002F
+            break;
+    }
+
+    if (Status == STATUS_PENDING)
+    {
+        return Status;
+    }
+
+    if (Urb->UrbHeader.UsbdFlags & USBD_FLAG_ALLOCATED_TRANSFER)
+    {
+        PUSBPORT_TRANSFER Transfer;
+
+        Transfer = Urb->UrbControlTransfer.hca.Reserved8[0];
+        Urb->UrbControlTransfer.hca.Reserved8[0] = NULL;
+        Urb->UrbHeader.UsbdFlags |= ~USBD_FLAG_ALLOCATED_TRANSFER;
+        ExFreePoolWithTag(Transfer, USB_PORT_TAG);
+    }
+
+    if (DeviceHandle)
+    {
+        InterlockedDecrement(&DeviceHandle->DeviceHandleLock);
+    }
+
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return Status;
+}
diff --git a/reactos/drivers/usb/usbport/usb2.c b/reactos/drivers/usb/usbport/usb2.c
new file mode 100644 (file)
index 0000000..4bcff0a
--- /dev/null
@@ -0,0 +1,21 @@
+#include "usbport.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+BOOLEAN
+NTAPI
+USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
+                              IN PUSBPORT_ENDPOINT Endpoint)
+{
+    DPRINT1("USBPORT_AllocateBandwidthUSB2: UNIMPLEMENTED. FIXME. \n");
+    return TRUE;
+}
+
+VOID
+NTAPI
+USBPORT_FreeBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
+                          IN PUSBPORT_ENDPOINT Endpoint)
+{
+    DPRINT1("USBPORT_FreeBandwidthUSB2: UNIMPLEMENTED. FIXME. \n");
+}
diff --git a/reactos/drivers/usb/usbport/usbdebug.h b/reactos/drivers/usb/usbport/usbdebug.h
new file mode 100644 (file)
index 0000000..ebeb2e2
--- /dev/null
@@ -0,0 +1,128 @@
+#ifndef USBDEBUG_H__
+#define USBDEBUG_H__
+
+#if DBG
+
+    #ifndef NDEBUG_USBPORT_MINIPORT
+
+        #define DPRINT_MINIPORT(fmt, ...) do { \
+            if (DbgPrint("(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__))  \
+                DbgPrint("(%s:%d) DbgPrint() failed!\n", __RELFILE__, __LINE__); \
+        } while (0)
+
+    #else
+
+#if defined(_MSC_VER)
+        #define DPRINT_MINIPORT   __noop
+#else
+        #define DPRINT_MINIPORT(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
+#endif
+
+    #endif
+
+    #ifndef NDEBUG_USBPORT_CORE
+
+        #define DPRINT_CORE(fmt, ...) do { \
+            if (DbgPrint("(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__))  \
+                DbgPrint("(%s:%d) DbgPrint() failed!\n", __RELFILE__, __LINE__); \
+        } while (0)
+
+    #else
+
+#if defined(_MSC_VER)
+        #define DPRINT_CORE   __noop
+#else
+        #define DPRINT_CORE(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
+#endif
+
+    #endif
+
+    #ifndef NDEBUG_USBPORT_URB
+
+        #define DPRINT_URB(fmt, ...) do { \
+            if (DbgPrint("(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__))  \
+                DbgPrint("(%s:%d) DbgPrint() failed!\n", __RELFILE__, __LINE__); \
+        } while (0)
+
+    #else
+
+#if defined(_MSC_VER)
+        #define DPRINT_URB   __noop
+#else
+        #define DPRINT_URB(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
+#endif
+
+    #endif
+
+    #ifndef NDEBUG_USBPORT_INTERRUPT
+
+        #define DPRINT_INT(fmt, ...) do { \
+            if (DbgPrint("(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__))  \
+                DbgPrint("(%s:%d) DbgPrint() failed!\n", __RELFILE__, __LINE__); \
+        } while (0)
+
+    #else
+
+#if defined(_MSC_VER)
+        #define DPRINT_INT   __noop
+#else
+        #define DPRINT_INT(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
+#endif
+
+    #endif
+
+    #ifndef NDEBUG_USBPORT_TIMER
+
+        #define DPRINT_TIMER(fmt, ...) do { \
+            if (DbgPrint("(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__))  \
+                DbgPrint("(%s:%d) DbgPrint() failed!\n", __RELFILE__, __LINE__); \
+        } while (0)
+
+    #else
+
+#if defined(_MSC_VER)
+        #define DPRINT_TIMER   __noop
+#else
+        #define DPRINT_TIMER(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
+#endif
+
+    #endif
+
+    #ifndef NDEBUG_USBPORT_QUEUE
+
+        #define DPRINT_QUEUE(fmt, ...) do { \
+            if (DbgPrint("(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__))  \
+                DbgPrint("(%s:%d) DbgPrint() failed!\n", __RELFILE__, __LINE__); \
+        } while (0)
+
+    #else
+
+#if defined(_MSC_VER)
+        #define DPRINT_QUEUE   __noop
+#else
+        #define DPRINT_QUEUE(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
+#endif
+
+    #endif
+
+#else /* not DBG */
+
+#if defined(_MSC_VER)
+    #define DPRINT_MINIPORT    __noop
+    #define DPRINT_CORE    __noop
+    #define DPRINT_URB    __noop
+    #define DPRINT_INT    __noop
+    #define DPRINT_TIMER    __noop
+    #define DPRINT_QUEUE    __noop
+#else
+    #define DPRINT_MINIPORT(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
+    #define DPRINT_CORE(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
+    #define DPRINT_URB(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
+    #define DPRINT_INT(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
+    #define DPRINT_TIMER(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
+    #define DPRINT_QUEUE(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
+#endif /* _MSC_VER */
+
+#endif /* not DBG */
+
+#endif /* USBDEBUG_H__ */
diff --git a/reactos/drivers/usb/usbport/usbport.c b/reactos/drivers/usb/usbport/usbport.c
new file mode 100644 (file)
index 0000000..9a09982
--- /dev/null
@@ -0,0 +1,2775 @@
+#include "usbport.h"
+
+#define NDEBUG
+#include <debug.h>
+
+#define NDEBUG_USBPORT_CORE
+#define NDEBUG_USBPORT_INTERRUPT
+#define NDEBUG_USBPORT_TIMER
+#include "usbdebug.h"
+
+LIST_ENTRY USBPORT_MiniPortDrivers = {NULL, NULL};
+LIST_ENTRY USBPORT_USB1FdoList = {NULL, NULL};
+LIST_ENTRY USBPORT_USB2FdoList = {NULL, NULL};
+
+KSPIN_LOCK USBPORT_SpinLock;
+BOOLEAN USBPORT_Initialized = FALSE;
+
+PDEVICE_OBJECT
+NTAPI
+USBPORT_FindUSB2Controller(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_DEVICE_EXTENSION USB2FdoExtension;
+    KIRQL OldIrql;
+    PLIST_ENTRY USB2FdoEntry;
+    PDEVICE_OBJECT USB2FdoDevice = NULL;
+
+    DPRINT("USBPORT_FindUSB2Controller: FdoDevice - %p\n", FdoDevice);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    KeAcquireSpinLock(&USBPORT_SpinLock, &OldIrql);
+
+    USB2FdoEntry = USBPORT_USB2FdoList.Flink;
+
+    while (USB2FdoEntry && USB2FdoEntry != &USBPORT_USB2FdoList)
+    {
+        USB2FdoExtension = CONTAINING_RECORD(USB2FdoEntry,
+                                             USBPORT_DEVICE_EXTENSION,
+                                             ControllerLink);
+
+        if (USB2FdoExtension->BusNumber == FdoExtension->BusNumber &&
+            USB2FdoExtension->PciDeviceNumber == FdoExtension->PciDeviceNumber)
+        {
+            USB2FdoDevice = USB2FdoExtension->CommonExtension.SelfDevice;
+            break;
+        }
+
+        USB2FdoEntry = USB2FdoEntry->Flink;
+    }
+
+    KeReleaseSpinLock(&USBPORT_SpinLock, OldIrql);
+
+    return USB2FdoDevice;
+}
+
+VOID
+NTAPI
+USBPORT_AddUSB1Fdo(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT("USBPORT_AddUSB1Fdo: FdoDevice - %p\n", FdoDevice);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    FdoExtension->Flags |= USBPORT_FLAG_REGISTERED_FDO;
+
+    ExInterlockedInsertTailList(&USBPORT_USB1FdoList,
+                                &FdoExtension->ControllerLink,
+                                &USBPORT_SpinLock);
+}
+
+VOID
+NTAPI
+USBPORT_AddUSB2Fdo(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT("USBPORT_AddUSB2Fdo: FdoDevice - %p\n", FdoDevice);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    FdoExtension->Flags |= USBPORT_FLAG_REGISTERED_FDO;
+
+    ExInterlockedInsertTailList(&USBPORT_USB2FdoList,
+                                &FdoExtension->ControllerLink,
+                                &USBPORT_SpinLock);
+}
+
+VOID
+NTAPI
+USBPORT_RemoveUSBxFdo(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    KIRQL OldIrql;
+
+    DPRINT("USBPORT_RemoveUSBxFdo: FdoDevice - %p\n", FdoDevice);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    KeAcquireSpinLock(&USBPORT_SpinLock, &OldIrql);
+    RemoveEntryList(&FdoExtension->ControllerLink);
+    KeReleaseSpinLock(&USBPORT_SpinLock, OldIrql);
+
+    FdoExtension->Flags &= ~USBPORT_FLAG_REGISTERED_FDO;
+
+    FdoExtension->ControllerLink.Flink = NULL;
+    FdoExtension->ControllerLink.Blink = NULL;
+}
+
+BOOLEAN
+NTAPI
+USBPORT_IsCompanionFdoExtension(IN PDEVICE_OBJECT USB2FdoDevice,
+                                IN PUSBPORT_DEVICE_EXTENSION USB1FdoExtension)
+{
+    PUSBPORT_DEVICE_EXTENSION USB2FdoExtension;
+
+    DPRINT("USBPORT_IsCompanionFdoExtension: USB2Fdo - %p, USB1FdoExtension - %p\n",
+           USB2FdoDevice,
+           USB1FdoExtension);
+
+    USB2FdoExtension = USB2FdoDevice->DeviceExtension;
+
+    return USB2FdoExtension->BusNumber == USB1FdoExtension->BusNumber &&
+           USB2FdoExtension->PciDeviceNumber == USB1FdoExtension->PciDeviceNumber;
+}
+
+PDEVICE_RELATIONS
+NTAPI
+USBPORT_FindCompanionControllers(IN PDEVICE_OBJECT USB2FdoDevice,
+                                 IN BOOLEAN IsObRefer,
+                                 IN BOOLEAN IsFDOsReturned)
+{
+    PLIST_ENTRY USB1FdoList;
+    PUSBPORT_DEVICE_EXTENSION USB1FdoExtension;
+    ULONG NumControllers = 0; 
+    PDEVICE_OBJECT * Entry;
+    PDEVICE_RELATIONS ControllersList = NULL;
+    KIRQL OldIrql;
+
+    DPRINT("USBPORT_FindCompanionControllers: USB2Fdo - %p, IsObRefer - %x, IsFDOs - %x\n",
+           USB2FdoDevice,
+           IsObRefer,
+           IsFDOsReturned);
+
+    KeAcquireSpinLock(&USBPORT_SpinLock, &OldIrql);
+
+    USB1FdoList = USBPORT_USB1FdoList.Flink;
+
+    while (USB1FdoList && USB1FdoList != &USBPORT_USB1FdoList)
+    {
+        USB1FdoExtension = CONTAINING_RECORD(USB1FdoList,
+                                             USBPORT_DEVICE_EXTENSION,
+                                             ControllerLink);
+
+        if (USB1FdoExtension->Flags & USBPORT_FLAG_COMPANION_HC &&
+            USBPORT_IsCompanionFdoExtension(USB2FdoDevice, USB1FdoExtension))
+        {
+            ++NumControllers;
+        }
+
+        USB1FdoList = USB1FdoExtension->ControllerLink.Flink;
+    }
+
+    DPRINT("USBPORT_FindCompanionControllers: NumControllers - %x\n",
+           NumControllers);
+
+    if (!NumControllers)
+    {
+        goto Exit;
+    }
+
+    ControllersList = ExAllocatePoolWithTag(NonPagedPool,
+                                            NumControllers * sizeof(DEVICE_RELATIONS),
+                                            USB_PORT_TAG);
+
+    if (!ControllersList)
+    {
+        goto Exit;
+    }
+
+    RtlZeroMemory(ControllersList, NumControllers * sizeof(DEVICE_RELATIONS));
+
+    ControllersList->Count = NumControllers;
+
+    USB1FdoList = USBPORT_USB1FdoList.Flink;
+
+    Entry = &ControllersList->Objects[0];
+
+    while (USB1FdoList && USB1FdoList != &USBPORT_USB1FdoList)
+    {
+        USB1FdoExtension = CONTAINING_RECORD(USB1FdoList,
+                                             USBPORT_DEVICE_EXTENSION,
+                                             ControllerLink);
+
+        if (USB1FdoExtension->Flags & USBPORT_FLAG_COMPANION_HC &&
+            USBPORT_IsCompanionFdoExtension(USB2FdoDevice, USB1FdoExtension))
+        {
+            *Entry = USB1FdoExtension->CommonExtension.LowerPdoDevice;
+
+            if (IsObRefer)
+            {
+                ObReferenceObject(USB1FdoExtension->CommonExtension.LowerPdoDevice);
+            }
+
+            if (IsFDOsReturned)
+            {
+                *Entry = USB1FdoExtension->CommonExtension.SelfDevice;
+            }
+
+            ++Entry;
+        }
+
+        USB1FdoList = USB1FdoExtension->ControllerLink.Flink;
+    }
+
+Exit:
+
+    KeReleaseSpinLock(&USBPORT_SpinLock, OldIrql);
+
+    return ControllersList;
+}
+
+MPSTATUS
+NTAPI
+USBPORT_NtStatusToMpStatus(NTSTATUS NtStatus)
+{
+    DPRINT("USBPORT_NtStatusToMpStatus: NtStatus - %x\n", NtStatus);
+
+    if (NtStatus == STATUS_SUCCESS)
+    {
+        return MP_STATUS_SUCCESS;
+    }
+    else
+    {
+        return MP_STATUS_UNSUCCESSFUL;
+    }
+}
+
+NTSTATUS
+NTAPI
+USBPORT_SetRegistryKeyValue(IN PDEVICE_OBJECT DeviceObject,
+                            IN BOOL UseDriverKey,
+                            IN ULONG Type,
+                            IN PCWSTR ValueNameString,
+                            IN PVOID Data,
+                            IN ULONG DataSize)
+{
+    UNICODE_STRING ValueName;
+    HANDLE KeyHandle;
+    NTSTATUS Status;
+
+    DPRINT("USBPORT_SetRegistryKeyValue: ValueNameString - %S \n",
+           ValueNameString);
+
+    if (UseDriverKey)
+    {
+        Status = IoOpenDeviceRegistryKey(DeviceObject,
+                                         PLUGPLAY_REGKEY_DRIVER,
+                                         STANDARD_RIGHTS_ALL,
+                                         &KeyHandle);
+    }
+    else
+    {
+        Status = IoOpenDeviceRegistryKey(DeviceObject,
+                                         PLUGPLAY_REGKEY_DEVICE,
+                                         STANDARD_RIGHTS_ALL,
+                                         &KeyHandle);
+    }
+
+    if (NT_SUCCESS(Status))
+    {
+        RtlInitUnicodeString(&ValueName, ValueNameString);
+
+        Status = ZwSetValueKey(KeyHandle,
+                               &ValueName,
+                               0,
+                               Type,
+                               Data,
+                               DataSize);
+
+        ZwClose(KeyHandle);
+    }
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_GetRegistryKeyValueFullInfo(IN PDEVICE_OBJECT FdoDevice,
+                                    IN PDEVICE_OBJECT PdoDevice,
+                                    IN BOOL UseDriverKey,
+                                    IN PCWSTR SourceString,
+                                    IN ULONG LengthStr,
+                                    IN PVOID Buffer,
+                                    IN ULONG BufferLength)
+{
+    NTSTATUS Status;
+    PKEY_VALUE_FULL_INFORMATION KeyValue;
+    UNICODE_STRING ValueName;
+    HANDLE KeyHandle;
+    ULONG LengthKey;
+
+    DPRINT("USBPORT_GetRegistryKeyValue: UseDriverKey - %x, SourceString - %S, LengthStr - %x, Buffer - %p, BufferLength - %x\n",
+           UseDriverKey,
+           SourceString,
+           LengthStr,
+           Buffer,
+           BufferLength);
+
+    if (UseDriverKey)
+    {
+        Status = IoOpenDeviceRegistryKey(PdoDevice,
+                                         PLUGPLAY_REGKEY_DRIVER,
+                                         STANDARD_RIGHTS_ALL,
+                                         &KeyHandle);
+    }
+    else
+    {
+        Status = IoOpenDeviceRegistryKey(PdoDevice,
+                                         PLUGPLAY_REGKEY_DEVICE,
+                                         STANDARD_RIGHTS_ALL,
+                                         &KeyHandle);
+    }
+
+    if (NT_SUCCESS(Status))
+    {
+        RtlInitUnicodeString(&ValueName, SourceString);
+
+        LengthKey = sizeof(KEY_VALUE_FULL_INFORMATION) +
+                    LengthStr +
+                    BufferLength;
+
+        KeyValue = ExAllocatePoolWithTag(PagedPool,
+                                         LengthKey,
+                                         USB_PORT_TAG);
+
+        if (KeyValue)
+        {
+            RtlZeroMemory(KeyValue, LengthKey);
+
+            Status = ZwQueryValueKey(KeyHandle,
+                                     &ValueName,
+                                     KeyValueFullInformation,
+                                     KeyValue,
+                                     LengthKey,
+                                     &LengthKey);
+
+            if (NT_SUCCESS(Status))
+            {
+                RtlCopyMemory(Buffer,
+                              (PUCHAR)KeyValue + KeyValue->DataOffset,
+                              BufferLength);
+            }
+
+            ExFreePoolWithTag(KeyValue, USB_PORT_TAG);
+        }
+
+        ZwClose(KeyHandle);
+    }
+
+    return Status;
+}
+
+MPSTATUS
+NTAPI
+USBPORT_GetMiniportRegistryKeyValue(IN PVOID Context,
+                                    IN BOOL UseDriverKey,
+                                    IN PCWSTR SourceString,
+                                    IN SIZE_T LengthStr,
+                                    IN PVOID Buffer,
+                                    IN SIZE_T BufferLength)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PDEVICE_OBJECT FdoDevice;
+    NTSTATUS Status;
+
+    DPRINT("USBPORT_GetMiniportRegistryKeyValue: Context - %p, UseDriverKey - %x, SourceString - %S, LengthStr - %x, Buffer - %p, BufferLength - %x\n",
+           Context,
+           UseDriverKey,
+           SourceString,
+           LengthStr,
+           Buffer,
+           BufferLength);
+
+    //DbgBreakPoint();
+
+    //FdoExtension->MiniPortExt = (PVOID)((ULONG_PTR)FdoExtension + sizeof(USBPORT_DEVICE_EXTENSION));
+    FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)Context -
+                                               sizeof(USBPORT_DEVICE_EXTENSION));
+
+    FdoDevice = FdoExtension->CommonExtension.SelfDevice;
+
+    Status = USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
+                                                 FdoExtension->CommonExtension.LowerPdoDevice,
+                                                 UseDriverKey,
+                                                 SourceString,
+                                                 LengthStr,
+                                                 Buffer,
+                                                 BufferLength);
+
+    return USBPORT_NtStatusToMpStatus(Status);
+}
+
+NTSTATUS
+NTAPI
+USBPORT_GetSetConfigSpaceData(IN PDEVICE_OBJECT FdoDevice,
+                              IN BOOLEAN IsReadData,
+                              IN PVOID Buffer,
+                              IN ULONG Offset,
+                              IN ULONG Length)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    ULONG BytesReadWrite;
+
+    DPRINT("USBPORT_GetSetConfigSpaceData ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    BytesReadWrite = Length;
+
+    if (IsReadData)
+    {
+        RtlZeroMemory(Buffer, Length);
+
+        BytesReadWrite = (*FdoExtension->BusInterface.GetBusData)
+                          (FdoExtension->BusInterface.Context,
+                           PCI_WHICHSPACE_CONFIG,
+                           Buffer,
+                           Offset,
+                           Length);
+    }
+    else
+    {
+        BytesReadWrite = (*FdoExtension->BusInterface.SetBusData)
+                          (FdoExtension->BusInterface.Context,
+                           PCI_WHICHSPACE_CONFIG,
+                           Buffer,
+                           Offset,
+                           Length);
+    }
+
+    if (BytesReadWrite == Length)
+    {
+        return STATUS_SUCCESS;
+    }
+
+    return STATUS_UNSUCCESSFUL;
+}
+
+MPSTATUS
+NTAPI
+USBPORT_ReadWriteConfigSpace(IN PVOID Context,
+                             IN BOOLEAN IsReadData,
+                             IN PVOID Buffer,
+                             IN ULONG Offset,
+                             IN ULONG Length)
+{
+    NTSTATUS Status;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PDEVICE_OBJECT FdoDevice;
+
+    DPRINT("USBPORT_ReadWriteConfigSpace: ... \n");
+
+    //FdoExtension->MiniPortExt = (PVOID)((ULONG_PTR)FdoExtension + sizeof(USBPORT_DEVICE_EXTENSION));
+    FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)Context -
+                                               sizeof(USBPORT_DEVICE_EXTENSION));
+
+    FdoDevice = FdoExtension->CommonExtension.SelfDevice;
+
+    Status = USBPORT_GetSetConfigSpaceData(FdoDevice,
+                                           IsReadData,
+                                           Buffer,
+                                           Offset,
+                                           Length);
+
+    return USBPORT_NtStatusToMpStatus(Status);
+}
+
+NTSTATUS
+NTAPI
+USBPORT_USBDStatusToNtStatus(IN PURB Urb,
+                             IN USBD_STATUS USBDStatus)
+{
+    NTSTATUS Status;
+
+    if (USBD_ERROR(USBDStatus))
+    {
+        DPRINT1("USBPORT_USBDStatusToNtStatus: Urb - %p, USBDStatus - %x\n",
+                Urb,
+                USBDStatus);
+    }
+
+    if (Urb)
+        Urb->UrbHeader.Status = USBDStatus;
+
+    switch (USBDStatus)
+    {
+        case USBD_STATUS_SUCCESS:
+            Status = STATUS_SUCCESS;
+            break;
+
+        case USBD_STATUS_INSUFFICIENT_RESOURCES:
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            break;
+
+        case USBD_STATUS_DEVICE_GONE:
+            Status = STATUS_DEVICE_NOT_CONNECTED;
+            break;
+
+        case USBD_STATUS_CANCELED:
+            Status = STATUS_CANCELLED;
+            break;
+
+        case USBD_STATUS_NOT_SUPPORTED:
+            Status = STATUS_NOT_SUPPORTED;
+            break;
+
+        case USBD_STATUS_INVALID_URB_FUNCTION:
+        case USBD_STATUS_INVALID_PARAMETER:
+        case USBD_STATUS_INVALID_PIPE_HANDLE:
+        case USBD_STATUS_BAD_START_FRAME:
+            Status = STATUS_INVALID_PARAMETER;
+            break;
+
+        default:
+            if (USBD_ERROR(USBDStatus))
+                Status = STATUS_UNSUCCESSFUL;
+            else
+                Status = STATUS_SUCCESS;
+
+            break;
+    }
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_Wait(IN PVOID Context,
+             IN ULONG Milliseconds)
+{
+    LARGE_INTEGER Interval = {{0, 0}};
+
+    DPRINT("USBPORT_Wait: Milliseconds - %x\n", Milliseconds);
+    Interval.QuadPart -= 10000 * Milliseconds + (KeQueryTimeIncrement() - 1);
+    return KeDelayExecutionThread(KernelMode, FALSE, &Interval);
+}
+
+VOID
+NTAPI
+USBPORT_MiniportInterrupts(IN PDEVICE_OBJECT FdoDevice,
+                           IN BOOLEAN IsEnable)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    BOOLEAN IsLock;
+    KIRQL OldIrql;
+
+    DPRINT_INT("USBPORT_MiniportInterrupts: IsEnable - %p\n", IsEnable);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    IsLock = (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_NOT_LOCK_INT) == 0;
+
+    if (IsLock)
+        KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+
+    if (IsEnable)
+    {
+        FdoExtension->Flags |= USBPORT_FLAG_INTERRUPT_ENABLED;
+        Packet->EnableInterrupts(FdoExtension->MiniPortExt);
+    }
+    else
+    {
+        Packet->DisableInterrupts(FdoExtension->MiniPortExt);
+        FdoExtension->Flags &= ~USBPORT_FLAG_INTERRUPT_ENABLED;
+    }
+
+    if (IsLock)
+        KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+}
+
+VOID
+NTAPI
+USBPORT_SoftInterruptDpc(IN PRKDPC Dpc,
+                         IN PVOID DeferredContext,
+                         IN PVOID SystemArgument1,
+                         IN PVOID SystemArgument2)
+{
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT("USBPORT_SoftInterruptDpc: ... \n");
+
+    FdoDevice = DeferredContext;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    if (!KeInsertQueueDpc(&FdoExtension->IsrDpc, NULL, (PVOID)1))
+    {
+        InterlockedDecrement(&FdoExtension->IsrDpcCounter);
+    }
+}
+
+VOID
+NTAPI
+USBPORT_SoftInterrupt(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    LARGE_INTEGER DueTime = {{0, 0}};
+
+    DPRINT("USBPORT_SoftInterrupt: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    KeInitializeTimer(&FdoExtension->TimerSoftInterrupt);
+
+    KeInitializeDpc(&FdoExtension->SoftInterruptDpc,
+                    USBPORT_SoftInterruptDpc,
+                    FdoDevice);
+
+    DueTime.QuadPart -= 10000 + (KeQueryTimeIncrement() - 1);
+
+    KeSetTimer(&FdoExtension->TimerSoftInterrupt,
+               DueTime,
+               &FdoExtension->SoftInterruptDpc);
+}
+
+VOID
+NTAPI
+USBPORT_InvalidateControllerHandler(IN PDEVICE_OBJECT FdoDevice,
+                                    IN ULONG Type)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT("USBPORT_InvalidateControllerHandler: Invalidate Type - %x\n",
+           Type);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    switch (Type)
+    {
+        case INVALIDATE_CONTROLLER_RESET:
+            DPRINT1("USBPORT_InvalidateControllerHandler: INVALIDATE_CONTROLLER_RESET UNIMPLEMENTED. FIXME. \n");
+            break;
+
+        case INVALIDATE_CONTROLLER_SURPRISE_REMOVE:
+            DPRINT1("USBPORT_InvalidateControllerHandler: INVALIDATE_CONTROLLER_SURPRISE_REMOVE UNIMPLEMENTED. FIXME. \n");
+            break;
+
+        case INVALIDATE_CONTROLLER_SOFT_INTERRUPT:
+            if (InterlockedIncrement(&FdoExtension->IsrDpcCounter))
+            {
+                InterlockedDecrement(&FdoExtension->IsrDpcCounter);
+            }
+            else
+            {
+                USBPORT_SoftInterrupt(FdoDevice);
+            }
+            break;
+    }
+}
+
+ULONG
+NTAPI
+USBPORT_InvalidateController(IN PVOID Context,
+                             IN ULONG Type)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PDEVICE_OBJECT FdoDevice;
+
+    DPRINT("USBPORT_InvalidateController: Invalidate Type - %x\n", Type);
+
+    //FdoExtension->MiniPortExt = (PVOID)((ULONG_PTR)FdoExtension + sizeof(USBPORT_DEVICE_EXTENSION));
+    FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)Context -
+                                               sizeof(USBPORT_DEVICE_EXTENSION));
+    FdoDevice = FdoExtension->CommonExtension.SelfDevice;
+
+    USBPORT_InvalidateControllerHandler(FdoDevice, Type);
+
+    return 0;
+}
+
+ULONG
+NTAPI
+USBPORT_NotifyDoubleBuffer(IN PVOID Context1,
+                           IN PVOID Context2,
+                           IN PVOID Buffer,
+                           IN SIZE_T Length)
+{
+    DPRINT1("USBPORT_NotifyDoubleBuffer: UNIMPLEMENTED. FIXME. \n");
+    return 0;
+}
+
+VOID
+NTAPI
+USBPORT_WorkerRequestDpc(IN PRKDPC Dpc,
+                         IN PVOID DeferredContext,
+                         IN PVOID SystemArgument1,
+                         IN PVOID SystemArgument2)
+{
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT("USBPORT_WorkerRequestDpc: ... \n");
+
+    FdoDevice = DeferredContext;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    if (!InterlockedIncrement(&FdoExtension->IsrDpcHandlerCounter))
+    {
+        USBPORT_DpcHandler(FdoDevice);
+    }
+
+    InterlockedDecrement(&FdoExtension->IsrDpcHandlerCounter);
+}
+
+VOID
+NTAPI
+USBPORT_DoneTransfer(IN PUSBPORT_TRANSFER Transfer)
+{
+    PUSBPORT_ENDPOINT          Endpoint;
+    PDEVICE_OBJECT             FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION  FdoExtension;
+    PURB                       Urb;
+    PIRP                       Irp;
+    KIRQL                      CancelIrql;
+    KIRQL                      OldIrql;
+
+    DPRINT_CORE("USBPORT_DoneTransfer: Transfer - %p\n", Transfer);
+
+    Endpoint = Transfer->Endpoint;
+    FdoDevice = Endpoint->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    Urb = Transfer->Urb;
+    Irp = Transfer->Irp;
+
+    KeAcquireSpinLock(&FdoExtension->FlushTransferSpinLock, &OldIrql);
+
+    if (Irp)
+    {
+        IoAcquireCancelSpinLock(&CancelIrql);
+        IoSetCancelRoutine(Irp, NULL);
+        IoReleaseCancelSpinLock(CancelIrql);
+
+        USBPORT_RemoveActiveTransferIrp(FdoDevice, Irp);
+    }
+
+    KeReleaseSpinLock(&FdoExtension->FlushTransferSpinLock, OldIrql);
+
+    USBPORT_USBDStatusToNtStatus(Transfer->Urb, Transfer->USBDStatus);
+    USBPORT_CompleteTransfer(Urb, Urb->UrbHeader.Status);
+
+    DPRINT_CORE("USBPORT_DoneTransfer: exit\n");
+}
+
+VOID
+NTAPI
+USBPORT_FlushDoneTransfers(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PLIST_ENTRY DoneTransferList;
+    PUSBPORT_TRANSFER Transfer;
+    PUSBPORT_ENDPOINT Endpoint;
+    ULONG TransferCount;
+    KIRQL OldIrql;
+    BOOLEAN IsHasTransfers;
+
+    DPRINT_CORE("USBPORT_FlushDoneTransfers: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    DoneTransferList = &FdoExtension->DoneTransferList;
+
+    while (TRUE)
+    {
+        KeAcquireSpinLock(&FdoExtension->DoneTransferSpinLock, &OldIrql);
+
+        if (IsListEmpty(DoneTransferList))
+            break;
+
+        Transfer = CONTAINING_RECORD(DoneTransferList->Flink,
+                                     USBPORT_TRANSFER,
+                                     TransferLink);
+
+        RemoveHeadList(DoneTransferList);
+        KeReleaseSpinLock(&FdoExtension->DoneTransferSpinLock, OldIrql);
+
+        if (Transfer)
+        {
+            Endpoint = Transfer->Endpoint;
+
+            if ((Transfer->Flags & TRANSFER_FLAG_SPLITED))
+            {
+                ASSERT(FALSE);// USBPORT_DoneSplitTransfer(Transfer);
+            }
+            else
+            {
+                USBPORT_DoneTransfer(Transfer);
+            }
+
+            IsHasTransfers = USBPORT_EndpointHasQueuedTransfers(FdoDevice,
+                                                                Endpoint,
+                                                                &TransferCount);
+
+            if (IsHasTransfers && !TransferCount)
+            {
+                USBPORT_InvalidateEndpointHandler(FdoDevice,
+                                                  Endpoint,
+                                                  INVALIDATE_ENDPOINT_WORKER_DPC);
+            }
+        }
+    }
+
+    KeReleaseSpinLock(&FdoExtension->DoneTransferSpinLock, OldIrql);
+}
+
+
+VOID
+NTAPI
+USBPORT_TransferFlushDpc(IN PRKDPC Dpc,
+                         IN PVOID DeferredContext,
+                         IN PVOID SystemArgument1,
+                         IN PVOID SystemArgument2)
+{
+    PDEVICE_OBJECT FdoDevice;
+
+    DPRINT_CORE("USBPORT_TransferFlushDpc: ... \n");
+    FdoDevice = DeferredContext;
+    USBPORT_FlushDoneTransfers(FdoDevice);
+}
+
+BOOLEAN
+NTAPI
+USBPORT_QueueDoneTransfer(IN PUSBPORT_TRANSFER Transfer,
+                          IN USBD_STATUS USBDStatus)
+{
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION  FdoExtension;
+
+    DPRINT_CORE("USBPORT_QueueDoneTransfer: Transfer - %p, USBDStatus - %p\n",
+                Transfer,
+                USBDStatus);
+
+    FdoDevice = Transfer->Endpoint->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    RemoveEntryList(&Transfer->TransferLink);
+    Transfer->USBDStatus = USBDStatus;
+
+    ExInterlockedInsertTailList(&FdoExtension->DoneTransferList,
+                                &Transfer->TransferLink,
+                                &FdoExtension->DoneTransferSpinLock);
+
+    return KeInsertQueueDpc(&FdoExtension->TransferFlushDpc, NULL, NULL);
+}
+
+VOID
+NTAPI
+USBPORT_DpcHandler(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_ENDPOINT Endpoint;
+    PLIST_ENTRY Entry;
+    LIST_ENTRY List;
+    LONG LockCounter;
+
+    DPRINT("USBPORT_DpcHandler: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    InitializeListHead(&List);
+
+    KeAcquireSpinLockAtDpcLevel(&FdoExtension->EndpointListSpinLock);
+    Entry = FdoExtension->EndpointList.Flink;
+
+    while (Entry && Entry != &FdoExtension->EndpointList)
+    {
+        Endpoint = CONTAINING_RECORD(Entry,
+                                     USBPORT_ENDPOINT,
+                                     EndpointLink);
+
+        LockCounter = InterlockedIncrement(&Endpoint->LockCounter);
+
+        if (USBPORT_GetEndpointState(Endpoint) != USBPORT_ENDPOINT_ACTIVE ||
+            LockCounter ||
+            Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)
+        {
+            InterlockedDecrement(&Endpoint->LockCounter);
+        }
+        else
+        {
+            InsertTailList(&List, &Endpoint->DispatchLink);
+
+            if (Endpoint->WorkerLink.Flink && Endpoint->WorkerLink.Blink)
+            {
+                RemoveEntryList(&Endpoint->WorkerLink);
+
+                Endpoint->WorkerLink.Flink = NULL;
+                Endpoint->WorkerLink.Blink = NULL;
+            }
+        }
+
+        Entry = Endpoint->EndpointLink.Flink;
+    }
+
+    KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock);
+
+    while (!IsListEmpty(&List))
+    {
+        Endpoint = CONTAINING_RECORD(List.Flink,
+                                     USBPORT_ENDPOINT,
+                                     DispatchLink);
+
+        RemoveEntryList(List.Flink);
+        Endpoint->DispatchLink.Flink = NULL;
+        Endpoint->DispatchLink.Blink = NULL;
+
+        USBPORT_EndpointWorker(Endpoint, TRUE);
+        USBPORT_FlushPendingTransfers(Endpoint);
+    }
+
+    KeAcquireSpinLockAtDpcLevel(&FdoExtension->EndpointListSpinLock);
+
+    if (!IsListEmpty(&FdoExtension->WorkerList))
+    {
+        USBPORT_SignalWorkerThread(FdoDevice);
+    }
+
+    KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock);
+
+    USBPORT_FlushDoneTransfers(FdoDevice);
+}
+
+VOID
+NTAPI
+USBPORT_IsrDpcHandler(IN PDEVICE_OBJECT FdoDevice,
+                      IN BOOLEAN IsDpcHandler)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    PUSBPORT_ENDPOINT Endpoint;
+    PLIST_ENTRY List;
+    ULONG FrameNumber;
+
+    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+    DPRINT_CORE("USBPORT_IsrDpcHandler: IsDpcHandler - %x\n", IsDpcHandler);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    if (InterlockedIncrement(&FdoExtension->IsrDpcHandlerCounter))
+    {
+        KeInsertQueueDpc(&FdoExtension->IsrDpc, NULL, NULL);
+        InterlockedDecrement(&FdoExtension->IsrDpcHandlerCounter);
+        return;
+    }
+
+    for (List = ExInterlockedRemoveHeadList(&FdoExtension->EpStateChangeList,
+                                            &FdoExtension->EpStateChangeSpinLock);
+         List != NULL;
+         List = ExInterlockedRemoveHeadList(&FdoExtension->EpStateChangeList,
+                                            &FdoExtension->EpStateChangeSpinLock))
+    {
+        Endpoint = CONTAINING_RECORD(List,
+                                     USBPORT_ENDPOINT,
+                                     StateChangeLink);
+
+        DPRINT_CORE("USBPORT_IsrDpcHandler: Endpoint - %p\n", Endpoint);
+
+        KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock);
+
+        KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
+        FrameNumber = Packet->Get32BitFrameNumber(FdoExtension->MiniPortExt);
+        KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
+
+        if (FrameNumber <= Endpoint->FrameNumber &&
+            !(Endpoint->Flags & ENDPOINT_FLAG_NUKE))
+        {
+            KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
+
+            ExInterlockedInsertHeadList(&FdoExtension->EpStateChangeList,
+                                        &Endpoint->StateChangeLink,
+                                        &FdoExtension->EpStateChangeSpinLock);
+
+            KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
+            Packet->InterruptNextSOF(FdoExtension->MiniPortExt);
+            KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
+
+            break;
+        }
+
+        KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
+
+        KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock);
+        Endpoint->StateLast = Endpoint->StateNext;
+        KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock);
+
+        DPRINT_CORE("USBPORT_IsrDpcHandler: Endpoint->StateLast - %x\n",
+                    Endpoint->StateLast);
+
+        if (IsDpcHandler)
+        {
+            USBPORT_InvalidateEndpointHandler(FdoDevice,
+                                              Endpoint,
+                                              INVALIDATE_ENDPOINT_ONLY);
+        }
+        else
+        {
+            USBPORT_InvalidateEndpointHandler(FdoDevice,
+                                              Endpoint,
+                                              INVALIDATE_ENDPOINT_WORKER_THREAD);
+        }
+    }
+
+    if (IsDpcHandler)
+    {
+        USBPORT_DpcHandler(FdoDevice);
+    }
+
+    InterlockedDecrement(&FdoExtension->IsrDpcHandlerCounter);
+}
+
+VOID
+NTAPI
+USBPORT_IsrDpc(IN PRKDPC Dpc,
+               IN PVOID DeferredContext,
+               IN PVOID SystemArgument1,
+               IN PVOID SystemArgument2)
+{
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    BOOLEAN InterruptEnable;
+
+    DPRINT_INT("USBPORT_IsrDpc: DeferredContext - %p, SystemArgument2 - %p\n",
+               DeferredContext,
+               SystemArgument2);
+
+    FdoDevice = DeferredContext;
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    if (SystemArgument2)
+    {
+        InterlockedDecrement(&FdoExtension->IsrDpcCounter);
+    }
+
+    KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportInterruptsSpinLock);
+    InterruptEnable = (FdoExtension->Flags & USBPORT_FLAG_INTERRUPT_ENABLED) ==
+                       USBPORT_FLAG_INTERRUPT_ENABLED;
+
+    Packet->InterruptDpc(FdoExtension->MiniPortExt, InterruptEnable);
+
+    KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportInterruptsSpinLock);
+
+    if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND &&
+        FdoExtension->TimerFlags & USBPORT_TMFLAG_WAKE)
+    {
+        USBPORT_CompletePdoWaitWake(FdoDevice);
+    }
+    else
+    {
+        USBPORT_IsrDpcHandler(FdoDevice, TRUE);
+    }
+
+    DPRINT_INT("USBPORT_IsrDpc: exit\n");
+}
+
+BOOLEAN
+NTAPI
+USBPORT_InterruptService(IN PKINTERRUPT Interrupt,
+                         IN PVOID ServiceContext)
+{
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    BOOLEAN Result = FALSE;
+
+    FdoDevice = ServiceContext;
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    DPRINT_INT("USBPORT_InterruptService: FdoExtension->Flags - %lx\n",
+           FdoExtension->Flags);
+
+    if (FdoExtension->Flags & USBPORT_FLAG_INTERRUPT_ENABLED &&
+        FdoExtension->MiniPortFlags & USBPORT_MPFLAG_INTERRUPTS_ENABLED)
+    {
+        Result = Packet->InterruptService(FdoExtension->MiniPortExt);
+
+        if (Result)
+        {
+            KeInsertQueueDpc(&FdoExtension->IsrDpc, NULL, NULL);
+        }
+    }
+
+    DPRINT_INT("USBPORT_InterruptService: return - %x\n", Result);
+
+    return Result;
+}
+
+VOID
+NTAPI
+USBPORT_SignalWorkerThread(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    KIRQL OldIrql;
+
+    DPRINT_CORE("USBPORT_SignalWorkerThread ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    KeAcquireSpinLock(&FdoExtension->WorkerThreadEventSpinLock, &OldIrql);
+    KeSetEvent(&FdoExtension->WorkerThreadEvent, EVENT_INCREMENT, FALSE);
+    KeReleaseSpinLock(&FdoExtension->WorkerThreadEventSpinLock, OldIrql);
+}
+
+VOID
+NTAPI
+USBPORT_WorkerThreadHandler(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    PLIST_ENTRY workerList;
+    KIRQL OldIrql;
+    PUSBPORT_ENDPOINT Endpoint;
+    LIST_ENTRY list;
+    BOOLEAN Result;
+
+    DPRINT_CORE("USBPORT_WorkerThreadHandler: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+
+    if (!(FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND))
+    {
+        Packet->CheckController(FdoExtension->MiniPortExt);
+    }
+
+    KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+
+    InitializeListHead(&list);
+
+    USBPORT_FlushAllEndpoints(FdoDevice);
+
+    while (TRUE)
+    {
+        KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+        KeAcquireSpinLockAtDpcLevel(&FdoExtension->EndpointListSpinLock);
+
+        workerList = &FdoExtension->WorkerList;
+
+        if (IsListEmpty(workerList))
+            break;
+
+        Endpoint = CONTAINING_RECORD(workerList->Flink,
+                                     USBPORT_ENDPOINT,
+                                     WorkerLink);
+
+        DPRINT_CORE("USBPORT_WorkerThreadHandler: Endpoint - %p\n", Endpoint);
+
+        RemoveHeadList(workerList);
+        Endpoint->WorkerLink.Blink = NULL;
+        Endpoint->WorkerLink.Flink = NULL;
+
+        KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock);
+
+        Result = USBPORT_EndpointWorker(Endpoint, FALSE);
+        KeAcquireSpinLockAtDpcLevel(&FdoExtension->EndpointListSpinLock);
+
+        if (Result)
+        {
+            if (Endpoint->FlushAbortLink.Flink == NULL ||
+                Endpoint->FlushAbortLink.Blink == NULL)
+            {
+                InsertTailList(&list, &Endpoint->FlushAbortLink);
+            }
+        }
+
+        while (!IsListEmpty(&list))
+        {
+            Endpoint = CONTAINING_RECORD(list.Flink,
+                                         USBPORT_ENDPOINT,
+                                         FlushAbortLink);
+
+            RemoveHeadList(&list);
+
+            Endpoint->FlushAbortLink.Flink = NULL;
+            Endpoint->FlushAbortLink.Blink = NULL;
+
+            if (Endpoint->WorkerLink.Flink == NULL ||
+                Endpoint->WorkerLink.Blink == NULL)
+            {
+                InsertTailList(&FdoExtension->WorkerList,
+                               &Endpoint->WorkerLink);
+
+                USBPORT_SignalWorkerThread(FdoDevice);
+            }
+        }
+
+        KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock);
+        KeLowerIrql(OldIrql);
+    }
+
+    KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock);
+    KeLowerIrql(OldIrql);
+
+    USBPORT_FlushClosedEndpointList(FdoDevice);
+}
+
+VOID
+NTAPI
+USBPORT_DoRootHubCallback(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PDEVICE_OBJECT PdoDevice;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PRH_INIT_CALLBACK RootHubInitCallback;
+    PVOID RootHubInitContext;
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    DPRINT("USBPORT_DoRootHubCallback: FdoDevice - %p\n", FdoDevice);
+
+    PdoDevice = FdoExtension->RootHubPdo;
+
+    if (PdoDevice)
+    {
+        PdoExtension = PdoDevice->DeviceExtension;
+
+        RootHubInitContext = PdoExtension->RootHubInitContext;
+        RootHubInitCallback = PdoExtension->RootHubInitCallback;
+
+        PdoExtension->RootHubInitCallback = NULL;
+        PdoExtension->RootHubInitContext = NULL;
+
+        if (RootHubInitCallback)
+        {
+            RootHubInitCallback(RootHubInitContext);
+        }
+    }
+
+    DPRINT("USBPORT_DoRootHubCallback: exit\n");
+}
+
+VOID
+NTAPI
+USBPORT_SynchronizeRootHubCallback(IN PDEVICE_OBJECT FdoDevice,
+                                   IN PDEVICE_OBJECT Usb2FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    PUSBPORT_DEVICE_EXTENSION Usb2FdoExtension;
+    PDEVICE_RELATIONS CompanionControllersList;
+    PUSBPORT_DEVICE_EXTENSION CompanionFdoExtension;
+    PDEVICE_OBJECT * Entry;
+    ULONG ix;
+
+    DPRINT("USBPORT_SynchronizeRootHubCallback: FdoDevice - %p, Usb2FdoDevice - %p\n",
+           FdoDevice,
+           Usb2FdoDevice);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    if (Usb2FdoDevice == NULL &&
+        !(Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2))
+    {
+        /* Not Companion USB11 Controller */
+        USBPORT_DoRootHubCallback(FdoDevice);
+
+        FdoExtension->Flags &= ~USBPORT_FLAG_RH_INIT_CALLBACK;
+        InterlockedCompareExchange(&FdoExtension->RHInitCallBackLock, 0, 1);
+
+        DPRINT("USBPORT_SynchronizeRootHubCallback: exit \n");
+        return;
+    }
+
+    /* USB2 or Companion USB11 */
+
+    DPRINT("USBPORT_SynchronizeRootHubCallback: FdoExtension->Flags - %p\n",
+           FdoExtension->Flags);
+
+    if (!(FdoExtension->Flags & USBPORT_FLAG_COMPANION_HC))
+    {
+        KeWaitForSingleObject(&FdoExtension->ControllerSemaphore,
+                              Executive,
+                              KernelMode,
+                              FALSE,
+                              NULL);
+
+        FdoExtension->Flags |= USBPORT_FLAG_PWR_AND_CHIRP_LOCK;
+
+        if (!(FdoExtension->Flags & (USBPORT_FLAG_HC_SUSPEND |
+                                     USBPORT_FLAG_POWER_AND_CHIRP_OK)))
+        {
+            USBPORT_RootHubPowerAndChirpAllCcPorts(FdoDevice);
+            FdoExtension->Flags |= USBPORT_FLAG_POWER_AND_CHIRP_OK;
+        }
+
+        FdoExtension->Flags &= ~USBPORT_FLAG_PWR_AND_CHIRP_LOCK;
+
+        KeReleaseSemaphore(&FdoExtension->ControllerSemaphore,
+                           LOW_REALTIME_PRIORITY,
+                           1,
+                           FALSE);
+
+        CompanionControllersList = USBPORT_FindCompanionControllers(FdoDevice,
+                                                                    FALSE,
+                                                                    TRUE);
+
+        if (CompanionControllersList)
+        {
+            Entry = &CompanionControllersList->Objects[0];
+
+            for (ix = 0; ix < CompanionControllersList->Count; ++ix)
+            {
+                CompanionFdoExtension = ((*Entry)->DeviceExtension);
+
+                InterlockedCompareExchange(&CompanionFdoExtension->RHInitCallBackLock,
+                                           0,
+                                           1);
+
+                ++Entry;
+            }
+
+            ExFreePoolWithTag(CompanionControllersList, USB_PORT_TAG);
+        }
+
+        USBPORT_DoRootHubCallback(FdoDevice);
+
+        FdoExtension->Flags &= ~USBPORT_FLAG_RH_INIT_CALLBACK;
+        InterlockedCompareExchange(&FdoExtension->RHInitCallBackLock, 0, 1);
+    }
+    else
+    {
+        Usb2FdoExtension = Usb2FdoDevice->DeviceExtension;
+
+        USBPORT_Wait(FdoDevice, 50);
+
+        while (FdoExtension->RHInitCallBackLock)
+        {
+            USBPORT_Wait(FdoDevice, 10);
+
+            Usb2FdoExtension->Flags |= USBPORT_FLAG_RH_INIT_CALLBACK;
+            USBPORT_SignalWorkerThread(Usb2FdoDevice);
+        }
+
+        USBPORT_DoRootHubCallback(FdoDevice);
+
+        FdoExtension->Flags &= ~USBPORT_FLAG_RH_INIT_CALLBACK;
+    }
+
+    DPRINT("USBPORT_SynchronizeRootHubCallback: exit \n");
+}
+
+VOID
+NTAPI
+USBPORT_WorkerThread(IN PVOID StartContext)
+{
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    LARGE_INTEGER OldTime;
+    LARGE_INTEGER NewTime;
+    KIRQL OldIrql;
+
+    DPRINT_CORE("USBPORT_WorkerThread ... \n");
+
+    FdoDevice = StartContext;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    FdoExtension->WorkerThread = KeGetCurrentThread();
+
+    do
+    {
+        KeQuerySystemTime(&OldTime);
+
+        KeWaitForSingleObject(&FdoExtension->WorkerThreadEvent,
+                              Suspended,
+                              KernelMode,
+                              FALSE,
+                              NULL);
+
+        KeQuerySystemTime(&NewTime);
+
+        KeAcquireSpinLock(&FdoExtension->WorkerThreadEventSpinLock, &OldIrql);
+        KeResetEvent(&FdoExtension->WorkerThreadEvent);
+        KeReleaseSpinLock(&FdoExtension->WorkerThreadEventSpinLock, OldIrql);
+        DPRINT_CORE("USBPORT_WorkerThread: run \n");
+
+        if (FdoExtension->MiniPortFlags & USBPORT_MPFLAG_INTERRUPTS_ENABLED)
+        {
+            USBPORT_DoSetPowerD0(FdoDevice);
+
+            if (FdoExtension->Flags & USBPORT_FLAG_RH_INIT_CALLBACK)
+            {
+                PDEVICE_OBJECT USB2FdoDevice = NULL;
+
+                USB2FdoDevice = USBPORT_FindUSB2Controller(FdoDevice);
+                USBPORT_SynchronizeRootHubCallback(FdoDevice, USB2FdoDevice);
+            }
+        }
+
+        USBPORT_WorkerThreadHandler(FdoDevice);
+    }
+    while (!(FdoExtension->Flags & USBPORT_FLAG_WORKER_THREAD_ON));
+
+    PsTerminateSystemThread(0);
+}
+
+NTSTATUS
+NTAPI
+USBPORT_CreateWorkerThread(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    NTSTATUS Status;
+
+    DPRINT("USBPORT_CreateWorkerThread ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    FdoExtension->Flags &= ~USBPORT_FLAG_WORKER_THREAD_ON;
+
+    KeInitializeEvent(&FdoExtension->WorkerThreadEvent,
+                      NotificationEvent,
+                      FALSE);
+
+    Status = PsCreateSystemThread(&FdoExtension->WorkerThreadHandle,
+                                  THREAD_ALL_ACCESS,
+                                  NULL,
+                                  NULL,
+                                  NULL,
+                                  USBPORT_WorkerThread,
+                                  (PVOID)FdoDevice);
+
+    return Status;
+}
+
+VOID
+NTAPI
+USBPORT_SynchronizeControllersStart(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PDEVICE_OBJECT PdoDevice;
+    PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+    PDEVICE_OBJECT USB2FdoDevice = NULL;
+    PUSBPORT_DEVICE_EXTENSION USB2FdoExtension;
+    BOOLEAN IsOn; 
+
+    DPRINT_TIMER("USBPORT_SynchronizeControllersStart: FdoDevice - %p\n",
+                 FdoDevice);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    PdoDevice = FdoExtension->RootHubPdo;
+
+    if (!PdoDevice)
+    {
+        return;
+    }
+
+    PdoExtension = PdoDevice->DeviceExtension;
+
+    if (PdoExtension->RootHubInitCallback == NULL ||
+        FdoExtension->Flags & USBPORT_FLAG_RH_INIT_CALLBACK)
+    {
+        return;
+    }
+
+    DPRINT_TIMER("USBPORT_SynchronizeControllersStart: Flags - %p\n",
+                 FdoExtension->Flags);
+
+    if (FdoExtension->Flags & USBPORT_FLAG_COMPANION_HC)
+    {
+        IsOn = FALSE;
+
+        USB2FdoDevice = USBPORT_FindUSB2Controller(FdoDevice);
+
+        DPRINT_TIMER("USBPORT_SynchronizeControllersStart: USB2FdoDevice - %p\n",
+                     USB2FdoDevice);
+
+        if (USB2FdoDevice)
+        {
+            USB2FdoExtension = USB2FdoDevice->DeviceExtension;
+
+            if (USB2FdoExtension->CommonExtension.PnpStateFlags &
+                USBPORT_PNP_STATE_STARTED)
+            {
+                IsOn = TRUE;
+            }
+        }
+
+        if (!(FdoExtension->Flags & USBPORT_FLAG_NO_HACTION))
+        {
+            goto Start;
+        }
+
+        USB2FdoDevice = NULL;
+    }
+
+    IsOn = TRUE;
+
+  Start:
+
+    if (IsOn &&
+        !InterlockedCompareExchange(&FdoExtension->RHInitCallBackLock, 1, 0))
+    {
+        FdoExtension->Flags |= USBPORT_FLAG_RH_INIT_CALLBACK;
+        USBPORT_SignalWorkerThread(FdoDevice);
+
+        if (USB2FdoDevice)
+        {
+            USB2FdoExtension = USB2FdoDevice->DeviceExtension;
+
+            USB2FdoExtension->Flags |= USBPORT_FLAG_RH_INIT_CALLBACK;
+            USBPORT_SignalWorkerThread(USB2FdoDevice);
+        }
+    }
+
+    DPRINT_TIMER("USBPORT_SynchronizeControllersStart: exit\n");
+}
+
+VOID
+NTAPI
+USBPORT_TimerDpc(IN PRKDPC Dpc,
+                 IN PVOID DeferredContext,
+                 IN PVOID SystemArgument1,
+                 IN PVOID SystemArgument2)
+{
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    LARGE_INTEGER DueTime = {{0, 0}};
+    ULONG TimerFlags;
+    PTIMER_WORK_QUEUE_ITEM IdleQueueItem;
+    KIRQL OldIrql;
+    KIRQL TimerOldIrql;
+
+    DPRINT_TIMER("USBPORT_TimerDpc: Dpc - %p, DeferredContext - %p\n",
+           Dpc,
+           DeferredContext);
+
+    FdoDevice = DeferredContext;
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    KeAcquireSpinLock(&FdoExtension->TimerFlagsSpinLock, &TimerOldIrql);
+
+    TimerFlags = FdoExtension->TimerFlags;
+
+    DPRINT_TIMER("USBPORT_TimerDpc: Flags - %p, TimerFlags - %p\n",
+                 FdoExtension->Flags,
+                 TimerFlags);
+
+    if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND &&
+        FdoExtension->Flags & USBPORT_FLAG_HC_WAKE_SUPPORT &&
+        !(TimerFlags & USBPORT_TMFLAG_HC_RESUME))
+    {
+        KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+        Packet->PollController(FdoExtension->MiniPortExt);
+        KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+    }
+
+    USBPORT_SynchronizeControllersStart(FdoDevice);
+
+    if (TimerFlags & USBPORT_TMFLAG_HC_SUSPENDED)
+    {
+        USBPORT_BadRequestFlush(FdoDevice);
+        goto Exit;
+    }
+
+    KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+
+    if (!(FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND))
+    {
+        Packet->CheckController(FdoExtension->MiniPortExt);
+    }
+
+    KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+
+    if (FdoExtension->Flags & USBPORT_FLAG_HC_POLLING)
+    {
+        KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+        Packet->PollController(FdoExtension->MiniPortExt);
+        KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+    }
+
+    USBPORT_IsrDpcHandler(FdoDevice, FALSE);
+
+    DPRINT_TIMER("USBPORT_TimerDpc: USBPORT_TimeoutAllEndpoints UNIMPLEMENTED.\n");
+    //USBPORT_TimeoutAllEndpoints(FdoDevice);
+    DPRINT_TIMER("USBPORT_TimerDpc: USBPORT_CheckIdleEndpoints UNIMPLEMENTED.\n");
+    //USBPORT_CheckIdleEndpoints(FdoDevice);
+
+    USBPORT_BadRequestFlush(FdoDevice);
+
+    if (FdoExtension->IdleLockCounter > -1 &&
+        !(TimerFlags & USBPORT_TMFLAG_IDLE_QUEUEITEM_ON))
+    {
+        IdleQueueItem = ExAllocatePoolWithTag(NonPagedPool,
+                                              sizeof(TIMER_WORK_QUEUE_ITEM),
+                                              USB_PORT_TAG);
+
+        DPRINT("USBPORT_TimerDpc: IdleLockCounter - %x, IdleQueueItem - %p\n",
+               FdoExtension->IdleLockCounter,
+               IdleQueueItem);
+
+        if (IdleQueueItem)
+        {
+            RtlZeroMemory(IdleQueueItem, sizeof(TIMER_WORK_QUEUE_ITEM));
+
+            IdleQueueItem->WqItem.List.Flink = NULL;
+            IdleQueueItem->WqItem.WorkerRoutine = USBPORT_DoIdleNotificationCallback;
+            IdleQueueItem->WqItem.Parameter = IdleQueueItem;
+
+            IdleQueueItem->FdoDevice = FdoDevice;
+            IdleQueueItem->Context = 0;
+
+            FdoExtension->TimerFlags |= USBPORT_TMFLAG_IDLE_QUEUEITEM_ON;
+
+            ExQueueWorkItem(&IdleQueueItem->WqItem, CriticalWorkQueue);
+        }
+    }
+
+Exit:
+
+    KeReleaseSpinLock(&FdoExtension->TimerFlagsSpinLock, TimerOldIrql);
+
+    if (TimerFlags & USBPORT_TMFLAG_TIMER_QUEUED)
+    {
+        DueTime.QuadPart -= FdoExtension->TimerValue * 10000 +
+                            (KeQueryTimeIncrement() - 1);
+
+        KeSetTimer(&FdoExtension->TimerObject,
+                   DueTime,
+                   &FdoExtension->TimerDpc);
+    }
+
+    DPRINT_TIMER("USBPORT_TimerDpc: exit\n");
+}
+
+BOOLEAN
+NTAPI
+USBPORT_StartTimer(IN PDEVICE_OBJECT FdoDevice,
+                   IN ULONG Time)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    LARGE_INTEGER DueTime = {{0, 0}};
+    ULONG TimeIncrement;
+    BOOLEAN Result;
+
+    DPRINT_TIMER("USBPORT_StartTimer: FdoDevice - %p, Time - %x\n",
+           FdoDevice,
+           Time);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    TimeIncrement = KeQueryTimeIncrement();
+
+    FdoExtension->TimerFlags |= USBPORT_TMFLAG_TIMER_QUEUED;
+    FdoExtension->TimerValue = Time;
+
+    KeInitializeTimer(&FdoExtension->TimerObject);
+    KeInitializeDpc(&FdoExtension->TimerDpc, USBPORT_TimerDpc, FdoDevice);
+
+    DueTime.QuadPart -= 10000 * Time + (TimeIncrement - 1);
+
+    Result = KeSetTimer(&FdoExtension->TimerObject,
+                        DueTime,
+                        &FdoExtension->TimerDpc);
+
+    return Result;
+}
+
+PUSBPORT_COMMON_BUFFER_HEADER
+NTAPI
+USBPORT_AllocateCommonBuffer(IN PDEVICE_OBJECT FdoDevice,
+                             IN SIZE_T BufferLength)
+{
+    PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer = NULL;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PDMA_ADAPTER DmaAdapter;
+    PDMA_OPERATIONS DmaOperations;
+    SIZE_T HeaderSize;
+    ULONG Length = 0;
+    ULONG LengthPadded;
+    PHYSICAL_ADDRESS LogicalAddress;
+    ULONG_PTR BaseVA;
+    ULONG_PTR StartBufferVA;
+    ULONG_PTR StartBufferPA;
+
+    DPRINT("USBPORT_AllocateCommonBuffer: FdoDevice - %p, BufferLength - %p\n",
+           FdoDevice,
+           BufferLength);
+
+    if (BufferLength == 0)
+        goto Exit;
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    DmaAdapter = FdoExtension->DmaAdapter;
+    DmaOperations = DmaAdapter->DmaOperations;
+
+    HeaderSize = sizeof(USBPORT_COMMON_BUFFER_HEADER);
+    Length = ROUND_TO_PAGES(BufferLength + HeaderSize);
+    LengthPadded = Length - (BufferLength + HeaderSize);
+
+    BaseVA = (ULONG_PTR)DmaOperations->AllocateCommonBuffer(DmaAdapter,
+                                                            Length,
+                                                            &LogicalAddress,
+                                                            TRUE);
+
+    if (!BaseVA)
+        goto Exit;
+
+    StartBufferVA = BaseVA & ~(PAGE_SIZE - 1);
+    StartBufferPA = LogicalAddress.LowPart & ~(PAGE_SIZE - 1);
+
+    HeaderBuffer = (PUSBPORT_COMMON_BUFFER_HEADER)(StartBufferVA +
+                                                   BufferLength +
+                                                   LengthPadded);
+
+    HeaderBuffer->Length = Length;
+    HeaderBuffer->BaseVA = BaseVA;
+    HeaderBuffer->LogicalAddress = LogicalAddress;
+
+    HeaderBuffer->BufferLength = BufferLength + LengthPadded;
+    HeaderBuffer->VirtualAddress = StartBufferVA;
+    HeaderBuffer->PhysicalAddress = StartBufferPA;
+
+    RtlZeroMemory((PVOID)StartBufferVA, BufferLength + LengthPadded);
+
+Exit:
+    return HeaderBuffer;
+}
+
+VOID
+NTAPI
+USBPORT_FreeCommonBuffer(IN PDEVICE_OBJECT FdoDevice,
+                         IN PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PDMA_ADAPTER DmaAdapter;
+    PDMA_OPERATIONS DmaOperations;
+
+    DPRINT("USBPORT_FreeCommonBuffer: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    DmaAdapter = FdoExtension->DmaAdapter;
+    DmaOperations = DmaAdapter->DmaOperations;
+
+    DmaOperations->FreeCommonBuffer(FdoExtension->DmaAdapter,
+                                    HeaderBuffer->Length,
+                                    HeaderBuffer->LogicalAddress,
+                                    (PVOID)HeaderBuffer->VirtualAddress,
+                                    TRUE);
+}
+
+PUSBPORT_MINIPORT_INTERFACE
+NTAPI
+USBPORT_FindMiniPort(IN PDRIVER_OBJECT DriverObject)
+{
+    KIRQL OldIrql;
+    PLIST_ENTRY List;
+    PUSBPORT_MINIPORT_INTERFACE MiniPortInterface;
+    BOOLEAN IsFound = FALSE;
+
+    DPRINT("USBPORT_FindMiniPort: ... \n");
+
+    KeAcquireSpinLock(&USBPORT_SpinLock, &OldIrql);
+
+    for (List = USBPORT_MiniPortDrivers.Flink;
+         List != &USBPORT_MiniPortDrivers;
+         List = List->Flink)
+    {
+        MiniPortInterface = CONTAINING_RECORD(List,
+                                              USBPORT_MINIPORT_INTERFACE,
+                                              DriverLink);
+
+        if (MiniPortInterface->DriverObject == DriverObject)
+        {
+            DPRINT("USBPORT_FindMiniPort: find MiniPortInterface - %p\n",
+                   MiniPortInterface);
+
+            IsFound = TRUE;
+            break;
+        }
+    }
+
+    KeReleaseSpinLock(&USBPORT_SpinLock, OldIrql);
+
+    if (IsFound)
+        return MiniPortInterface;
+    else
+        return NULL;
+    
+}
+
+NTSTATUS
+NTAPI
+USBPORT_AddDevice(IN PDRIVER_OBJECT DriverObject,
+                  IN PDEVICE_OBJECT PhysicalDeviceObject)
+{
+    NTSTATUS Status;
+    PUSBPORT_MINIPORT_INTERFACE MiniPortInterface;
+    ULONG DeviceNumber = 0;
+    WCHAR CharDeviceName[64];
+    UNICODE_STRING DeviceName;
+    PDEVICE_OBJECT DeviceObject;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_COMMON_DEVICE_EXTENSION FdoCommonExtension;
+    PDEVICE_OBJECT LowerDevice;
+    ULONG Length;
+
+    DPRINT("USBPORT_AddDevice: DriverObject - %p, PhysicalDeviceObject - %p\n",
+           DriverObject,
+           PhysicalDeviceObject);
+
+    MiniPortInterface = USBPORT_FindMiniPort(DriverObject);
+
+    if (!MiniPortInterface)
+    {
+        DPRINT("USBPORT_AddDevice: USBPORT_FindMiniPort not found MiniPortInterface\n");
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    while (TRUE)
+    {
+        /* Construct device name */
+        RtlStringCbPrintfW(CharDeviceName,
+                           sizeof(CharDeviceName),
+                           L"\\Device\\USBFDO-%d",
+                           DeviceNumber);
+
+        RtlInitUnicodeString(&DeviceName, CharDeviceName);
+
+        Length = sizeof(USBPORT_DEVICE_EXTENSION) +
+                 MiniPortInterface->Packet.MiniPortExtensionSize;
+
+        /* Create device */
+        Status = IoCreateDevice(DriverObject,
+                                Length,
+                                &DeviceName,
+                                FILE_DEVICE_CONTROLLER,
+                                0,
+                                FALSE,
+                                &DeviceObject);
+
+        /* Check for success */
+        if (NT_SUCCESS(Status)) break;
+
+        /* Is there a device object with that same name */
+        if ((Status == STATUS_OBJECT_NAME_EXISTS) ||
+            (Status == STATUS_OBJECT_NAME_COLLISION))
+        {
+            /* Try the next name */
+            DeviceNumber++;
+            continue;
+        }
+
+        /* Bail out on other errors */
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("USBPORT_AddDevice: failed to create %wZ, Status %x\n",
+                    &DeviceName,
+                    Status);
+
+            return Status;
+        }
+    }
+
+    DPRINT("USBPORT_AddDevice: created device %p <%wZ>, Status %x\n",
+           DeviceObject,
+           &DeviceName,
+           Status);
+
+    FdoExtension = DeviceObject->DeviceExtension;
+    FdoCommonExtension = &FdoExtension->CommonExtension;
+
+    RtlZeroMemory(FdoExtension, sizeof(USBPORT_DEVICE_EXTENSION));
+
+    FdoCommonExtension->SelfDevice = DeviceObject;
+    FdoCommonExtension->LowerPdoDevice = PhysicalDeviceObject;
+    FdoCommonExtension->IsPDO = FALSE;
+
+    LowerDevice = IoAttachDeviceToDeviceStack(DeviceObject,
+                                              PhysicalDeviceObject);
+
+    FdoCommonExtension->LowerDevice = LowerDevice;
+
+    FdoCommonExtension->DevicePowerState = PowerDeviceD3;
+
+    FdoExtension->MiniPortExt = (PVOID)((ULONG_PTR)FdoExtension +
+                                        sizeof(USBPORT_DEVICE_EXTENSION));
+
+    FdoExtension->MiniPortInterface = MiniPortInterface;
+    FdoExtension->FdoNameNumber = DeviceNumber;
+
+    KeInitializeSemaphore(&FdoExtension->DeviceSemaphore, 1, 1);
+    KeInitializeSemaphore(&FdoExtension->ControllerSemaphore, 1, 1);
+
+    InitializeListHead(&FdoExtension->EndpointList);
+    InitializeListHead(&FdoExtension->DoneTransferList);
+    InitializeListHead(&FdoExtension->WorkerList);
+    InitializeListHead(&FdoExtension->EpStateChangeList);
+    InitializeListHead(&FdoExtension->MapTransferList);
+    InitializeListHead(&FdoExtension->DeviceHandleList);
+    InitializeListHead(&FdoExtension->IdleIrpList);
+    InitializeListHead(&FdoExtension->BadRequestList);
+    InitializeListHead(&FdoExtension->EndpointClosedList);
+
+    DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+
+    return Status;
+}
+
+VOID
+NTAPI
+USBPORT_Unload(IN PDRIVER_OBJECT DriverObject)
+{
+    PUSBPORT_MINIPORT_INTERFACE MiniPortInterface;
+
+    DPRINT1("USBPORT_Unload: FIXME!\n");
+
+    MiniPortInterface = USBPORT_FindMiniPort(DriverObject);
+
+    if (!MiniPortInterface)
+    {
+        DPRINT("USBPORT_Unload: CRITICAL ERROR!!! USBPORT_FindMiniPort not found MiniPortInterface\n");
+        KeBugCheckEx(BUGCODE_USB_DRIVER, 1, 0, 0, 0);
+    }
+
+    DPRINT1("USBPORT_Unload: UNIMPLEMENTED. FIXME. \n");
+    //MiniPortInterface->DriverUnload(DriverObject); // Call MiniPort _HCI_Unload
+}
+
+ULONG
+NTAPI
+USBPORT_MiniportCompleteTransfer(IN PVOID MiniPortExtension,
+                                 IN PVOID MiniPortEndpoint,
+                                 IN PVOID TransferParameters,
+                                 IN USBD_STATUS USBDStatus,
+                                 IN ULONG TransferLength)
+{
+    PUSBPORT_TRANSFER Transfer;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+
+    DPRINT_CORE("USBPORT_MiniportCompleteTransfer: USBDStatus - %x, TransferLength - %x\n",
+                USBDStatus,
+                TransferLength);
+
+    Transfer = CONTAINING_RECORD(TransferParameters,
+                                 USBPORT_TRANSFER,
+                                 TransferParameters);
+
+    FdoDevice = Transfer->Endpoint->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    Transfer->CompletedTransferLen = TransferLength;
+
+    RemoveEntryList(&Transfer->TransferLink);
+
+    Transfer->USBDStatus = USBDStatus;
+
+    ExInterlockedInsertTailList(&FdoExtension->DoneTransferList,
+                                &Transfer->TransferLink,
+                                &FdoExtension->DoneTransferSpinLock);
+
+    return KeInsertQueueDpc(&FdoExtension->TransferFlushDpc, NULL, NULL);
+}
+
+ULONG
+NTAPI
+USBPORT_CompleteIsoTransfer(IN PVOID MiniPortExtension,
+                            IN PVOID MiniPortEndpoint,
+                            IN PVOID TransferParameters,
+                            IN ULONG TransferLength)
+{
+    DPRINT1("USBPORT_CompleteIsoTransfer: UNIMPLEMENTED. FIXME.\n");
+    return 0;
+}
+
+VOID
+NTAPI
+USBPORT_AsyncTimerDpc(IN PRKDPC Dpc,
+                      IN PVOID DeferredContext,
+                      IN PVOID SystemArgument1,
+                      IN PVOID SystemArgument2)
+{
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_ASYNC_CALLBACK_DATA AsyncCallbackData;
+
+    DPRINT("USBPORT_AsyncTimerDpc: ... \n");
+
+    AsyncCallbackData = DeferredContext;
+    FdoDevice = AsyncCallbackData->FdoDevice;
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    (*AsyncCallbackData->CallbackFunction)(FdoExtension->MiniPortExt,
+                                           &AsyncCallbackData->CallbackContext);
+
+    ExFreePoolWithTag(AsyncCallbackData, USB_PORT_TAG);
+}
+
+ULONG
+NTAPI
+USBPORT_RequestAsyncCallback(IN PVOID Context,
+                             IN ULONG TimerValue,
+                             IN PVOID Buffer,
+                             IN SIZE_T Length,
+                             IN ASYNC_TIMER_CALLBACK * Callback)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_ASYNC_CALLBACK_DATA AsyncCallbackData;
+    LARGE_INTEGER DueTime = {{0, 0}};
+
+    DPRINT("USBPORT_RequestAsyncCallback: ... \n");
+
+    FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)Context -
+                                               sizeof(USBPORT_DEVICE_EXTENSION));
+
+    FdoDevice = FdoExtension->CommonExtension.SelfDevice;
+
+    AsyncCallbackData = ExAllocatePoolWithTag(NonPagedPool,
+                                              sizeof(USBPORT_ASYNC_CALLBACK_DATA) + Length,
+                                              USB_PORT_TAG);
+
+    if (!AsyncCallbackData)
+    {
+        DPRINT1("USBPORT_RequestAsyncCallback: Not allocated AsyncCallbackData!\n");
+        return 0;
+    }
+
+    RtlZeroMemory(AsyncCallbackData,
+                  sizeof(USBPORT_ASYNC_CALLBACK_DATA) + Length);
+
+    if (Length)
+    {
+        RtlCopyMemory(&AsyncCallbackData->CallbackContext, Buffer, Length);
+    }
+
+    AsyncCallbackData->FdoDevice = FdoDevice;
+    AsyncCallbackData->CallbackFunction = Callback;
+
+    KeInitializeTimer(&AsyncCallbackData->AsyncTimer);
+
+    KeInitializeDpc(&AsyncCallbackData->AsyncTimerDpc,
+                    USBPORT_AsyncTimerDpc,
+                    AsyncCallbackData);
+
+    DueTime.QuadPart -= (KeQueryTimeIncrement() - 1) + 10000 * TimerValue;
+
+    KeSetTimer(&AsyncCallbackData->AsyncTimer,
+               DueTime,
+               &AsyncCallbackData->AsyncTimerDpc);
+
+    return 0;
+}
+
+PVOID
+NTAPI
+USBPORT_GetMappedVirtualAddress(IN PVOID PhysicalAddress,
+                                IN PVOID MiniPortExtension,
+                                IN PVOID MiniPortEndpoint)
+{
+    PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer;
+    PUSBPORT_ENDPOINT Endpoint;
+    ULONG Offset;
+    ULONG_PTR VirtualAddress;
+
+    DPRINT_CORE("USBPORT_GetMappedVirtualAddress ... \n");
+
+    Endpoint = (PUSBPORT_ENDPOINT)((ULONG_PTR)MiniPortEndpoint -
+                                   sizeof(USBPORT_ENDPOINT));
+
+    if (!Endpoint)
+    {
+        ASSERT(FALSE);
+    }
+
+    HeaderBuffer = Endpoint->HeaderBuffer;
+
+    Offset = (ULONG_PTR)PhysicalAddress - HeaderBuffer->PhysicalAddress;
+    VirtualAddress = HeaderBuffer->VirtualAddress + Offset;
+
+    return (PVOID)VirtualAddress;
+}
+
+ULONG
+NTAPI
+USBPORT_InvalidateEndpoint(IN PVOID Context1,
+                           IN PVOID Context2)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_ENDPOINT Endpoint;
+
+    DPRINT_CORE("USBPORT_InvalidateEndpoint: ... \n");
+
+    FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)Context1 -
+                                               sizeof(USBPORT_DEVICE_EXTENSION));
+
+    FdoDevice = FdoExtension->CommonExtension.SelfDevice;
+
+    Endpoint = (PUSBPORT_ENDPOINT)((ULONG_PTR)Context2 -
+                                   sizeof(USBPORT_ENDPOINT));
+
+    if (Context2)
+    {
+        USBPORT_InvalidateEndpointHandler(FdoDevice,
+                                          Endpoint,
+                                          INVALIDATE_ENDPOINT_ONLY);
+    }
+    else
+    {
+        USBPORT_InvalidateEndpointHandler(FdoDevice,
+                                          NULL,
+                                          INVALIDATE_ENDPOINT_ONLY);
+    }
+
+    return 0;
+}
+
+VOID
+NTAPI
+USBPORT_CompleteTransfer(IN PURB Urb,
+                         IN USBD_STATUS TransferStatus)
+{
+    struct _URB_CONTROL_TRANSFER *UrbTransfer;
+    PUSBPORT_TRANSFER Transfer;
+    NTSTATUS Status;
+    PIRP Irp;
+    KIRQL OldIrql;
+    PRKEVENT Event;
+    BOOLEAN WriteToDevice;
+    BOOLEAN IsFlushSuccess;
+    PMDL Mdl;
+    ULONG_PTR CurrentVa;
+    SIZE_T TransferLength;
+    PUSBPORT_ENDPOINT Endpoint;
+    PDEVICE_OBJECT FdoDevice;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PDMA_OPERATIONS DmaOperations;
+
+    DPRINT("USBPORT_CompleteTransfer: Urb - %p, TransferStatus - %X\n",
+           Urb,
+           TransferStatus);
+
+    UrbTransfer = &Urb->UrbControlTransfer;
+    Transfer = UrbTransfer->hca.Reserved8[0];
+
+    Transfer->USBDStatus = TransferStatus;
+    Status = USBPORT_USBDStatusToNtStatus(Urb, TransferStatus);
+
+    UrbTransfer->TransferBufferLength = Transfer->CompletedTransferLen;
+
+    if (Transfer->Flags & TRANSFER_FLAG_DMA_MAPPED)
+    {
+        Endpoint = Transfer->Endpoint;
+        FdoDevice = Endpoint->FdoDevice;
+        FdoExtension = FdoDevice->DeviceExtension;
+        DmaOperations = FdoExtension->DmaAdapter->DmaOperations;
+
+        WriteToDevice = Transfer->Direction == USBPORT_DMA_DIRECTION_TO_DEVICE;
+        Mdl = UrbTransfer->TransferBufferMDL;
+        CurrentVa = (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
+        TransferLength = UrbTransfer->TransferBufferLength;
+
+        IsFlushSuccess = DmaOperations->FlushAdapterBuffers(FdoExtension->DmaAdapter,
+                                                            Mdl,
+                                                            Transfer->MapRegisterBase,
+                                                            (PVOID)CurrentVa,
+                                                            TransferLength,
+                                                            WriteToDevice);
+
+        if (!IsFlushSuccess)
+        {
+            DPRINT("USBPORT_CompleteTransfer: no FlushAdapterBuffers !!!\n");
+            ASSERT(FALSE);
+        }
+
+        KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+
+        DmaOperations->FreeMapRegisters(FdoExtension->DmaAdapter,
+                                        Transfer->MapRegisterBase,
+                                        Transfer->NumberOfMapRegisters);
+
+        KeLowerIrql(OldIrql);
+    }
+
+    if (Urb->UrbHeader.UsbdFlags & USBD_FLAG_ALLOCATED_MDL)
+    {
+        IoFreeMdl(Transfer->TransferBufferMDL);
+        Urb->UrbHeader.UsbdFlags |= ~USBD_FLAG_ALLOCATED_MDL;
+    }
+
+    Urb->UrbControlTransfer.hca.Reserved8[0] = NULL;
+    Urb->UrbHeader.UsbdFlags |= ~USBD_FLAG_ALLOCATED_TRANSFER;
+
+    Irp = Transfer->Irp;
+
+    if (Irp)
+    {
+        if (!NT_SUCCESS(Status))
+        {
+            //DbgBreakPoint();
+            DPRINT1("USBPORT_CompleteTransfer: Irp - %p complete with Status - %lx\n",
+                    Irp,
+                    Status);
+
+            USBPORT_DumpingURB(Urb);
+        }
+
+        Irp->IoStatus.Status = Status;
+        Irp->IoStatus.Information = 0;
+
+        KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        KeLowerIrql(OldIrql);
+    }
+
+    Event = Transfer->Event;
+
+    if (Event)
+    {
+        KeSetEvent(Event, EVENT_INCREMENT, FALSE);
+    }
+
+    ExFreePoolWithTag(Transfer, USB_PORT_TAG);
+
+    DPRINT_CORE("USBPORT_CompleteTransfer: exit\n");
+}
+
+IO_ALLOCATION_ACTION
+NTAPI
+USBPORT_MapTransfer(IN PDEVICE_OBJECT FdoDevice,
+                    IN PIRP Irp,
+                    IN PVOID MapRegisterBase,
+                    IN PVOID Context)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PDMA_ADAPTER DmaAdapter;
+    PUSBPORT_TRANSFER Transfer;
+    PURB Urb;
+    PUSBPORT_ENDPOINT Endpoint;
+    PMDL Mdl;
+    ULONG_PTR CurrentVa;
+    PUSBPORT_SCATTER_GATHER_LIST sgList;
+    SIZE_T CurrentLength;
+    ULONG ix;
+    BOOLEAN WriteToDevice;
+    PHYSICAL_ADDRESS PhAddr = {{0, 0}};
+    PHYSICAL_ADDRESS PhAddress = {{0, 0}};
+    SIZE_T TransferLength;
+    SIZE_T SgCurrentLength;
+    SIZE_T ElementLength;
+    PUSBPORT_DEVICE_HANDLE DeviceHandle;
+    PDMA_OPERATIONS DmaOperations;
+
+    DPRINT_CORE("USBPORT_MapTransfer: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    DmaAdapter = FdoExtension->DmaAdapter;
+    DmaOperations = DmaAdapter->DmaOperations;
+
+    Transfer = Context;
+
+    Urb = Transfer->Urb;
+    Endpoint = Transfer->Endpoint;
+    TransferLength = Transfer->TransferParameters.TransferBufferLength;
+
+    Mdl = Urb->UrbControlTransfer.TransferBufferMDL;
+    CurrentVa = (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
+
+    Transfer->SgList.CurrentVa = CurrentVa;
+    Transfer->SgList.MappedSystemVa = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
+
+    sgList = &Transfer->SgList;
+    sgList->Flags = 0;
+
+    Transfer->MapRegisterBase = MapRegisterBase;
+
+    ix = 0;
+    CurrentLength = 0;
+
+    do
+    {
+        WriteToDevice = Transfer->Direction == USBPORT_DMA_DIRECTION_TO_DEVICE;
+        ASSERT(Transfer->Direction != 0);
+
+        PhAddress = DmaOperations->MapTransfer(DmaAdapter,
+                                               Mdl,
+                                               MapRegisterBase,
+                                               (PVOID)CurrentVa,
+                                               &TransferLength,
+                                               WriteToDevice);
+
+        DPRINT_CORE("USBPORT_MapTransfer: PhAddress.LowPart - %p, PhAddress.HighPart - %x, TransferLength - %x\n",
+               PhAddress.LowPart,
+               PhAddress.HighPart,
+               TransferLength);
+
+        PhAddress.HighPart = 0;
+        SgCurrentLength = TransferLength;
+
+        do
+        {
+            ElementLength = 0x1000 - (PhAddress.LowPart & 0xFFF);
+
+            if (ElementLength > SgCurrentLength)
+                ElementLength = SgCurrentLength;
+
+            DPRINT_CORE("USBPORT_MapTransfer: PhAddress.LowPart - %p, HighPart - %x, ElementLength - %x\n",
+                   PhAddress.LowPart,
+                   PhAddress.HighPart,
+                   ElementLength);
+
+            sgList->SgElement[ix].SgPhysicalAddress = PhAddress;
+            sgList->SgElement[ix].SgTransferLength = ElementLength;
+            sgList->SgElement[ix].SgOffset = CurrentLength +
+                                             (TransferLength - SgCurrentLength);
+
+            PhAddress.LowPart += ElementLength;
+            SgCurrentLength -= ElementLength;
+
+            ++ix;
+        }
+        while (SgCurrentLength);
+
+        if ((PhAddr.LowPart == PhAddress.LowPart) &&
+            (PhAddr.HighPart == PhAddress.HighPart))
+        {
+            ASSERT(FALSE);
+        }
+
+        PhAddr = PhAddress;
+
+        CurrentLength += TransferLength;
+        CurrentVa += TransferLength;
+
+        TransferLength = Transfer->TransferParameters.TransferBufferLength -
+                         CurrentLength;
+    }
+    while (CurrentLength != Transfer->TransferParameters.TransferBufferLength);
+
+    Transfer->SgList.SgElementCount = ix;
+    Transfer->Flags |= TRANSFER_FLAG_DMA_MAPPED;
+
+    ASSERT(Transfer->TransferParameters.TransferBufferLength <=
+           Endpoint->EndpointProperties.MaxTransferSize);
+
+    KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
+    InsertTailList(&Endpoint->TransferList, &Transfer->TransferLink);
+    KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
+
+    DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
+    InterlockedDecrement(&DeviceHandle->DeviceHandleLock);
+
+    if (USBPORT_EndpointWorker(Endpoint, 0))
+    {
+        USBPORT_InvalidateEndpointHandler(FdoDevice,
+                                          Endpoint,
+                                          INVALIDATE_ENDPOINT_WORKER_THREAD);
+    }
+
+    return DeallocateObjectKeepRegisters;
+}
+
+VOID
+NTAPI
+USBPORT_FlushMapTransfers(IN PDEVICE_OBJECT FdoDevice)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PLIST_ENTRY MapTransferList;
+    PUSBPORT_TRANSFER Transfer;
+    ULONG NumMapRegisters;
+    PMDL Mdl;
+    SIZE_T TransferBufferLength;
+    ULONG_PTR VirtualAddr;
+    KIRQL OldIrql;
+    NTSTATUS Status;
+    PDMA_OPERATIONS DmaOperations;
+
+    DPRINT_CORE("USBPORT_FlushMapTransfers: ... \n");
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    DmaOperations = FdoExtension->DmaAdapter->DmaOperations;
+
+    KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+
+    while (TRUE)
+    {
+        MapTransferList = &FdoExtension->MapTransferList;
+
+        if (IsListEmpty(&FdoExtension->MapTransferList))
+        {
+            KeLowerIrql(OldIrql);
+            return;
+        }
+
+        Transfer = CONTAINING_RECORD(MapTransferList->Flink,
+                                     USBPORT_TRANSFER,
+                                     TransferLink);
+
+        RemoveHeadList(MapTransferList);
+
+        Mdl = Transfer->Urb->UrbControlTransfer.TransferBufferMDL;
+        TransferBufferLength = Transfer->TransferParameters.TransferBufferLength;
+        VirtualAddr = (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
+
+        NumMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddr,
+                                                         TransferBufferLength);
+
+        Transfer->NumberOfMapRegisters = NumMapRegisters;
+
+        Status = DmaOperations->AllocateAdapterChannel(FdoExtension->DmaAdapter,
+                                                       FdoDevice,
+                                                       NumMapRegisters,
+                                                       USBPORT_MapTransfer,
+                                                       Transfer);
+
+        if (!NT_SUCCESS(Status))
+            ASSERT(FALSE);
+    }
+
+    KeLowerIrql(OldIrql);
+}
+
+USBD_STATUS
+NTAPI
+USBPORT_AllocateTransfer(IN PDEVICE_OBJECT FdoDevice,
+                         IN PURB Urb,
+                         IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+                         IN PIRP Irp,
+                         IN PRKEVENT Event)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    SIZE_T TransferLength;
+    PMDL Mdl;
+    ULONG_PTR VirtualAddr;
+    ULONG PagesNeed = 0;
+    SIZE_T PortTransferLength;
+    SIZE_T FullTransferLength;
+    PUSBPORT_TRANSFER Transfer;
+    PUSBPORT_PIPE_HANDLE PipeHandle;
+    USBD_STATUS USBDStatus;
+
+    DPRINT_CORE("USBPORT_AllocateTransfer: FdoDevice - %p, Urb - %p, DeviceHandle - %p, Irp - %p, Event - %p\n",
+           FdoDevice,
+           Urb,
+           DeviceHandle,
+           Irp,
+           Event);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    TransferLength = Urb->UrbControlTransfer.TransferBufferLength;
+    PipeHandle = Urb->UrbControlTransfer.PipeHandle;
+
+    if (TransferLength)
+    {
+        Mdl = Urb->UrbControlTransfer.TransferBufferMDL;
+        VirtualAddr = (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
+
+        PagesNeed = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddr,
+                                                   TransferLength);
+    }
+
+    if (Urb->UrbHeader.Function == URB_FUNCTION_ISOCH_TRANSFER)
+    {
+        DPRINT1("USBPORT_AllocateTransfer: ISOCH_TRANSFER UNIMPLEMENTED. FIXME.\n");
+    }
+
+    PortTransferLength = sizeof(USBPORT_TRANSFER) +
+                         PagesNeed * sizeof(USBPORT_SCATTER_GATHER_ELEMENT);
+
+    FullTransferLength = PortTransferLength +
+                         FdoExtension->MiniPortInterface->Packet.MiniPortTransferSize;
+
+    Transfer = ExAllocatePoolWithTag(NonPagedPool,
+                                     FullTransferLength,
+                                     USB_PORT_TAG);
+
+    if (Transfer)
+    {
+        RtlZeroMemory(Transfer, FullTransferLength);
+
+        Transfer->Irp = Irp;
+        Transfer->Urb = Urb;
+        Transfer->Endpoint = PipeHandle->Endpoint;
+        Transfer->Event = Event;
+        Transfer->PortTransferLength = PortTransferLength;
+        Transfer->FullTransferLength = FullTransferLength;
+
+        Transfer->MiniportTransfer = (PVOID)((ULONG_PTR)Transfer +
+                                             PortTransferLength);
+
+        Urb->UrbControlTransfer.hca.Reserved8[0] = Transfer;
+        Urb->UrbHeader.UsbdFlags |= USBD_FLAG_ALLOCATED_TRANSFER;
+
+        USBDStatus = USBD_STATUS_SUCCESS;
+    }
+    else
+    {
+        USBDStatus = USBD_STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    DPRINT_CORE("USBPORT_AllocateTransfer: return USBDStatus - %x\n",
+                USBDStatus);
+
+    return USBDStatus;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_Dispatch(IN PDEVICE_OBJECT DeviceObject,
+                 IN PIRP Irp)
+{
+    PUSBPORT_COMMON_DEVICE_EXTENSION DeviceExtension;
+    PIO_STACK_LOCATION IoStack;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    DeviceExtension = DeviceObject->DeviceExtension;
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    if (DeviceExtension->PnpStateFlags & USBPORT_PNP_STATE_FAILED)
+    {
+        DPRINT1("USBPORT_Dispatch: USBPORT_PNP_STATE_FAILED\n");
+        DbgBreakPoint();
+    }
+
+    switch (IoStack->MajorFunction)
+    {
+        case IRP_MJ_DEVICE_CONTROL:
+            if (DeviceExtension->IsPDO)
+            {
+                DPRINT("USBPORT_Dispatch: PDO IRP_MJ_DEVICE_CONTROL. Major - %d, Minor - %d\n",
+                       IoStack->MajorFunction,
+                       IoStack->MinorFunction);
+
+                Status = USBPORT_PdoDeviceControl(DeviceObject, Irp);
+            }
+            else
+            {
+                DPRINT("USBPORT_Dispatch: FDO IRP_MJ_DEVICE_CONTROL. Major - %d, Minor - %d\n",
+                       IoStack->MajorFunction,
+                       IoStack->MinorFunction);
+
+                Status = USBPORT_FdoDeviceControl(DeviceObject, Irp);
+            }
+
+            break;
+
+        case IRP_MJ_INTERNAL_DEVICE_CONTROL:
+            if (DeviceExtension->IsPDO)
+            {
+                DPRINT("USBPORT_Dispatch: PDO IRP_MJ_INTERNAL_DEVICE_CONTROL. Major - %d, Minor - %d\n",
+                       IoStack->MajorFunction,
+                       IoStack->MinorFunction);
+
+                Status = USBPORT_PdoInternalDeviceControl(DeviceObject, Irp);
+            }
+            else
+            {
+                DPRINT("USBPORT_Dispatch: FDO IRP_MJ_INTERNAL_DEVICE_CONTROL. Major - %d, Minor - %d\n",
+                       IoStack->MajorFunction,
+                       IoStack->MinorFunction);
+
+                Status = USBPORT_FdoInternalDeviceControl(DeviceObject, Irp);
+            }
+
+            break;
+
+        case IRP_MJ_POWER:
+            if (DeviceExtension->IsPDO)
+            {
+                DPRINT("USBPORT_Dispatch: PDO IRP_MJ_POWER. Major - %d, Minor - %d\n",
+                       IoStack->MajorFunction,
+                       IoStack->MinorFunction);
+
+                Status = USBPORT_PdoPower(DeviceObject, Irp);
+            }
+            else
+            {
+                DPRINT("USBPORT_Dispatch: FDO IRP_MJ_POWER. Major - %d, Minor - %d\n",
+                       IoStack->MajorFunction,
+                       IoStack->MinorFunction);
+
+                Status = USBPORT_FdoPower(DeviceObject, Irp);
+            }
+
+            break;
+
+        case IRP_MJ_SYSTEM_CONTROL:
+            if (DeviceExtension->IsPDO)
+            {
+                DPRINT("USBPORT_Dispatch: PDO IRP_MJ_SYSTEM_CONTROL. Major - %d, Minor - %d\n",
+                       IoStack->MajorFunction,
+                       IoStack->MinorFunction);
+
+                Irp->IoStatus.Status = Status;
+                IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            }
+            else
+            {
+                DPRINT("USBPORT_Dispatch: FDO IRP_MJ_SYSTEM_CONTROL. Major - %d, Minor - %d\n",
+                       IoStack->MajorFunction,
+                       IoStack->MinorFunction);
+
+                IoSkipCurrentIrpStackLocation(Irp);
+                Status = IoCallDriver(DeviceExtension->LowerDevice, Irp);
+            }
+
+            break;
+
+        case IRP_MJ_PNP:
+            if (DeviceExtension->IsPDO)
+            {
+                DPRINT("USBPORT_Dispatch: PDO IRP_MJ_PNP. Major - %d, Minor - %d\n",
+                       IoStack->MajorFunction,
+                       IoStack->MinorFunction);
+
+                Status = USBPORT_PdoPnP(DeviceObject, Irp);
+            }
+            else
+            {
+                DPRINT("USBPORT_Dispatch: FDO IRP_MJ_PNP. Major - %d, Minor - %d\n",
+                       IoStack->MajorFunction,
+                       IoStack->MinorFunction);
+
+                Status = USBPORT_FdoPnP(DeviceObject, Irp);
+            }
+
+            break;
+
+        case IRP_MJ_CREATE:
+        case IRP_MJ_CLOSE:
+            DPRINT("USBPORT_Dispatch: IRP_MJ_CREATE | IRP_MJ_CLOSE\n");
+            Irp->IoStatus.Status = Status;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            break;
+
+        default:
+            if (DeviceExtension->IsPDO)
+            {
+                DPRINT("USBPORT_Dispatch: PDO unhandled IRP_MJ_???. Major - %d, Minor - %d\n",
+                       IoStack->MajorFunction,
+                       IoStack->MinorFunction);
+            }
+            else
+            {
+                DPRINT("USBPORT_Dispatch: FDO unhandled IRP_MJ_???. Major - %d, Minor - %d\n",
+                       IoStack->MajorFunction,
+                       IoStack->MinorFunction);
+            }
+
+            Status = STATUS_INVALID_DEVICE_REQUEST;
+            Irp->IoStatus.Status = Status;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            break;
+    }
+
+    DPRINT("USBPORT_Dispatch: Status - %x\n", Status);
+    return Status;
+}
+
+ULONG
+NTAPI
+USBPORT_GetHciMn(VOID)
+{
+    return USBPORT_HCI_MN;
+}
+
+NTSTATUS
+NTAPI
+USBPORT_RegisterUSBPortDriver(IN PDRIVER_OBJECT DriverObject,
+                              IN ULONG Version,
+                              IN PUSBPORT_REGISTRATION_PACKET RegPacket)
+{
+    PUSBPORT_MINIPORT_INTERFACE MiniPortInterface;
+
+    DPRINT("USBPORT_RegisterUSBPortDriver: DriverObject - %p, Version - %p, RegPacket - %p\n",
+           DriverObject,
+           Version,
+           RegPacket);
+
+    DPRINT("USBPORT_RegisterUSBPortDriver: sizeof(USBPORT_MINIPORT_INTERFACE) - %x\n",
+           sizeof(USBPORT_MINIPORT_INTERFACE));
+
+    DPRINT("USBPORT_RegisterUSBPortDriver: sizeof(USBPORT_DEVICE_EXTENSION)   - %x\n",
+           sizeof(USBPORT_DEVICE_EXTENSION));
+
+    if (Version < 100) // 100 - USB1.1; 200 - USB2.0
+    {
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    if (!USBPORT_Initialized)
+    {
+        InitializeListHead(&USBPORT_MiniPortDrivers);
+        InitializeListHead(&USBPORT_USB1FdoList);
+        InitializeListHead(&USBPORT_USB2FdoList);
+
+        KeInitializeSpinLock(&USBPORT_SpinLock);
+        USBPORT_Initialized = TRUE;
+    }
+
+    MiniPortInterface = ExAllocatePoolWithTag(NonPagedPool,
+                                              sizeof(USBPORT_MINIPORT_INTERFACE),
+                                              USB_PORT_TAG);
+    if (!MiniPortInterface)
+    {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    RtlZeroMemory(MiniPortInterface, sizeof(USBPORT_MINIPORT_INTERFACE));
+
+    MiniPortInterface->DriverObject = DriverObject;
+    MiniPortInterface->DriverUnload = DriverObject->DriverUnload;
+    MiniPortInterface->Version = Version;
+
+    ExInterlockedInsertTailList(&USBPORT_MiniPortDrivers,
+                                &MiniPortInterface->DriverLink,
+                                &USBPORT_SpinLock);
+
+    DriverObject->DriverExtension->AddDevice = USBPORT_AddDevice;
+    DriverObject->DriverUnload = USBPORT_Unload;
+
+    DriverObject->MajorFunction[IRP_MJ_CREATE] = USBPORT_Dispatch;
+    DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBPORT_Dispatch;
+    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBPORT_Dispatch;
+    DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = USBPORT_Dispatch;
+    DriverObject->MajorFunction[IRP_MJ_PNP] = USBPORT_Dispatch;
+    DriverObject->MajorFunction[IRP_MJ_POWER] = USBPORT_Dispatch;
+    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = USBPORT_Dispatch;
+
+    RegPacket->UsbPortDbgPrint = USBPORT_DbgPrint;
+    RegPacket->UsbPortTestDebugBreak = USBPORT_TestDebugBreak;
+    RegPacket->UsbPortAssertFailure = USBPORT_AssertFailure;
+    RegPacket->UsbPortGetMiniportRegistryKeyValue = USBPORT_GetMiniportRegistryKeyValue;
+    RegPacket->UsbPortInvalidateRootHub = USBPORT_InvalidateRootHub;
+    RegPacket->UsbPortInvalidateEndpoint = USBPORT_InvalidateEndpoint;
+    RegPacket->UsbPortCompleteTransfer = USBPORT_MiniportCompleteTransfer;
+    RegPacket->UsbPortCompleteIsoTransfer = USBPORT_CompleteIsoTransfer;
+    RegPacket->UsbPortLogEntry = USBPORT_LogEntry;
+    RegPacket->UsbPortGetMappedVirtualAddress = USBPORT_GetMappedVirtualAddress;
+    RegPacket->UsbPortRequestAsyncCallback = USBPORT_RequestAsyncCallback;
+    RegPacket->UsbPortReadWriteConfigSpace = USBPORT_ReadWriteConfigSpace;
+    RegPacket->UsbPortWait = USBPORT_Wait;
+    RegPacket->UsbPortInvalidateController = USBPORT_InvalidateController;
+    RegPacket->UsbPortBugCheck = USBPORT_BugCheck;
+    RegPacket->UsbPortNotifyDoubleBuffer = USBPORT_NotifyDoubleBuffer;
+
+    RtlCopyMemory(&MiniPortInterface->Packet,
+                  RegPacket,
+                  sizeof(USBPORT_REGISTRATION_PACKET));
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+DriverEntry(IN PDRIVER_OBJECT DriverObject,
+            IN PUNICODE_STRING RegistryPath)
+{
+    return STATUS_SUCCESS;
+}
diff --git a/reactos/drivers/usb/usbport/usbport.h b/reactos/drivers/usb/usbport/usbport.h
new file mode 100644 (file)
index 0000000..4771c05
--- /dev/null
@@ -0,0 +1,1121 @@
+#ifndef USBPORT_H__
+#define USBPORT_H__
+
+#include <ntddk.h>
+#include <windef.h>
+#include <stdio.h>
+#include <wdmguid.h>
+#include <ntstrsafe.h>
+#include <usb.h>
+#include <hubbusif.h>
+#include <usbbusif.h>
+#include <usbdlib.h>
+#include <usbuser.h>
+#include <drivers/usbport/usbmport.h>
+
+#define PCI_INTERFACE_USB_ID_UHCI 0x00
+#define PCI_INTERFACE_USB_ID_OHCI 0x10
+#define PCI_INTERFACE_USB_ID_EHCI 0x20
+#define PCI_INTERFACE_USB_ID_XHCI 0x30
+
+#ifdef USBD_TRANSFER_DIRECTION // due hubbusif.h included usbdi.h (Which overwrites...)
+#undef USBD_TRANSFER_DIRECTION
+#define USBD_TRANSFER_DIRECTION 0x00000001
+#endif
+
+#define USBPORT_RECIPIENT_ROOT_HUB  BMREQUEST_TO_DEVICE
+#define USBPORT_RECIPIENT_ROOT_PORT BMREQUEST_TO_OTHER
+
+#define INVALIDATE_CONTROLLER_RESET           1
+#define INVALIDATE_CONTROLLER_SURPRISE_REMOVE 2
+#define INVALIDATE_CONTROLLER_SOFT_INTERRUPT  3
+
+#define INVALIDATE_ENDPOINT_ONLY           0
+#define INVALIDATE_ENDPOINT_WORKER_THREAD  1
+#define INVALIDATE_ENDPOINT_WORKER_DPC     2
+#define INVALIDATE_ENDPOINT_INT_NEXT_SOF   3
+
+#define USBPORT_DMA_DIRECTION_FROM_DEVICE 1
+#define USBPORT_DMA_DIRECTION_TO_DEVICE   2
+
+#define USB_PORT_TAG 'pbsu'
+#define URB_FUNCTION_MAX 0x31
+
+/* Hub Class Feature Selectors (Recipient - Port) */
+#define FEATURE_PORT_CONNECTION     0
+#define FEATURE_PORT_ENABLE         1
+#define FEATURE_PORT_SUSPEND        2
+#define FEATURE_PORT_OVER_CURRENT   3
+#define FEATURE_PORT_RESET          4
+#define FEATURE_PORT_POWER          8
+#define FEATURE_PORT_LOW_SPEED      9
+#define FEATURE_C_PORT_CONNECTION   16
+#define FEATURE_C_PORT_ENABLE       17
+#define FEATURE_C_PORT_SUSPEND      18
+#define FEATURE_C_PORT_OVER_CURRENT 19
+#define FEATURE_C_PORT_RESET        20
+
+/* Hub Class Feature Selectors (Recipient - Hub) */
+#define FEATURE_C_HUB_LOCAL_POWER  0
+#define FEATURE_C_HUB_OVER_CURRENT 1
+
+/* Flags */
+#define USBPORT_FLAG_INT_CONNECTED     0x00000001
+#define USBPORT_FLAG_HC_STARTED        0x00000002
+#define USBPORT_FLAG_HC_POLLING        0x00000004
+#define USBPORT_FLAG_WORKER_THREAD_ON  0x00000008
+#define USBPORT_FLAG_HC_SUSPEND        0x00000100
+#define USBPORT_FLAG_INTERRUPT_ENABLED 0x00000400
+#define USBPORT_FLAG_SELECTIVE_SUSPEND 0x00000800
+#define USBPORT_FLAG_DOS_SYMBOLIC_NAME 0x00010000
+#define USBPORT_FLAG_LEGACY_SUPPORT    0x00080000
+#define USBPORT_FLAG_HC_WAKE_SUPPORT   0x00200000
+#define USBPORT_FLAG_DIAGNOSTIC_MODE   0x00800000 //IOCTL_USB_DIAGNOSTIC_MODE_ON
+#define USBPORT_FLAG_COMPANION_HC      0x01000000
+#define USBPORT_FLAG_REGISTERED_FDO    0x02000000
+#define USBPORT_FLAG_NO_HACTION        0x04000000
+#define USBPORT_FLAG_BIOS_DISABLE_SS   0x08000000 //Selective Suspend
+#define USBPORT_FLAG_PWR_AND_CHIRP_LOCK 0x10000000
+#define USBPORT_FLAG_POWER_AND_CHIRP_OK 0x40000000
+#define USBPORT_FLAG_RH_INIT_CALLBACK  0x80000000
+
+/* PnP state Flags */
+#define USBPORT_PNP_STATE_NOT_INIT  0x00000001
+#define USBPORT_PNP_STATE_STARTED   0x00000002
+#define USBPORT_PNP_STATE_FAILED    0x00000004
+#define USBPORT_PNP_STATE_STOPPED   0x00000008
+
+/* Timer Flags */
+#define USBPORT_TMFLAG_TIMER_QUEUED       0x00000001
+#define USBPORT_TMFLAG_HC_SUSPENDED       0x00000002
+#define USBPORT_TMFLAG_HC_RESUME          0x00000004
+#define USBPORT_TMFLAG_RH_SUSPENDED       0x00000008
+#define USBPORT_TMFLAG_TIMER_STARTED      0x00000010
+#define USBPORT_TMFLAG_WAKE               0x00000020
+#define USBPORT_TMFLAG_IDLE_QUEUEITEM_ON  0x00000040
+
+/* Miniport Flags */
+#define USBPORT_MPFLAG_INTERRUPTS_ENABLED  0x00000001
+#define USBPORT_MPFLAG_SUSPENDED           0x00000002
+
+/* Device handle Flags (USBPORT_DEVICE_HANDLE) */
+#define DEVICE_HANDLE_FLAG_ROOTHUB     0x00000002
+#define DEVICE_HANDLE_FLAG_REMOVED     0x00000008
+#define DEVICE_HANDLE_FLAG_INITIALIZED 0x00000010
+
+/* Endpoint Flags (USBPORT_ENDPOINT) */
+#define ENDPOINT_FLAG_DMA_TYPE      0x00000001
+#define ENDPOINT_FLAG_ROOTHUB_EP0   0x00000002
+#define ENDPOINT_FLAG_NUKE          0x00000008
+#define ENDPOINT_FLAG_QUEUENE_EMPTY 0x00000010
+#define ENDPOINT_FLAG_ABORTING      0x00000020
+#define ENDPOINT_FLAG_IDLE          0x00000100
+#define ENDPOINT_FLAG_OPENED        0x00000200
+#define ENDPOINT_FLAG_CLOSED        0x00000400
+
+/* UsbdFlags Flags (URB) */
+#define USBD_FLAG_ALLOCATED_MDL      0x00000002
+#define USBD_FLAG_NOT_ISO_TRANSFER   0x00000010
+#define USBD_FLAG_ALLOCATED_TRANSFER 0x00000020
+
+/* Pipe handle Flags (USBPORT_PIPE_HANDLE) */
+#define PIPE_HANDLE_FLAG_CLOSED 0x00000001
+#define PIPE_HANDLE_FLAG_NULL_PACKET_SIZE 0x00000002
+
+/* Transfer Flags (USBPORT_TRANSFER) */
+#define TRANSFER_FLAG_CANCELED   0x00000001
+#define TRANSFER_FLAG_DMA_MAPPED 0x00000002
+#define TRANSFER_FLAG_SUBMITED   0x00000008
+#define TRANSFER_FLAG_ABORTED    0x00000010
+#define TRANSFER_FLAG_ISO        0x00000020
+#define TRANSFER_FLAG_DEVICE_GONE 0x00000080
+#define TRANSFER_FLAG_SPLITED    0x00000100
+
+extern KSPIN_LOCK USBPORT_SpinLock;
+extern LIST_ENTRY USBPORT_MiniPortDrivers;
+
+typedef USBD_STATUS* PUSBD_STATUS;
+
+typedef struct _USBPORT_COMMON_BUFFER_HEADER {
+  ULONG Length;
+  ULONG_PTR BaseVA;
+  PHYSICAL_ADDRESS LogicalAddress;
+  SIZE_T BufferLength;
+  ULONG_PTR VirtualAddress;
+  ULONG_PTR PhysicalAddress;
+} USBPORT_COMMON_BUFFER_HEADER, *PUSBPORT_COMMON_BUFFER_HEADER;
+
+typedef struct _USBPORT_ENDPOINT *PUSBPORT_ENDPOINT;
+
+typedef struct _USBPORT_PIPE_HANDLE {
+  ULONG Flags;
+  ULONG PipeFlags;
+  USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+  UCHAR Padded;
+  PUSBPORT_ENDPOINT Endpoint;
+  LIST_ENTRY PipeLink;
+} USBPORT_PIPE_HANDLE, *PUSBPORT_PIPE_HANDLE;
+
+typedef struct _USBPORT_CONFIGURATION_HANDLE {
+  PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
+  LIST_ENTRY InterfaceHandleList;
+  //USB_CONFIGURATION_DESCRIPTOR CfgDescriptor; // Body.
+} USBPORT_CONFIGURATION_HANDLE, *PUSBPORT_CONFIGURATION_HANDLE;
+
+typedef struct _USBPORT_INTERFACE_HANDLE {
+  LIST_ENTRY InterfaceLink;
+  UCHAR AlternateSetting;
+  UCHAR Pad1[3];
+  USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+  UCHAR Pad2[3];
+  USBPORT_PIPE_HANDLE PipeHandle[1];
+} USBPORT_INTERFACE_HANDLE, *PUSBPORT_INTERFACE_HANDLE;
+
+typedef struct _USBPORT_DEVICE_HANDLE {
+  ULONG Flags;
+  USHORT DeviceAddress;
+  USHORT PortNumber;
+  USBPORT_PIPE_HANDLE PipeHandle;
+  ULONG DeviceSpeed;
+  BOOL IsRootHub;
+  LIST_ENTRY PipeHandleList;
+  PUSBPORT_CONFIGURATION_HANDLE ConfigHandle;
+  struct _USBPORT_DEVICE_HANDLE *HubDeviceHandle;
+  USB_DEVICE_DESCRIPTOR DeviceDescriptor;
+  LIST_ENTRY DeviceHandleLink;
+  LONG DeviceHandleLock;
+  ULONG TtCount;
+} USBPORT_DEVICE_HANDLE, *PUSBPORT_DEVICE_HANDLE;
+
+typedef struct _USBPORT_ENDPOINT {
+  ULONG Flags;
+  PDEVICE_OBJECT FdoDevice;
+  PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer;
+  PUSBPORT_DEVICE_HANDLE DeviceHandle;
+  USBPORT_ENDPOINT_PROPERTIES EndpointProperties;
+  ULONG EndpointWorker;
+  ULONG FrameNumber;
+  /* Locks */
+  KSPIN_LOCK EndpointSpinLock;
+  KIRQL EndpointOldIrql;
+  KIRQL EndpointStateOldIrql;
+  UCHAR Padded[2];
+  LONG LockCounter;
+  LONG FlushPendingLock;
+  /* State */
+  ULONG StateLast;
+  ULONG StateNext;
+  LIST_ENTRY StateChangeLink;
+  KSPIN_LOCK StateChangeSpinLock;
+  /* Transfer lists */
+  LIST_ENTRY PendingTransferList;
+  LIST_ENTRY TransferList;
+  LIST_ENTRY CancelList;
+  LIST_ENTRY AbortList;
+  /* Links */
+  LIST_ENTRY EndpointLink;
+  LIST_ENTRY WorkerLink;
+  LIST_ENTRY CloseLink;
+  LIST_ENTRY DispatchLink;
+  LIST_ENTRY FlushLink;
+  LIST_ENTRY FlushControllerLink;
+  LIST_ENTRY FlushAbortLink;
+} USBPORT_ENDPOINT, *PUSBPORT_ENDPOINT;
+
+typedef struct _USBPORT_TRANSFER {
+  ULONG Flags;
+  PIRP Irp;
+  PURB Urb;
+  PRKEVENT Event;
+  PVOID MiniportTransfer;
+  SIZE_T PortTransferLength; // Only port part
+  SIZE_T FullTransferLength; // Port + miniport
+  PUSBPORT_ENDPOINT Endpoint;
+  USBPORT_TRANSFER_PARAMETERS TransferParameters;
+  PMDL TransferBufferMDL;
+  ULONG Direction;
+  LIST_ENTRY TransferLink;
+  USBD_STATUS USBDStatus;
+  ULONG CompletedTransferLen;
+  ULONG NumberOfMapRegisters;
+  PVOID MapRegisterBase;
+  ULONG TimeOut;
+  LARGE_INTEGER Time;
+  // SgList should be LAST field
+  USBPORT_SCATTER_GATHER_LIST SgList; // Non IsoTransfer
+} USBPORT_TRANSFER, *PUSBPORT_TRANSFER;
+
+typedef struct _USBPORT_IRP_TABLE {
+  struct _USBPORT_IRP_TABLE * LinkNextTable;
+  PIRP irp[0X200];
+} USBPORT_IRP_TABLE, *PUSBPORT_IRP_TABLE;
+
+typedef struct _USBPORT_COMMON_DEVICE_EXTENSION {
+  PDEVICE_OBJECT SelfDevice;
+  PDEVICE_OBJECT LowerPdoDevice; // PhysicalDeviceObject
+  PDEVICE_OBJECT LowerDevice; // TopOfStackDeviceObject
+  ULONG IsPDO;
+  UNICODE_STRING SymbolicLinkName;
+  BOOL IsInterfaceEnabled;
+  DEVICE_POWER_STATE DevicePowerState;
+  ULONG PnpStateFlags;
+} USBPORT_COMMON_DEVICE_EXTENSION, *PUSBPORT_COMMON_DEVICE_EXTENSION;
+
+typedef struct _USBPORT_DEVICE_EXTENSION {
+  USBPORT_COMMON_DEVICE_EXTENSION CommonExtension;
+  ULONG Flags;
+  PDEVICE_OBJECT RootHubPdo; // RootHubDeviceObject
+  KSPIN_LOCK RootHubCallbackSpinLock;
+  LONG RHInitCallBackLock;
+  LONG ChirpRootPortLock;
+  KSEMAPHORE ControllerSemaphore;
+  ULONG FdoNameNumber;
+  UNICODE_STRING DosDeviceSymbolicName;
+  ULONG UsbBIOSx;
+  LIST_ENTRY ControllerLink;
+  ULONG CommonBufferLimit;
+  /* Miniport */
+  ULONG MiniPortFlags;
+  PVOID MiniPortExt;
+  PUSBPORT_MINIPORT_INTERFACE MiniPortInterface;
+  USBPORT_RESOURCES UsbPortResources;
+  PUSBPORT_COMMON_BUFFER_HEADER MiniPortCommonBuffer;
+  KSPIN_LOCK MiniportSpinLock;
+  /* Bus Interface */
+  BUS_INTERFACE_STANDARD BusInterface;
+  USHORT VendorID;
+  USHORT DeviceID;
+  UCHAR RevisionID;
+  UCHAR ProgIf;
+  UCHAR SubClass;
+  UCHAR BaseClass;
+  /* Dma Adapter */
+  PDMA_ADAPTER DmaAdapter;
+  ULONG NumberMapRegs;
+  /* Interrupt */
+  PKINTERRUPT InterruptObject;
+  KDPC IsrDpc;
+  LONG IsrDpcCounter;
+  LONG IsrDpcHandlerCounter;
+  KSPIN_LOCK MiniportInterruptsSpinLock;
+  KTIMER TimerSoftInterrupt;
+  KDPC SoftInterruptDpc;
+  /* Endpoints */
+  ULONG PeriodicEndpoints;
+  LIST_ENTRY EndpointList;
+  KSPIN_LOCK EndpointListSpinLock;
+  LIST_ENTRY EpStateChangeList;
+  KSPIN_LOCK EpStateChangeSpinLock;
+  LIST_ENTRY EndpointClosedList;
+  KSPIN_LOCK EndpointClosedSpinLock;
+  LIST_ENTRY WorkerList;
+  /* Transfers */
+  LIST_ENTRY MapTransferList;
+  KSPIN_LOCK MapTransferSpinLock;
+  LIST_ENTRY DoneTransferList;
+  KSPIN_LOCK DoneTransferSpinLock;
+  KDPC TransferFlushDpc;
+  KSPIN_LOCK FlushTransferSpinLock;
+  KSPIN_LOCK FlushPendingTransferSpinLock;
+  /* Timer */
+  ULONG TimerValue; // Timer period (500) msec. default
+  ULONG TimerFlags;
+  KTIMER TimerObject;
+  KDPC TimerDpc;
+  KSPIN_LOCK TimerFlagsSpinLock;
+  /* Worker Thread */
+  PRKTHREAD WorkerThread;
+  HANDLE WorkerThreadHandle;
+  KEVENT WorkerThreadEvent;
+  KSPIN_LOCK WorkerThreadEventSpinLock;
+  /* Usb Devices */
+  ULONG UsbAddressBitMap[4];
+  LIST_ENTRY DeviceHandleList;
+  KSPIN_LOCK DeviceHandleSpinLock;
+  KSEMAPHORE DeviceSemaphore;
+  /* Device Capabilities */
+  DEVICE_CAPABILITIES Capabilities;
+  ULONG BusNumber;
+  ULONG PciDeviceNumber;
+  ULONG PciFunctionNumber;
+  ULONG TotalBusBandwidth;
+  /* Idle */
+  LARGE_INTEGER IdleTime;
+  IO_CSQ IdleIoCsq;
+  KSPIN_LOCK IdleIoCsqSpinLock;
+  LIST_ENTRY IdleIrpList;
+  LONG IdleLockCounter;
+  /* Bad Requests */
+  IO_CSQ BadRequestIoCsq;
+  KSPIN_LOCK BadRequestIoCsqSpinLock;
+  LIST_ENTRY BadRequestList;
+  LONG BadRequestLockCounter;
+  /* Irp Queues */
+  PUSBPORT_IRP_TABLE PendingIrpTable;
+  PUSBPORT_IRP_TABLE ActiveIrpTable;
+  /* Power */
+  LONG SetPowerLockCounter;
+  KSPIN_LOCK PowerWakeSpinLock;
+  KSPIN_LOCK SetPowerD0SpinLock;
+  KDPC WorkerRequestDpc;
+  KDPC HcWakeDpc;
+  ULONG Padded[34]; // Miniport extension should be aligned on 0x100
+} USBPORT_DEVICE_EXTENSION, *PUSBPORT_DEVICE_EXTENSION;
+
+C_ASSERT(sizeof(USBPORT_DEVICE_EXTENSION) == 0x400);
+
+typedef struct _USBPORT_RH_DESCRIPTORS {
+  USB_DEVICE_DESCRIPTOR DeviceDescriptor;
+  USB_CONFIGURATION_DESCRIPTOR ConfigDescriptor;
+  USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+  USB_ENDPOINT_DESCRIPTOR EndPointDescriptor;
+  USB_HUB_DESCRIPTOR Descriptor; // Size may be: 7 + 2[1..32] (7 + 2..64)
+} USBPORT_RH_DESCRIPTORS, *PUSBPORT_RH_DESCRIPTORS;
+
+typedef struct _USBPORT_RHDEVICE_EXTENSION {
+  USBPORT_COMMON_DEVICE_EXTENSION CommonExtension;
+  ULONG Flags;
+  PDEVICE_OBJECT FdoDevice;
+  ULONG PdoNameNumber;
+  USBPORT_DEVICE_HANDLE DeviceHandle;
+  PUSBPORT_RH_DESCRIPTORS RootHubDescriptors;
+  PUSBPORT_ENDPOINT Endpoint;
+  ULONG ConfigurationValue;
+  PRH_INIT_CALLBACK RootHubInitCallback;
+  PVOID RootHubInitContext;
+  DEVICE_CAPABILITIES Capabilities;
+  PIRP WakeIrp;
+} USBPORT_RHDEVICE_EXTENSION, *PUSBPORT_RHDEVICE_EXTENSION;
+
+typedef struct _USBPORT_ASYNC_CALLBACK_DATA {
+  ULONG Reserved;
+  PDEVICE_OBJECT FdoDevice;
+  KTIMER AsyncTimer;
+  KDPC AsyncTimerDpc;
+  ASYNC_TIMER_CALLBACK *CallbackFunction;
+  ULONG CallbackContext;
+} USBPORT_ASYNC_CALLBACK_DATA, *PUSBPORT_ASYNC_CALLBACK_DATA;
+
+C_ASSERT(sizeof(USBPORT_ASYNC_CALLBACK_DATA) == 88);
+
+typedef struct _TIMER_WORK_QUEUE_ITEM {
+  WORK_QUEUE_ITEM WqItem;
+  PDEVICE_OBJECT FdoDevice;
+  ULONG Context;
+} TIMER_WORK_QUEUE_ITEM, *PTIMER_WORK_QUEUE_ITEM;
+
+/* usbport.c */
+NTSTATUS
+NTAPI
+USBPORT_USBDStatusToNtStatus(
+  IN PURB Urb,
+  IN USBD_STATUS USBDStatus);
+
+NTSTATUS
+NTAPI
+USBPORT_Wait(
+  IN PVOID Context,
+  IN ULONG Milliseconds);
+
+VOID
+NTAPI
+USBPORT_TransferFlushDpc(
+  IN PRKDPC Dpc,
+  IN PVOID DeferredContext,
+  IN PVOID SystemArgument1,
+  IN PVOID SystemArgument2);
+
+NTSTATUS
+NTAPI
+USBPORT_CreateWorkerThread(
+  IN PDEVICE_OBJECT FdoDevice);
+
+BOOLEAN
+NTAPI
+USBPORT_StartTimer(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN ULONG Time);
+
+PUSBPORT_COMMON_BUFFER_HEADER
+NTAPI
+USBPORT_AllocateCommonBuffer(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN SIZE_T BufferLength);
+
+VOID
+NTAPI
+USBPORT_FreeCommonBuffer(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer);
+
+USBD_STATUS
+NTAPI
+USBPORT_AllocateTransfer(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PURB Urb,
+  IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+  IN PIRP Irp,
+  IN PRKEVENT Event);
+
+VOID
+NTAPI
+USBPORT_FlushMapTransfers(
+  IN PDEVICE_OBJECT FdoDevice);
+
+VOID
+NTAPI
+USBPORT_IsrDpc(
+  IN PRKDPC Dpc,
+  IN PVOID DeferredContext,
+  IN PVOID SystemArgument1,
+  IN PVOID SystemArgument2);
+
+BOOLEAN
+NTAPI
+USBPORT_InterruptService(
+  IN PKINTERRUPT Interrupt,
+  IN PVOID ServiceContext);
+
+VOID
+NTAPI
+USBPORT_SignalWorkerThread(
+  IN PDEVICE_OBJECT FdoDevice);
+
+VOID
+NTAPI
+USBPORT_CompleteTransfer(
+  IN PURB Urb,
+  IN USBD_STATUS TransferStatus);
+
+VOID
+NTAPI
+USBPORT_DpcHandler(
+  IN PDEVICE_OBJECT FdoDevice);
+
+VOID
+NTAPI
+USBPORT_WorkerRequestDpc(
+  IN PRKDPC Dpc,
+  IN PVOID DeferredContext,
+  IN PVOID SystemArgument1,
+  IN PVOID SystemArgument2);
+
+BOOLEAN
+NTAPI
+USBPORT_QueueDoneTransfer(
+  IN PUSBPORT_TRANSFER Transfer,
+  IN USBD_STATUS USBDStatus);
+
+VOID
+NTAPI
+USBPORT_MiniportInterrupts(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN BOOLEAN IsEnable);
+
+NTSTATUS
+NTAPI
+USBPORT_SetRegistryKeyValue(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN BOOL UseDriverKey,
+  IN ULONG Type,
+  IN PCWSTR ValueNameString,
+  IN PVOID Data,
+  IN ULONG DataSize);
+
+NTSTATUS
+NTAPI
+USBPORT_GetRegistryKeyValueFullInfo(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PDEVICE_OBJECT PdoDevice,
+  IN BOOL UseDriverKey,
+  IN PCWSTR SourceString,
+  IN ULONG LengthStr,
+  IN PVOID Buffer,
+  IN ULONG NumberOfBytes);
+
+VOID
+NTAPI
+USBPORT_AddUSB1Fdo(
+  IN PDEVICE_OBJECT FdoDevice);
+
+VOID
+NTAPI
+USBPORT_AddUSB2Fdo(
+  IN PDEVICE_OBJECT FdoDevice);
+
+VOID
+NTAPI
+USBPORT_RemoveUSBxFdo(
+  IN PDEVICE_OBJECT FdoDevice);
+
+PDEVICE_OBJECT
+NTAPI
+USBPORT_FindUSB2Controller(
+  IN PDEVICE_OBJECT FdoDevice);
+
+PDEVICE_RELATIONS
+NTAPI
+USBPORT_FindCompanionControllers(
+  IN PDEVICE_OBJECT USB2FdoDevice,
+  IN BOOLEAN IsObRefer,
+  IN BOOLEAN IsFDOsReturned);
+
+VOID
+NTAPI
+USBPORT_InvalidateControllerHandler(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN ULONG Type);
+
+/* debug.c */
+ULONG
+NTAPI
+USBPORT_DbgPrint(
+  IN PVOID Context,
+  IN ULONG Level,
+  IN PCH Format,
+  ...);
+
+ULONG
+NTAPI
+USBPORT_TestDebugBreak(
+  IN PVOID Context);
+
+ULONG
+NTAPI
+USBPORT_AssertFailure(
+  PVOID Context,
+  PVOID FailedAssertion,
+  PVOID FileName,
+  ULONG LineNumber,
+  PCHAR Message);
+
+VOID
+NTAPI
+USBPORT_BugCheck(
+  IN PVOID Context);
+
+ULONG
+NTAPI
+USBPORT_LogEntry(
+  IN PVOID BusContext,
+  IN ULONG DriverTag,
+  IN ULONG EnumTag,
+  IN ULONG P1,
+  IN ULONG P2,
+  IN ULONG P3);
+
+VOID
+NTAPI
+USBPORT_DumpingDeviceDescriptor(
+  IN PUSB_DEVICE_DESCRIPTOR DeviceDescriptor);
+
+VOID
+NTAPI
+USBPORT_DumpingConfiguration(
+  IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor);
+
+VOID
+NTAPI
+USBPORT_DumpingCapabilities(
+  IN PDEVICE_CAPABILITIES Capabilities);
+
+VOID
+NTAPI
+USBPORT_DumpingSetupPacket(
+  IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket);
+
+VOID
+NTAPI
+USBPORT_DumpingURB(
+  IN PURB Urb);
+
+VOID
+NTAPI
+USBPORT_DumpingIDs(
+  IN PVOID Buffer);
+
+/* device.c */
+NTSTATUS
+NTAPI
+USBPORT_HandleSelectConfiguration(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PIRP Irp,
+  IN PURB Urb);
+
+VOID
+NTAPI
+USBPORT_AddDeviceHandle(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PUSBPORT_DEVICE_HANDLE DeviceHandle);
+
+VOID
+NTAPI
+USBPORT_RemoveDeviceHandle(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PUSBPORT_DEVICE_HANDLE DeviceHandle);
+
+BOOLEAN
+NTAPI
+USBPORT_ValidateDeviceHandle(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PUSBPORT_DEVICE_HANDLE DeviceHandle);
+
+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);
+
+NTSTATUS
+NTAPI
+USBPORT_InitializeDevice(
+  IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+  IN PDEVICE_OBJECT FdoDevice);
+
+NTSTATUS
+NTAPI
+USBPORT_GetUsbDescriptor(
+  IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+  IN PDEVICE_OBJECT FdoDevice,
+  IN UCHAR Type,
+  IN PUCHAR ConfigDesc,
+  IN PULONG ConfigDescSize);
+
+NTSTATUS
+NTAPI
+USBPORT_HandleSelectInterface(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PIRP Irp,
+  IN PURB Urb);
+
+NTSTATUS
+NTAPI
+USBPORT_RemoveDevice(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN OUT PUSBPORT_DEVICE_HANDLE DeviceHandle,
+  IN ULONG Flags);
+
+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);
+
+NTSTATUS
+NTAPI
+USBPORT_RestoreDevice(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN OUT PUSBPORT_DEVICE_HANDLE OldDeviceHandle,
+  IN OUT PUSBPORT_DEVICE_HANDLE NewDeviceHandle);
+
+NTSTATUS
+NTAPI
+USBPORT_Initialize20Hub(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
+  IN ULONG TtCount);
+
+/* endpoint.c */
+NTSTATUS
+NTAPI
+USBPORT_OpenPipe(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+  IN PUSBPORT_PIPE_HANDLE PipeHandle,
+  IN PUSBD_STATUS UsbdStatus);
+
+MPSTATUS
+NTAPI
+MiniportOpenEndpoint(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PUSBPORT_ENDPOINT Endpoint);
+
+NTSTATUS
+NTAPI
+USBPORT_ReopenPipe(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PUSBPORT_ENDPOINT Endpoint);
+
+VOID
+NTAPI
+USBPORT_ClosePipe(
+  IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PUSBPORT_PIPE_HANDLE PipeHandle);
+
+VOID
+NTAPI
+MiniportCloseEndpoint(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PUSBPORT_ENDPOINT Endpoint);
+
+VOID
+NTAPI
+USBPORT_AddPipeHandle(
+  IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+  IN PUSBPORT_PIPE_HANDLE PipeHandle);
+
+VOID
+NTAPI
+USBPORT_RemovePipeHandle(
+  IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+  IN PUSBPORT_PIPE_HANDLE PipeHandle);
+
+BOOLEAN
+NTAPI
+USBPORT_ValidatePipeHandle(
+  IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
+  IN PUSBPORT_PIPE_HANDLE PipeHandle);
+
+VOID
+NTAPI
+USBPORT_FlushClosedEndpointList(
+  IN PDEVICE_OBJECT FdoDevice);
+
+VOID
+NTAPI
+USBPORT_SetEndpointState(
+  IN PUSBPORT_ENDPOINT Endpoint,
+  IN ULONG State);
+
+ULONG 
+NTAPI
+USBPORT_GetEndpointState(
+  IN PUSBPORT_ENDPOINT Endpoint);
+
+VOID
+NTAPI
+USBPORT_InvalidateEndpointHandler(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PUSBPORT_ENDPOINT Endpoint,
+  IN ULONG Type);
+
+BOOLEAN
+NTAPI
+USBPORT_EndpointWorker(
+  IN PUSBPORT_ENDPOINT Endpoint,
+  IN BOOLEAN Flag);
+
+VOID
+NTAPI
+USBPORT_NukeAllEndpoints(
+  IN PDEVICE_OBJECT FdoDevice);
+
+BOOLEAN
+NTAPI
+USBPORT_EndpointHasQueuedTransfers(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PUSBPORT_ENDPOINT Endpoint,
+  IN PULONG TransferCount);
+
+/* iface.c */
+NTSTATUS
+NTAPI
+USBPORT_PdoQueryInterface(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PDEVICE_OBJECT PdoDevice,
+  IN PIRP Irp);
+
+/* ioctl.c */
+NTSTATUS
+NTAPI
+USBPORT_PdoDeviceControl(
+  PDEVICE_OBJECT PdoDevice,
+  PIRP Irp);
+
+NTSTATUS
+NTAPI
+USBPORT_FdoDeviceControl(
+  PDEVICE_OBJECT FdoDevice,
+  PIRP Irp);
+
+NTSTATUS
+NTAPI
+USBPORT_FdoInternalDeviceControl(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PIRP Irp);
+
+NTSTATUS
+NTAPI
+USBPORT_PdoInternalDeviceControl(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PIRP Irp);
+
+NTSTATUS
+NTAPI
+USBPORT_GetSymbolicName(
+  IN PDEVICE_OBJECT RootHubPdo,
+  IN PUNICODE_STRING DestinationString);
+
+/* pnp.c */
+NTSTATUS
+NTAPI
+USBPORT_FdoPnP(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PIRP Irp);
+
+NTSTATUS
+NTAPI
+USBPORT_PdoPnP(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PIRP Irp);
+
+/* power.c */
+NTSTATUS
+NTAPI
+USBPORT_PdoPower(
+  IN PDEVICE_OBJECT PdoDevice,
+  IN PIRP Irp);
+
+NTSTATUS
+NTAPI
+USBPORT_FdoPower(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PIRP Irp);
+
+NTSTATUS
+NTAPI
+USBPORT_IdleNotification(
+  IN PDEVICE_OBJECT PdoDevice,
+  IN PIRP Irp);
+
+VOID
+NTAPI
+USBPORT_AdjustDeviceCapabilities(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PDEVICE_OBJECT PdoDevice);
+
+VOID
+NTAPI
+USBPORT_DoIdleNotificationCallback(
+  IN PVOID Context);
+
+VOID
+NTAPI
+USBPORT_CompletePdoWaitWake(
+  IN PDEVICE_OBJECT FdoDevice);
+
+VOID
+NTAPI
+USBPORT_DoSetPowerD0(
+  IN PDEVICE_OBJECT FdoDevice);
+
+VOID
+NTAPI
+USBPORT_HcWakeDpc(
+  IN PRKDPC Dpc,
+  IN PVOID DeferredContext,
+  IN PVOID SystemArgument1,
+  IN PVOID SystemArgument2);
+
+VOID
+NTAPI
+USBPORT_HcQueueWakeDpc(
+  IN PDEVICE_OBJECT FdoDevice);
+
+/* queue.c */
+VOID
+NTAPI
+USBPORT_InsertIdleIrp(
+  IN PIO_CSQ Csq,
+  IN PIRP Irp);
+
+VOID
+NTAPI
+USBPORT_RemoveIdleIrp(
+  IN PIO_CSQ Csq,
+  IN PIRP Irp);
+
+PIRP
+NTAPI
+USBPORT_PeekNextIdleIrp(
+  IN PIO_CSQ Csq,
+  IN PIRP Irp,
+  IN PVOID PeekContext);
+
+VOID
+NTAPI
+USBPORT_AcquireIdleLock(
+  IN PIO_CSQ Csq,
+  IN PKIRQL Irql);
+
+VOID
+NTAPI
+USBPORT_ReleaseIdleLock(
+  IN PIO_CSQ Csq,
+  IN KIRQL Irql);
+
+VOID
+NTAPI
+USBPORT_CompleteCanceledIdleIrp(
+  IN PIO_CSQ Csq,
+  IN PIRP Irp);
+
+VOID
+NTAPI
+USBPORT_InsertBadRequest(
+  IN PIO_CSQ Csq,
+  IN PIRP Irp);
+
+VOID
+NTAPI
+USBPORT_RemoveBadRequest(
+  IN PIO_CSQ Csq,
+  IN PIRP Irp);
+
+PIRP
+NTAPI
+USBPORT_PeekNextBadRequest(
+  IN PIO_CSQ Csq,
+  IN PIRP Irp,
+  IN PVOID PeekContext);
+
+VOID
+NTAPI
+USBPORT_AcquireBadRequestLock(
+  IN PIO_CSQ Csq,
+  IN PKIRQL Irql);
+
+VOID
+NTAPI
+USBPORT_ReleaseBadRequestLock(
+  IN PIO_CSQ Csq,
+  IN KIRQL Irql);
+
+VOID
+NTAPI
+USBPORT_CompleteCanceledBadRequest(
+  IN PIO_CSQ Csq,
+  IN PIRP Irp);
+
+VOID
+NTAPI
+USBPORT_InsertIrpInTable(
+  IN PUSBPORT_IRP_TABLE IrpTable,
+  IN PIRP Irp);
+
+PIRP
+NTAPI
+USBPORT_RemovePendingTransferIrp(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PIRP Irp);
+
+PIRP
+NTAPI
+USBPORT_RemoveActiveTransferIrp(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PIRP Irp);
+
+VOID
+NTAPI
+USBPORT_FindUrbInIrpTable(
+  IN PUSBPORT_IRP_TABLE IrpTable,
+  IN PURB Urb,
+  IN PIRP Irp);
+
+VOID
+NTAPI
+USBPORT_CancelActiveTransferIrp(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PIRP Irp);
+
+VOID
+NTAPI
+USBPORT_FlushAbortList(
+  IN PUSBPORT_ENDPOINT Endpoint);
+
+VOID
+NTAPI
+USBPORT_FlushCancelList(
+  IN PUSBPORT_ENDPOINT Endpoint);
+
+VOID
+NTAPI
+USBPORT_QueueTransferUrb(
+  IN PURB Urb);
+
+VOID
+NTAPI
+USBPORT_FlushAllEndpoints(
+  IN PDEVICE_OBJECT FdoDevice);
+
+VOID
+NTAPI
+USBPORT_FlushPendingTransfers(
+  IN PUSBPORT_ENDPOINT Endpoint);
+
+BOOLEAN
+NTAPI
+USBPORT_QueueActiveUrbToEndpoint(
+  IN PUSBPORT_ENDPOINT Endpoint,
+  IN PURB Urb);
+
+VOID
+NTAPI
+USBPORT_FlushController(
+  IN PDEVICE_OBJECT FdoDevice);
+
+VOID
+NTAPI
+USBPORT_BadRequestFlush(
+  IN PDEVICE_OBJECT FdoDevice);
+
+VOID
+NTAPI
+USBPORT_AbortEndpoint(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PUSBPORT_ENDPOINT Endpoint,
+  IN PIRP Irp);
+
+/* roothub.c */
+VOID
+NTAPI
+USBPORT_RootHubEndpointWorker(
+  PUSBPORT_ENDPOINT Endpoint);
+
+NTSTATUS
+NTAPI
+USBPORT_RootHubCreateDevice(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PDEVICE_OBJECT PdoDevice);
+
+ULONG
+NTAPI
+USBPORT_InvalidateRootHub(
+  PVOID Context);
+
+VOID
+NTAPI
+USBPORT_RootHubPowerAndChirpAllCcPorts(
+  IN PDEVICE_OBJECT FdoDevice);
+
+/* urb.c */
+NTSTATUS
+NTAPI
+USBPORT_HandleSubmitURB(
+  IN PDEVICE_OBJECT PdoDevice,
+  IN PIRP Irp,
+  IN PURB Urb);
+
+/* usb2.c */
+BOOLEAN
+NTAPI
+USBPORT_AllocateBandwidthUSB2(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PUSBPORT_ENDPOINT Endpoint);
+
+VOID
+NTAPI
+USBPORT_FreeBandwidthUSB2(
+  IN PDEVICE_OBJECT FdoDevice,
+  IN PUSBPORT_ENDPOINT Endpoint);
+
+#endif /* USBPORT_H__ */
diff --git a/reactos/drivers/usb/usbport/usbport.rc b/reactos/drivers/usb/usbport/usbport.rc
new file mode 100644 (file)
index 0000000..15fc801
--- /dev/null
@@ -0,0 +1,5 @@
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION  "USB bus driver extension"
+#define REACTOS_STR_INTERNAL_NAME     "usbport"
+#define REACTOS_STR_ORIGINAL_FILENAME "usbport.sys"
+#include <reactos/version.rc>
diff --git a/reactos/drivers/usb/usbport/usbport.spec b/reactos/drivers/usb/usbport/usbport.spec
new file mode 100644 (file)
index 0000000..dbe80be
--- /dev/null
@@ -0,0 +1,2 @@
+@ stdcall USBPORT_GetHciMn()
+@ stdcall USBPORT_RegisterUSBPortDriver(ptr long ptr)
\ No newline at end of file
diff --git a/reactos/sdk/include/reactos/drivers/usbport/usbmport.h b/reactos/sdk/include/reactos/drivers/usbport/usbmport.h
new file mode 100644 (file)
index 0000000..7cf214b
--- /dev/null
@@ -0,0 +1,653 @@
+#ifndef USBMPORT_H__
+#define USBMPORT_H__
+
+#define USBPORT_HCI_MN 0x10000001
+
+/* Tranfer types */
+#define USBPORT_TRANSFER_TYPE_ISOCHRONOUS 0
+#define USBPORT_TRANSFER_TYPE_CONTROL     1
+#define USBPORT_TRANSFER_TYPE_BULK        2
+#define USBPORT_TRANSFER_TYPE_INTERRUPT   3
+
+/* Endpoint states */
+#define USBPORT_ENDPOINT_UNKNOWN 0
+#define USBPORT_ENDPOINT_PAUSED 2
+#define USBPORT_ENDPOINT_ACTIVE 3
+#define USBPORT_ENDPOINT_REMOVE 4
+#define USBPORT_ENDPOINT_CLOSED 5
+
+/* Endpoint status */
+#define USBPORT_ENDPOINT_RUN     0
+#define USBPORT_ENDPOINT_HALT    1
+#define USBPORT_ENDPOINT_CONTROL 4
+
+/* Types of resources. For USBPORT_RESOURCES::ResourcesTypes */
+#define USBPORT_RESOURCES_PORT      1
+#define USBPORT_RESOURCES_INTERRUPT 2
+#define USBPORT_RESOURCES_MEMORY    4
+
+typedef struct _USBPORT_RESOURCES {
+  ULONG ResourcesTypes;
+  ULONG HcFlavor;
+  ULONG InterruptVector;
+  KIRQL InterruptLevel;
+  UCHAR Padded1[3];
+  KAFFINITY InterruptAffinity;
+  BOOLEAN ShareVector;
+  UCHAR Padded2[3];
+  KINTERRUPT_MODE InterruptMode;
+  ULONG Reserved;
+  PVOID ResourceBase;
+  SIZE_T IoSpaceLength;
+  PVOID StartVA;
+  PVOID StartPA;
+  UCHAR LegacySupport;
+  BOOLEAN IsChirpHandled;
+  UCHAR Reserved2;
+  UCHAR Reserved3;
+} USBPORT_RESOURCES, *PUSBPORT_RESOURCES;
+
+C_ASSERT(sizeof(USBPORT_RESOURCES) == 52);
+
+typedef ULONG MPSTATUS; // Miniport status
+typedef ULONG RHSTATUS; // Roothub status
+
+#define MP_STATUS_SUCCESS       0
+#define MP_STATUS_FAILURE       1
+#define MP_STATUS_NO_RESOURCES  2
+#define MP_STATUS_NO_BANDWIDTH  3
+#define MP_STATUS_ERROR         4
+#define MP_STATUS_RESERVED1     5
+#define MP_STATUS_NOT_SUPPORTED 6
+#define MP_STATUS_HW_ERROR      7
+#define MP_STATUS_UNSUCCESSFUL  8
+
+#define RH_STATUS_SUCCESS       0
+#define RH_STATUS_NO_CHANGES    1
+#define RH_STATUS_UNSUCCESSFUL  2
+
+typedef USB_20_PORT_CHANGE USB_PORT_STATUS_CHANGE;
+
+typedef union _USBHUB_PORT_STATUS {
+struct {
+    USB_PORT_STATUS UsbPortStatus;
+    USB_PORT_STATUS_CHANGE UsbPortStatusChange;
+  };
+  ULONG AsULONG;
+} USBHUB_PORT_STATUS, *PUSBHUB_PORT_STATUS;
+
+/* Hub status & hub status change bits.
+   See USB 2.0 spec Table 11-19 and Table 11-20. */
+#define HUB_STATUS_CHANGE_LOCAL_POWER 0x00010000
+#define HUB_STATUS_CHANGE_OVERCURRENT 0x00020000
+
+/* Additional USB Class Codes from USB.org */
+#define USBC_DEVICE_CLASS_AUDIO_VIDEO           0x10
+#define USBC_DEVICE_CLASS_BILLBOARD             0x11
+#define USBC_DEVICE_CLASS_TYPE_C_BRIDGE         0x12
+
+/* Miniport functions */
+typedef MPSTATUS
+(NTAPI *PHCI_OPEN_ENDPOINT)(
+  PVOID,
+  PVOID,
+  PVOID);
+
+typedef MPSTATUS
+(NTAPI *PHCI_REOPEN_ENDPOINT)(
+  PVOID,
+  PVOID,
+  PVOID);
+
+typedef VOID
+(NTAPI *PHCI_QUERY_ENDPOINT_REQUIREMENTS)(
+  PVOID,
+  PVOID,
+  PULONG);
+
+typedef VOID
+(NTAPI *PHCI_CLOSE_ENDPOINT)(
+  PVOID,
+  PVOID,
+  BOOLEAN);
+
+typedef MPSTATUS
+(NTAPI *PHCI_START_CONTROLLER)(
+  PVOID,
+  PUSBPORT_RESOURCES);
+
+typedef VOID
+(NTAPI *PHCI_STOP_CONTROLLER)(
+  PVOID,
+  BOOLEAN);
+
+typedef VOID
+(NTAPI *PHCI_SUSPEND_CONTROLLER)(PVOID);
+
+typedef MPSTATUS
+(NTAPI *PHCI_RESUME_CONTROLLER)(PVOID);
+
+typedef BOOLEAN
+(NTAPI *PHCI_INTERRUPT_SERVICE)(PVOID);
+
+typedef VOID
+(NTAPI *PHCI_INTERRUPT_DPC)(
+  PVOID,
+  BOOLEAN);
+
+typedef MPSTATUS
+(NTAPI *PHCI_SUBMIT_TRANSFER)(
+  PVOID,
+  PVOID,
+  PVOID,
+  PVOID,
+  PVOID);
+
+typedef MPSTATUS
+(NTAPI *PHCI_SUBMIT_ISO_TRANSFER)(
+  PVOID,
+  PVOID,
+  PVOID,
+  PVOID,
+  PVOID);
+
+typedef VOID
+(NTAPI *PHCI_ABORT_TRANSFER)(
+  PVOID,
+  PVOID,
+  PVOID,
+  PULONG);
+
+typedef ULONG
+(NTAPI *PHCI_GET_ENDPOINT_STATE)(
+  PVOID,
+  PVOID);
+
+typedef VOID
+(NTAPI *PHCI_SET_ENDPOINT_STATE)(
+  PVOID,
+  PVOID,
+  ULONG);
+
+typedef VOID
+(NTAPI *PHCI_POLL_ENDPOINT)(
+  PVOID,
+  PVOID);
+
+typedef VOID
+(NTAPI *PHCI_CHECK_CONTROLLER)(PVOID);
+
+typedef ULONG
+(NTAPI *PHCI_GET_32BIT_FRAME_NUMBER)(PVOID);
+
+typedef VOID
+(NTAPI *PHCI_INTERRUPT_NEXT_SOF)(PVOID);
+
+typedef VOID
+(NTAPI *PHCI_ENABLE_INTERRUPTS)(PVOID);
+
+typedef VOID
+(NTAPI *PHCI_DISABLE_INTERRUPTS)(PVOID);
+
+typedef VOID
+(NTAPI *PHCI_POLL_CONTROLLER)(PVOID);
+
+typedef VOID
+(NTAPI *PHCI_SET_ENDPOINT_DATA_TOGGLE)(
+  PVOID,
+  PVOID,
+  ULONG);
+
+typedef ULONG
+(NTAPI *PHCI_GET_ENDPOINT_STATUS)(
+  PVOID,
+  PVOID);
+
+typedef VOID
+(NTAPI *PHCI_SET_ENDPOINT_STATUS)(
+  PVOID,
+  PVOID,
+  ULONG);
+
+typedef VOID
+(NTAPI *PHCI_RESET_CONTROLLER)(PVOID);
+
+/* Roothub functions */
+typedef VOID
+(NTAPI *PHCI_RH_GET_ROOT_HUB_DATA)(
+  PVOID,
+  PVOID);
+
+typedef MPSTATUS
+(NTAPI *PHCI_RH_GET_STATUS)(
+  PVOID,
+  PUSHORT);
+
+typedef MPSTATUS
+(NTAPI *PHCI_RH_GET_PORT_STATUS)(
+  PVOID,
+  USHORT,
+  PUSBHUB_PORT_STATUS);
+
+typedef MPSTATUS
+(NTAPI *PHCI_RH_GET_HUB_STATUS)(
+  PVOID,
+  PUSB_HUB_STATUS);
+
+typedef MPSTATUS
+(NTAPI *PHCI_RH_SET_FEATURE_PORT_RESET)(
+  PVOID,
+  USHORT);
+
+typedef MPSTATUS
+(NTAPI *PHCI_RH_SET_FEATURE_PORT_POWER)(
+  PVOID,
+  USHORT);
+
+typedef MPSTATUS
+(NTAPI *PHCI_RH_SET_FEATURE_PORT_ENABLE)(
+  PVOID,
+  USHORT);
+
+typedef MPSTATUS
+(NTAPI *PHCI_RH_SET_FEATURE_PORT_SUSPEND)(
+  PVOID,
+  USHORT);
+
+typedef MPSTATUS
+(NTAPI *PHCI_RH_CLEAR_FEATURE_PORT_ENABLE)(
+  PVOID,
+  USHORT);
+
+typedef MPSTATUS
+(NTAPI *PHCI_RH_CLEAR_FEATURE_PORT_POWER)(
+  PVOID,
+  USHORT);
+
+typedef MPSTATUS
+(NTAPI *PHCI_RH_CLEAR_FEATURE_PORT_SUSPEND)(
+  PVOID,
+  USHORT);
+
+typedef MPSTATUS
+(NTAPI *PHCI_RH_CLEAR_FEATURE_PORT_ENABLE_CHANGE)(
+  PVOID,
+  USHORT);
+
+typedef MPSTATUS
+(NTAPI *PHCI_RH_CLEAR_FEATURE_PORT_CONNECT_CHANGE)(
+  PVOID,
+  USHORT);
+
+typedef MPSTATUS
+(NTAPI *PHCI_RH_CLEAR_FEATURE_PORT_RESET_CHANGE)(
+  PVOID,
+  USHORT);
+
+typedef MPSTATUS
+(NTAPI *PHCI_RH_CLEAR_FEATURE_PORT_SUSPEND_CHANGE)(
+  PVOID,
+  USHORT);
+
+typedef MPSTATUS
+(NTAPI *PHCI_RH_CLEAR_FEATURE_PORT_OVERCURRENT_CHANGE)(
+  PVOID,
+  USHORT);
+
+typedef VOID
+(NTAPI *PHCI_RH_DISABLE_IRQ)(PVOID);
+
+typedef VOID
+(NTAPI *PHCI_RH_ENABLE_IRQ)(PVOID);
+
+/* Miniport ioctl functions */
+typedef MPSTATUS
+(NTAPI *PHCI_START_SEND_ONE_PACKET)(
+  PVOID,
+  PVOID,
+  PVOID,
+  PULONG,
+  PVOID,
+  PVOID,
+  ULONG,
+  USBD_STATUS *);
+
+typedef MPSTATUS
+(NTAPI *PHCI_END_SEND_ONE_PACKET)(
+  PVOID,
+  PVOID,
+  PVOID,
+  PULONG,
+  PVOID,
+  PVOID,
+  ULONG,
+  USBD_STATUS *);
+
+typedef MPSTATUS
+(NTAPI *PHCI_PASS_THRU)(
+  PVOID,
+  PVOID,
+  ULONG,
+  PVOID);
+
+/* Port functions */
+typedef ULONG
+(NTAPI *PUSBPORT_DBG_PRINT)(
+  PVOID,
+  ULONG,
+  PCH,
+  ...);
+
+typedef ULONG
+(NTAPI *PUSBPORT_TEST_DEBUG_BREAK)(PVOID);
+
+typedef ULONG
+(NTAPI *PUSBPORT_ASSERT_FAILURE)(
+  PVOID,
+  PVOID,
+  PVOID,
+  ULONG,
+  PCHAR);
+
+typedef MPSTATUS
+(NTAPI *PUSBPORT_GET_MINIPORT_REGISTRY_KEY_VALUE)(
+  PVOID,
+  BOOL,
+  PCWSTR,
+  SIZE_T,
+  PVOID,
+  SIZE_T);
+
+typedef ULONG
+(NTAPI *PUSBPORT_INVALIDATE_ROOT_HUB)(PVOID);
+
+typedef ULONG
+(NTAPI *PUSBPORT_INVALIDATE_ENDPOINT)(
+  PVOID,
+  PVOID);
+
+typedef ULONG
+(NTAPI *PUSBPORT_COMPLETE_TRANSFER)(
+  PVOID,
+  PVOID,
+  PVOID,
+  USBD_STATUS,
+  SIZE_T);
+
+typedef ULONG
+(NTAPI *PUSBPORT_COMPLETE_ISO_TRANSFER)(
+  PVOID,
+  PVOID,
+  PVOID,
+  ULONG);
+
+typedef ULONG
+(NTAPI *PUSBPORT_LOG_ENTRY)(
+  PVOID,
+  ULONG,
+  ULONG,
+  ULONG,
+  ULONG,
+  ULONG);
+
+typedef PVOID
+(NTAPI *PUSBPORT_GET_MAPPED_VIRTUAL_ADDRESS)(
+  PVOID,
+  PVOID,
+  PVOID);
+
+typedef VOID
+(NTAPI ASYNC_TIMER_CALLBACK)(
+  IN PVOID MiniportExtension,
+  IN PVOID CallBackContext);
+
+typedef ULONG
+(NTAPI *PUSBPORT_REQUEST_ASYNC_CALLBACK)(
+  PVOID,
+  ULONG,
+  PVOID,
+  SIZE_T,
+  ASYNC_TIMER_CALLBACK *);
+
+typedef MPSTATUS
+(NTAPI *PUSBPORT_READ_WRITE_CONFIG_SPACE)(
+  PVOID,
+  BOOLEAN,
+  PVOID,
+  ULONG,
+  ULONG);
+
+typedef NTSTATUS
+(NTAPI *PUSBPORT_WAIT)(
+  PVOID,
+  ULONG); 
+
+typedef ULONG
+(NTAPI *PUSBPORT_INVALIDATE_CONTROLLER)(
+  PVOID,
+  ULONG); 
+
+typedef VOID
+(NTAPI *PUSBPORT_BUG_CHECK)(PVOID);
+
+typedef ULONG
+(NTAPI *PUSBPORT_NOTIFY_DOUBLE_BUFFER)(
+  PVOID,
+  PVOID,
+  PVOID,
+  SIZE_T);
+
+/* Miniport functions */
+typedef VOID
+(NTAPI *PHCI_REBALANCE_ENDPOINT)(
+  PVOID,
+  PVOID,
+  PVOID);
+
+typedef VOID
+(NTAPI *PHCI_FLUSH_INTERRUPTS)(PVOID);
+
+typedef MPSTATUS
+(NTAPI *PHCI_RH_CHIRP_ROOT_PORT)(
+  PVOID,
+  USHORT);
+
+typedef VOID
+(NTAPI *PHCI_TAKE_PORT_CONTROL)(PVOID);
+
+#define USB_MINIPORT_VERSION_OHCI 0x01
+#define USB_MINIPORT_VERSION_UHCI 0x02
+#define USB_MINIPORT_VERSION_EHCI 0x03
+
+#define USB_MINIPORT_FLAGS_INTERRUPT    0x0001
+#define USB_MINIPORT_FLAGS_PORT_IO      0x0002
+#define USB_MINIPORT_FLAGS_MEMORY_IO    0x0004
+#define USB_MINIPORT_FLAGS_USB2         0x0010
+#define USB_MINIPORT_FLAGS_DISABLE_SS   0x0020
+#define USB_MINIPORT_FLAGS_NOT_LOCK_INT 0x0040
+#define USB_MINIPORT_FLAGS_POLLING      0x0080
+#define USB_MINIPORT_FLAGS_NO_DMA       0x0100
+#define USB_MINIPORT_FLAGS_WAKE_SUPPORT 0x0200
+
+typedef struct _USBPORT_REGISTRATION_PACKET {
+  ULONG MiniPortVersion;
+  ULONG MiniPortFlags;
+  ULONG MiniPortBusBandwidth;
+  ULONG Reserved1;
+  SIZE_T MiniPortExtensionSize;
+  SIZE_T MiniPortEndpointSize;
+  SIZE_T MiniPortTransferSize;
+  ULONG Reserved2;
+  ULONG Reserved3;
+  SIZE_T MiniPortResourcesSize;
+
+  /* Miniport */
+  PHCI_OPEN_ENDPOINT OpenEndpoint;
+  PHCI_REOPEN_ENDPOINT ReopenEndpoint;
+  PHCI_QUERY_ENDPOINT_REQUIREMENTS QueryEndpointRequirements;
+  PHCI_CLOSE_ENDPOINT CloseEndpoint;
+  PHCI_START_CONTROLLER StartController;
+  PHCI_STOP_CONTROLLER StopController;
+  PHCI_SUSPEND_CONTROLLER SuspendController;
+  PHCI_RESUME_CONTROLLER ResumeController;
+  PHCI_INTERRUPT_SERVICE InterruptService;
+  PHCI_INTERRUPT_DPC InterruptDpc;
+  PHCI_SUBMIT_TRANSFER SubmitTransfer;
+  PHCI_SUBMIT_ISO_TRANSFER SubmitIsoTransfer;
+  PHCI_ABORT_TRANSFER AbortTransfer;
+  PHCI_GET_ENDPOINT_STATE GetEndpointState;
+  PHCI_SET_ENDPOINT_STATE SetEndpointState;
+  PHCI_POLL_ENDPOINT PollEndpoint;
+  PHCI_CHECK_CONTROLLER CheckController;
+  PHCI_GET_32BIT_FRAME_NUMBER Get32BitFrameNumber;
+  PHCI_INTERRUPT_NEXT_SOF InterruptNextSOF;
+  PHCI_ENABLE_INTERRUPTS EnableInterrupts;
+  PHCI_DISABLE_INTERRUPTS DisableInterrupts;
+  PHCI_POLL_CONTROLLER PollController;
+  PHCI_SET_ENDPOINT_DATA_TOGGLE SetEndpointDataToggle;
+  PHCI_GET_ENDPOINT_STATUS GetEndpointStatus;
+  PHCI_SET_ENDPOINT_STATUS SetEndpointStatus;
+  PHCI_RESET_CONTROLLER ResetController;
+
+  /* Roothub */
+  PHCI_RH_GET_ROOT_HUB_DATA RH_GetRootHubData;
+  PHCI_RH_GET_STATUS RH_GetStatus;
+  PHCI_RH_GET_PORT_STATUS RH_GetPortStatus;
+  PHCI_RH_GET_HUB_STATUS RH_GetHubStatus;
+  PHCI_RH_SET_FEATURE_PORT_RESET RH_SetFeaturePortReset;
+  PHCI_RH_SET_FEATURE_PORT_POWER RH_SetFeaturePortPower;
+  PHCI_RH_SET_FEATURE_PORT_ENABLE RH_SetFeaturePortEnable;
+  PHCI_RH_SET_FEATURE_PORT_SUSPEND RH_SetFeaturePortSuspend;
+  PHCI_RH_CLEAR_FEATURE_PORT_ENABLE RH_ClearFeaturePortEnable;
+  PHCI_RH_CLEAR_FEATURE_PORT_POWER RH_ClearFeaturePortPower;
+  PHCI_RH_CLEAR_FEATURE_PORT_SUSPEND RH_ClearFeaturePortSuspend;
+  PHCI_RH_CLEAR_FEATURE_PORT_ENABLE_CHANGE RH_ClearFeaturePortEnableChange;
+  PHCI_RH_CLEAR_FEATURE_PORT_CONNECT_CHANGE RH_ClearFeaturePortConnectChange;
+  PHCI_RH_CLEAR_FEATURE_PORT_RESET_CHANGE RH_ClearFeaturePortResetChange;
+  PHCI_RH_CLEAR_FEATURE_PORT_SUSPEND_CHANGE RH_ClearFeaturePortSuspendChange;
+  PHCI_RH_CLEAR_FEATURE_PORT_OVERCURRENT_CHANGE RH_ClearFeaturePortOvercurrentChange;
+  PHCI_RH_DISABLE_IRQ RH_DisableIrq;
+  PHCI_RH_ENABLE_IRQ RH_EnableIrq;
+
+  /* Miniport ioctl */
+  PHCI_START_SEND_ONE_PACKET StartSendOnePacket;
+  PHCI_END_SEND_ONE_PACKET EndSendOnePacket;
+  PHCI_PASS_THRU PassThru;
+
+  /* Port */
+  PUSBPORT_DBG_PRINT UsbPortDbgPrint;
+  PUSBPORT_TEST_DEBUG_BREAK UsbPortTestDebugBreak;
+  PUSBPORT_ASSERT_FAILURE UsbPortAssertFailure;
+  PUSBPORT_GET_MINIPORT_REGISTRY_KEY_VALUE UsbPortGetMiniportRegistryKeyValue;
+  PUSBPORT_INVALIDATE_ROOT_HUB UsbPortInvalidateRootHub;
+  PUSBPORT_INVALIDATE_ENDPOINT UsbPortInvalidateEndpoint;
+  PUSBPORT_COMPLETE_TRANSFER UsbPortCompleteTransfer;
+  PUSBPORT_COMPLETE_ISO_TRANSFER UsbPortCompleteIsoTransfer;
+  PUSBPORT_LOG_ENTRY UsbPortLogEntry;
+  PUSBPORT_GET_MAPPED_VIRTUAL_ADDRESS UsbPortGetMappedVirtualAddress;
+  PUSBPORT_REQUEST_ASYNC_CALLBACK UsbPortRequestAsyncCallback;
+  PUSBPORT_READ_WRITE_CONFIG_SPACE UsbPortReadWriteConfigSpace;
+  PUSBPORT_WAIT UsbPortWait;
+  PUSBPORT_INVALIDATE_CONTROLLER UsbPortInvalidateController;
+  PUSBPORT_BUG_CHECK UsbPortBugCheck;
+  PUSBPORT_NOTIFY_DOUBLE_BUFFER UsbPortNotifyDoubleBuffer;
+
+  /* Miniport */
+  PHCI_REBALANCE_ENDPOINT RebalanceEndpoint;
+  PHCI_FLUSH_INTERRUPTS FlushInterrupts;
+  PHCI_RH_CHIRP_ROOT_PORT RH_ChirpRootPort;
+  PHCI_TAKE_PORT_CONTROL TakePortControl;
+  ULONG Reserved4;
+  ULONG Reserved5;
+} USBPORT_REGISTRATION_PACKET, *PUSBPORT_REGISTRATION_PACKET;
+
+typedef struct _USBPORT_MINIPORT_INTERFACE {
+  PDRIVER_OBJECT DriverObject;
+  LIST_ENTRY DriverLink;
+  PDRIVER_UNLOAD DriverUnload;
+  ULONG Version;
+  USBPORT_REGISTRATION_PACKET Packet;
+} USBPORT_MINIPORT_INTERFACE, *PUSBPORT_MINIPORT_INTERFACE;
+
+C_ASSERT(sizeof(USBPORT_MINIPORT_INTERFACE) == 336);
+
+typedef struct _USBPORT_ENDPOINT_PROPERTIES {
+  USHORT DeviceAddress;
+  USHORT EndpointAddress;
+  USHORT TotalMaxPacketSize; // TransactionPerMicroframe * MaxPacketSize
+  UCHAR Period;
+  UCHAR Reserved1;
+  USB_DEVICE_SPEED DeviceSpeed;
+  ULONG UsbBandwidth;
+  ULONG ScheduleOffset;
+  ULONG TransferType;
+  ULONG Direction;
+  ULONG_PTR BufferVA;
+  ULONG_PTR BufferPA;
+  ULONG BufferLength;
+  ULONG Reserved3;
+  ULONG MaxTransferSize;
+  USHORT HubAddr;
+  USHORT PortNumber;
+  UCHAR InterruptScheduleMask;
+  UCHAR SplitCompletionMask;
+  UCHAR TransactionPerMicroframe; // 1 + additional transactions. Total: from 1 to 3)
+  UCHAR Reserved4;
+  ULONG MaxPacketSize;
+  ULONG Reserved6;
+} USBPORT_ENDPOINT_PROPERTIES, *PUSBPORT_ENDPOINT_PROPERTIES;
+
+C_ASSERT(sizeof(USBPORT_ENDPOINT_PROPERTIES) == 64);
+
+typedef struct _USBPORT_SCATTER_GATHER_ELEMENT {
+  PHYSICAL_ADDRESS SgPhysicalAddress;
+  ULONG Reserved1;
+  ULONG SgTransferLength;
+  ULONG SgOffset;
+  ULONG Reserved2;
+} USBPORT_SCATTER_GATHER_ELEMENT, *PUSBPORT_SCATTER_GATHER_ELEMENT;
+
+C_ASSERT(sizeof(USBPORT_SCATTER_GATHER_ELEMENT) == 24);
+
+typedef struct _USBPORT_SCATTER_GATHER_LIST {
+  ULONG Flags;
+  ULONG_PTR CurrentVa;
+  PVOID MappedSystemVa;
+  ULONG SgElementCount;
+  USBPORT_SCATTER_GATHER_ELEMENT SgElement[1];
+} USBPORT_SCATTER_GATHER_LIST, *PUSBPORT_SCATTER_GATHER_LIST;
+
+C_ASSERT(sizeof(USBPORT_SCATTER_GATHER_LIST) == 40);
+
+typedef struct _USBPORT_TRANSFER_PARAMETERS {
+  ULONG TransferFlags;
+  ULONG TransferBufferLength;
+  ULONG TransferCounter;
+  ULONG Reserved1;
+  ULONG Reserved2;
+  USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
+} USBPORT_TRANSFER_PARAMETERS, *PUSBPORT_TRANSFER_PARAMETERS;
+
+C_ASSERT(sizeof(USBPORT_TRANSFER_PARAMETERS) == 28);
+
+typedef struct _USBPORT_ROOT_HUB_DATA {
+  ULONG NumberOfPorts;
+  ULONG HubCharacteristics;
+  ULONG PowerOnToPowerGood;
+  ULONG HubControlCurrent;
+} USBPORT_ROOT_HUB_DATA, *PUSBPORT_ROOT_HUB_DATA;
+
+C_ASSERT(sizeof(USBPORT_ROOT_HUB_DATA) == 16);
+
+ULONG
+NTAPI
+USBPORT_GetHciMn(VOID);
+
+NTSTATUS
+NTAPI
+USBPORT_RegisterUSBPortDriver(
+  IN PDRIVER_OBJECT DriverObject,
+  IN ULONG Version,
+  IN PUSBPORT_REGISTRATION_PACKET RegistrationPacket);
+
+#endif /* USBMPORT_H__ */