add_subdirectory(usbehci)
add_subdirectory(usbhub)
add_subdirectory(usbohci)
+add_subdirectory(usbport)
add_subdirectory(usbstor)
add_subdirectory(usbuhci)
--- /dev/null
+
+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)
--- /dev/null
+#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");
+}
+
--- /dev/null
+#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
--- /dev/null
+#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;
+}
--- /dev/null
+/* 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 */
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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
--- /dev/null
+#include "usbport.h"
+
+#define NDEBUG
+#include <debug.h>
+
+#define NDEBUG_USBPORT_CORE
+#include "usbdebug.h"
+
+RHSTATUS
+NTAPI
+USBPORT_MPStatusToRHStatus(IN MPSTATUS MPStatus)
+{
+ RHSTATUS RHStatus = RH_STATUS_SUCCESS;
+
+ //DPRINT("USBPORT_MPStatusToRHStatus: MPStatus - %x\n", MPStatus);
+
+ if (MPStatus)
+ {
+ RHStatus = (MPStatus != MP_STATUS_FAILURE);
+ ++RHStatus;
+ }
+
+ return RHStatus;
+}
+
+MPSTATUS
+NTAPI
+USBPORT_RH_SetFeatureUSB2PortPower(IN PDEVICE_OBJECT FdoDevice,
+ IN USHORT Port)
+{
+ PUSBPORT_DEVICE_EXTENSION FdoExtension;
+ PUSBPORT_REGISTRATION_PACKET Packet;
+ PDEVICE_RELATIONS CompanionControllersList;
+ PUSBPORT_REGISTRATION_PACKET CompanionPacket;
+ PDEVICE_OBJECT CompanionFdoDevice;
+ PUSBPORT_DEVICE_EXTENSION CompanionFdoExtension;
+ PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+ USHORT ix;
+ PDEVICE_OBJECT * Entry;
+ ULONG NumController = 0;
+
+ DPRINT("USBPORT_RootHub_PowerUsb2Port: FdoDevice - %p, Port - %p\n",
+ FdoDevice,
+ Port);
+
+ FdoExtension = FdoDevice->DeviceExtension;
+ Packet = &FdoExtension->MiniPortInterface->Packet;
+
+ CompanionControllersList = USBPORT_FindCompanionControllers(FdoDevice,
+ FALSE,
+ TRUE);
+
+ if (!CompanionControllersList)
+ {
+ Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt, Port);
+ return MP_STATUS_SUCCESS;
+ }
+
+ Entry = &CompanionControllersList->Objects[0];
+
+ while (NumController < CompanionControllersList->Count)
+ {
+ CompanionFdoDevice = *Entry;
+
+ CompanionFdoExtension = CompanionFdoDevice->DeviceExtension;
+ CompanionPacket = &CompanionFdoExtension->MiniPortInterface->Packet;
+
+ PdoExtension = CompanionFdoExtension->RootHubPdo->DeviceExtension;
+
+ for (ix = 0;
+ (PdoExtension->CommonExtension.PnpStateFlags & USBPORT_PNP_STATE_STARTED) &&
+ ix < PdoExtension->RootHubDescriptors->Descriptor.bNumberOfPorts;
+ ++ix)
+ {
+ CompanionPacket->RH_SetFeaturePortPower(CompanionFdoExtension->MiniPortExt,
+ ix + 1);
+ }
+
+ ++NumController;
+ ++Entry;
+ }
+
+ Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt, Port);
+
+ if (CompanionControllersList)
+ {
+ ExFreePoolWithTag(CompanionControllersList, USB_PORT_TAG);
+ }
+
+ return MP_STATUS_SUCCESS;
+}
+
+RHSTATUS
+NTAPI
+USBPORT_RootHubClassCommand(IN PDEVICE_OBJECT FdoDevice,
+ IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
+ IN PVOID Buffer,
+ IN PULONG BufferLength)
+{
+ PUSBPORT_DEVICE_EXTENSION FdoExtension;
+ PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+ PUSBPORT_REGISTRATION_PACKET Packet;
+ USHORT Port;
+ USHORT Feature;
+ MPSTATUS MPStatus;
+ RHSTATUS RHStatus = RH_STATUS_UNSUCCESSFUL;
+ KIRQL OldIrql;
+
+ DPRINT("USBPORT_RootHubClassCommand: USB command - %x, *BufferLength - %x\n",
+ SetupPacket->bRequest,
+ *BufferLength);
+
+ FdoExtension = FdoDevice->DeviceExtension;
+ PdoExtension = FdoExtension->RootHubPdo->DeviceExtension;
+ Packet = &FdoExtension->MiniPortInterface->Packet;
+
+ Port = SetupPacket->wIndex.W;
+
+ switch (SetupPacket->bRequest)
+ {
+ case USB_REQUEST_GET_STATUS:
+ {
+ if (!Buffer)
+ {
+ return RHStatus;
+ }
+
+ *(PULONG)Buffer = 0;
+
+ if (SetupPacket->bmRequestType.Recipient == BMREQUEST_TO_OTHER)
+ {
+ ASSERT(*BufferLength >= 4);
+
+ if (Port > PdoExtension->RootHubDescriptors->Descriptor.bNumberOfPorts ||
+ Port <= 0 ||
+ SetupPacket->wLength < 4)
+ {
+ return RHStatus;
+ }
+
+ KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+
+ MPStatus = Packet->RH_GetPortStatus(FdoExtension->MiniPortExt,
+ SetupPacket->wIndex.W,
+ Buffer);
+
+ KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+ }
+ else
+ {
+ KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+
+ MPStatus = Packet->RH_GetHubStatus(FdoExtension->MiniPortExt,
+ Buffer);
+
+ KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+ }
+
+ RHStatus = USBPORT_MPStatusToRHStatus(MPStatus);
+ break;
+ }
+
+ case USB_REQUEST_CLEAR_FEATURE:
+ Feature = SetupPacket->wValue.W;
+
+ if ((SetupPacket->bmRequestType.Recipient) != USBPORT_RECIPIENT_ROOT_PORT)
+ {
+ if (Feature == FEATURE_C_HUB_LOCAL_POWER)
+ {
+ RHStatus = RH_STATUS_SUCCESS;
+ return RHStatus;
+ }
+
+ if (Feature == FEATURE_C_HUB_OVER_CURRENT)
+ {
+ MPStatus = Packet->RH_ClearFeaturePortOvercurrentChange(FdoExtension->MiniPortExt,
+ 0);
+ RHStatus = USBPORT_MPStatusToRHStatus(MPStatus);
+ return RHStatus;
+ }
+
+ DbgBreakPoint();
+ return RHStatus;
+ }
+
+ switch (Feature)
+ {
+ case FEATURE_PORT_ENABLE:
+ MPStatus = Packet->RH_ClearFeaturePortEnable(FdoExtension->MiniPortExt,
+ Port);
+ break;
+
+ case FEATURE_PORT_SUSPEND:
+ MPStatus = Packet->RH_ClearFeaturePortSuspend(FdoExtension->MiniPortExt,
+ Port);
+ break;
+
+ case FEATURE_PORT_POWER:
+ MPStatus = Packet->RH_ClearFeaturePortPower(FdoExtension->MiniPortExt,
+ Port);
+ break;
+
+ case FEATURE_C_PORT_CONNECTION:
+ MPStatus = Packet->RH_ClearFeaturePortConnectChange(FdoExtension->MiniPortExt,
+ Port);
+ break;
+
+ case FEATURE_C_PORT_ENABLE:
+ MPStatus = Packet->RH_ClearFeaturePortEnableChange(FdoExtension->MiniPortExt,
+ Port);
+ break;
+
+ case FEATURE_C_PORT_SUSPEND:
+ MPStatus = Packet->RH_ClearFeaturePortSuspendChange(FdoExtension->MiniPortExt,
+ Port);
+ break;
+
+ case FEATURE_C_PORT_OVER_CURRENT:
+ MPStatus = Packet->RH_ClearFeaturePortOvercurrentChange(FdoExtension->MiniPortExt,
+ Port);
+ break;
+
+ case FEATURE_C_PORT_RESET:
+ MPStatus = Packet->RH_ClearFeaturePortResetChange(FdoExtension->MiniPortExt,
+ Port);
+ break;
+
+ default:
+ DPRINT1("USBPORT_RootHubClassCommand: Not supported feature - %x\n",
+ Feature);
+ return RHStatus;
+ }
+
+ RHStatus = USBPORT_MPStatusToRHStatus(MPStatus);
+ break;
+
+ case USB_REQUEST_SET_FEATURE:
+ if (SetupPacket->bmRequestType.Recipient != USBPORT_RECIPIENT_ROOT_PORT)
+ {
+ return RHStatus;
+ }
+
+ Feature = SetupPacket->wValue.W;
+
+ switch (Feature)
+ {
+ case FEATURE_PORT_ENABLE:
+ MPStatus = Packet->RH_SetFeaturePortEnable(FdoExtension->MiniPortExt,
+ Port);
+ break;
+
+ case FEATURE_PORT_SUSPEND:
+ MPStatus = Packet->RH_SetFeaturePortSuspend(FdoExtension->MiniPortExt,
+ Port);
+ break;
+
+ case FEATURE_PORT_RESET:
+ MPStatus = Packet->RH_SetFeaturePortReset(FdoExtension->MiniPortExt,
+ Port);
+ break;
+
+ case FEATURE_PORT_POWER:
+ if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
+ {
+ MPStatus = USBPORT_RH_SetFeatureUSB2PortPower(FdoDevice, Port);
+ }
+ else
+ {
+ MPStatus = Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt,
+ Port);
+ }
+
+ break;
+
+ default:
+ DPRINT1("USBPORT_RootHubClassCommand: Not supported feature - %x\n",
+ Feature);
+ return RHStatus;
+ }
+
+ RHStatus = USBPORT_MPStatusToRHStatus(MPStatus);
+ break;
+
+ case USB_REQUEST_GET_DESCRIPTOR:
+ if (Buffer &&
+ SetupPacket->wValue.W == 0 &&
+ SetupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST)
+ {
+ SIZE_T DescriptorLength;
+
+ DescriptorLength = PdoExtension->RootHubDescriptors->Descriptor.bDescriptorLength;
+
+ if (*BufferLength < DescriptorLength)
+ DescriptorLength = *BufferLength;
+
+ RtlCopyMemory(Buffer,
+ &PdoExtension->RootHubDescriptors->Descriptor,
+ DescriptorLength);
+
+ *BufferLength = DescriptorLength;
+ RHStatus = RH_STATUS_SUCCESS;
+ }
+
+ break;
+
+ default:
+ DPRINT1("USBPORT_RootHubClassCommand: Not supported USB request - %x\n",
+ SetupPacket->bRequest);
+ //USB_REQUEST_SET_ADDRESS 0x05
+ //USB_REQUEST_SET_DESCRIPTOR 0x07
+ //USB_REQUEST_GET_CONFIGURATION 0x08
+ //USB_REQUEST_SET_CONFIGURATION 0x09
+ //USB_REQUEST_GET_INTERFACE 0x0A
+ //USB_REQUEST_SET_INTERFACE 0x0B
+ //USB_REQUEST_SYNC_FRAME 0x0C
+ break;
+ }
+
+ return RHStatus;
+}
+
+RHSTATUS
+NTAPI
+USBPORT_RootHubStandardCommand(IN PDEVICE_OBJECT FdoDevice,
+ IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
+ IN PVOID Buffer,
+ IN OUT PULONG TransferLength)
+{
+ PUSBPORT_DEVICE_EXTENSION FdoExtension;
+ PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+ PUSBPORT_REGISTRATION_PACKET Packet;
+ SIZE_T Length;
+ PVOID Descriptor;
+ SIZE_T DescriptorLength;
+ MPSTATUS MPStatus;
+ RHSTATUS RHStatus = RH_STATUS_UNSUCCESSFUL;
+ KIRQL OldIrql;
+
+ DPRINT("USBPORT_RootHubStandardCommand: USB command - %x, TransferLength - %p\n",
+ SetupPacket->bRequest,
+ TransferLength);
+
+ FdoExtension = FdoDevice->DeviceExtension;
+ PdoExtension = FdoExtension->RootHubPdo->DeviceExtension;
+ Packet = &FdoExtension->MiniPortInterface->Packet;
+
+ switch (SetupPacket->bRequest)
+ {
+ case USB_REQUEST_GET_DESCRIPTOR:
+ if (SetupPacket->wValue.LowByte ||
+ !(SetupPacket->bmRequestType.Dir))
+ {
+ return RHStatus;
+ }
+
+ switch (SetupPacket->wValue.HiByte)
+ {
+ case USB_DEVICE_DESCRIPTOR_TYPE:
+ Descriptor = &PdoExtension->RootHubDescriptors->DeviceDescriptor;
+ DescriptorLength = sizeof(USB_DEVICE_DESCRIPTOR);
+ break;
+
+ case USB_CONFIGURATION_DESCRIPTOR_TYPE:
+ Descriptor = &PdoExtension->RootHubDescriptors->ConfigDescriptor;
+ DescriptorLength = sizeof(USB_CONFIGURATION_DESCRIPTOR) +
+ sizeof(USB_INTERFACE_DESCRIPTOR) +
+ sizeof(USB_ENDPOINT_DESCRIPTOR);
+ break;
+
+ default:
+ DPRINT1("USBPORT_RootHubStandardCommand: Not supported Descriptor Type - %x\n",
+ SetupPacket->wValue.HiByte);
+ return RHStatus;
+ }
+
+ if (!Descriptor)
+ {
+ return RHStatus;
+ }
+
+ if (*TransferLength >= DescriptorLength)
+ Length = DescriptorLength;
+ else
+ Length = *TransferLength;
+
+ RtlCopyMemory(Buffer, Descriptor, Length);
+ *TransferLength = Length;
+
+ RHStatus = RH_STATUS_SUCCESS;
+ break;
+
+ case USB_REQUEST_GET_STATUS:
+ if (!SetupPacket->wValue.W &&
+ SetupPacket->wLength == sizeof(USHORT) &&
+ !SetupPacket->wIndex.W &&
+ SetupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST)
+ {
+ KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+
+ MPStatus = Packet->RH_GetStatus(FdoExtension->MiniPortExt,
+ Buffer);
+
+ KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+
+ *TransferLength = sizeof(USHORT);
+ RHStatus = USBPORT_MPStatusToRHStatus(MPStatus);
+ }
+
+ break;
+
+ case USB_REQUEST_GET_CONFIGURATION:
+ if (SetupPacket->wValue.W ||
+ SetupPacket->wIndex.W ||
+ SetupPacket->wLength != 1 ||
+ SetupPacket->bmRequestType.Dir == BMREQUEST_HOST_TO_DEVICE)
+ {
+ return RHStatus;
+ }
+
+ Length = 0;
+
+ if (*TransferLength >= 1)
+ {
+ Length = 1;
+ RtlCopyMemory(Buffer, &PdoExtension->ConfigurationValue, Length);
+ }
+
+ *TransferLength = Length;
+
+ RHStatus = RH_STATUS_SUCCESS;
+ break;
+
+ case USB_REQUEST_SET_CONFIGURATION:
+ if (!SetupPacket->wIndex.W &&
+ !SetupPacket->wLength &&
+ !(SetupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST))
+ {
+ if (SetupPacket->wValue.W == 0 ||
+ SetupPacket->wValue.W ==
+ PdoExtension->RootHubDescriptors->ConfigDescriptor.bConfigurationValue)
+ {
+ PdoExtension->ConfigurationValue = SetupPacket->wValue.LowByte;
+ RHStatus = RH_STATUS_SUCCESS;
+ }
+ }
+
+ break;
+
+ case USB_REQUEST_SET_ADDRESS:
+ if (!SetupPacket->wIndex.W &&
+ !SetupPacket->wLength &&
+ !(SetupPacket->bmRequestType.Dir))
+ {
+ PdoExtension->DeviceHandle.DeviceAddress = SetupPacket->wValue.LowByte;
+ RHStatus = RH_STATUS_SUCCESS;
+ break;
+ }
+
+ break;
+
+ default:
+ DPRINT1("USBPORT_RootHubStandardCommand: Not supported USB request - %x\n",
+ SetupPacket->bRequest);
+ //USB_REQUEST_CLEAR_FEATURE 0x01
+ //USB_REQUEST_SET_FEATURE 0x03
+ //USB_REQUEST_SET_DESCRIPTOR 0x07
+ //USB_REQUEST_GET_INTERFACE 0x0A
+ //USB_REQUEST_SET_INTERFACE 0x0B
+ //USB_REQUEST_SYNC_FRAME 0x0C
+ break;
+ }
+
+ return RHStatus;
+}
+
+RHSTATUS
+NTAPI
+USBPORT_RootHubEndpoint0(IN PUSBPORT_TRANSFER Transfer)
+{
+ PDEVICE_OBJECT FdoDevice;
+ SIZE_T TransferLength;
+ PVOID Buffer;
+ PURB Urb;
+ PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
+ UCHAR Type;
+ RHSTATUS RHStatus;
+
+ DPRINT("USBPORT_RootHubEndpoint0: Transfer - %p\n", Transfer);
+
+ TransferLength = Transfer->TransferParameters.TransferBufferLength;
+ Urb = Transfer->Urb;
+ FdoDevice = Transfer->Endpoint->FdoDevice;
+
+ if (TransferLength > 0)
+ Buffer = Urb->UrbControlTransfer.TransferBufferMDL->MappedSystemVa;
+ else
+ Buffer = NULL;
+
+ SetupPacket = (PUSB_DEFAULT_PIPE_SETUP_PACKET)Urb->UrbControlTransfer.SetupPacket;
+
+ Type = SetupPacket->bmRequestType.Type;
+
+ if (Type == BMREQUEST_STANDARD)
+ {
+ RHStatus = USBPORT_RootHubStandardCommand(FdoDevice,
+ SetupPacket,
+ Buffer,
+ &TransferLength);
+ }
+ else if (Type == BMREQUEST_CLASS)
+ {
+ RHStatus = USBPORT_RootHubClassCommand(FdoDevice,
+ SetupPacket,
+ Buffer,
+ &TransferLength);
+ }
+ else
+ {
+ return RH_STATUS_UNSUCCESSFUL;
+ }
+
+ if (RHStatus == RH_STATUS_SUCCESS)
+ Transfer->CompletedTransferLen = TransferLength;
+
+ return RHStatus;
+}
+
+RHSTATUS
+NTAPI
+USBPORT_RootHubSCE(IN PUSBPORT_TRANSFER Transfer)
+{
+ PUSBPORT_ENDPOINT Endpoint;
+ PUSBPORT_DEVICE_EXTENSION FdoExtension;
+ PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
+ PUSBPORT_REGISTRATION_PACKET Packet;
+ ULONG TransferLength;
+ USBHUB_PORT_STATUS PortStatus;
+ USB_HUB_STATUS HubStatus;
+ PVOID Buffer;
+ PULONG AddressBitMap;
+ ULONG Port;
+ PURB Urb;
+ RHSTATUS RHStatus = RH_STATUS_NO_CHANGES;
+ PUSB_HUB_DESCRIPTOR HubDescriptor;
+ UCHAR NumberOfPorts;
+
+ DPRINT("USBPORT_RootHubSCE: Transfer - %p\n", Transfer);
+
+ Endpoint = Transfer->Endpoint;
+
+ FdoExtension = Endpoint->FdoDevice->DeviceExtension;
+ PdoExtension = FdoExtension->RootHubPdo->DeviceExtension;
+ Packet = &FdoExtension->MiniPortInterface->Packet;
+
+ HubDescriptor = &PdoExtension->RootHubDescriptors->Descriptor;
+ NumberOfPorts = HubDescriptor->bNumberOfPorts;
+
+ PortStatus.AsULONG = 0;
+ HubStatus.AsUshort16 = 0;
+
+ Urb = Transfer->Urb;
+ TransferLength = Transfer->TransferParameters.TransferBufferLength;
+
+ if (TransferLength)
+ {
+ Buffer = Urb->UrbControlTransfer.TransferBufferMDL->MappedSystemVa;
+ }
+ else
+ {
+ Buffer = NULL;
+ }
+
+ /* Check parameters */
+
+ if (!Buffer)
+ {
+ /* Not valid parameter */
+ DPRINT1("USBPORT_RootHubSCE: Error! Buffer is NULL\n");
+ return RH_STATUS_UNSUCCESSFUL;
+ }
+
+ if ((TransferLength < (NumberOfPorts / 8 + 1)))
+ {
+ /* Not valid parameters */
+ DPRINT1("USBPORT_RootHubSCE: Error! TransferLength - %x, NumberOfPorts - %x\n",
+ TransferLength,
+ NumberOfPorts);
+
+ return RH_STATUS_UNSUCCESSFUL;
+ }
+
+ RtlZeroMemory(Buffer, TransferLength);
+
+ AddressBitMap = Buffer;
+
+ /* Scan all the ports for changes */
+ for (Port = 1; Port <= NumberOfPorts; Port++)
+ {
+ DPRINT_CORE("USBPORT_RootHubSCE: Port - %p\n", Port);
+
+ /* Request the port status from miniport */
+ if (Packet->RH_GetPortStatus(FdoExtension->MiniPortExt,
+ Port,
+ &PortStatus))
+ {
+ /* Miniport returned an error */
+ DPRINT1("USBPORT_RootHubSCE: RH_GetPortStatus failed\n");
+ return RH_STATUS_UNSUCCESSFUL;
+ }
+
+ if (PortStatus.UsbPortStatusChange.ConnectStatusChange ||
+ PortStatus.UsbPortStatusChange.PortEnableDisableChange ||
+ PortStatus.UsbPortStatusChange.SuspendChange ||
+ PortStatus.UsbPortStatusChange.OverCurrentIndicatorChange ||
+ PortStatus.UsbPortStatusChange.ResetChange)
+ {
+ /* At the port status there is a change */
+ AddressBitMap[Port >> 5] |= 1 << (Port & 0x1F);
+ RHStatus = RH_STATUS_SUCCESS;
+ }
+ }
+
+ /* Request the hub status from miniport */
+ if (!Packet->RH_GetHubStatus(FdoExtension->MiniPortExt, &HubStatus))
+ {
+ if (HubStatus.AsUshort16 & (HUB_STATUS_CHANGE_LOCAL_POWER |
+ HUB_STATUS_CHANGE_OVERCURRENT))
+ {
+ /* At the hub status there is a change */
+ AddressBitMap[0] |= 1;
+ &nb