reactos/drivers/usb/usbehci/pdo.c
Timo Kreuzer 5eb25b5c24 Create a branch for audio work
svn path=/branches/audio-bringup/; revision=49478
2010-11-05 11:04:48 +00:00

738 lines
28 KiB
C

/*
* PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
* LICENSE: GPL - See COPYING in the top level directory
* FILE: drivers/usb/usbehci/pdo.c
* PURPOSE: USB EHCI device driver.
* PROGRAMMERS:
* Michael Martin (michael.martin@reactos.org)
*/
#define INITGUID
#include "usbehci.h"
#include <hubbusif.h>
#include <usbbusif.h>
#include "usbiffn.h"
#include <wdmguid.h>
#include <stdio.h>
#include <debug.h>
/* Lifted from Linux with slight changes */
const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR [] =
{
0x12, /* bLength; */
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType; Device */
0x00, 0x20, /* bcdUSB; v1.1 */
USB_DEVICE_CLASS_HUB, /* bDeviceClass; HUB_CLASSCODE */
0x01, /* bDeviceSubClass; */
0x00, /* bDeviceProtocol; [ low/full speeds only ] */
0x08, /* bMaxPacketSize0; 8 Bytes */
/* Fill Vendor and Product in when init root hub */
0x00, 0x00, /* idVendor; */
0x00, 0x00, /* idProduct; */
0x00, 0x00, /* bcdDevice */
0x00, /* iManufacturer; */
0x00, /* iProduct; */
0x00, /* iSerialNumber; */
0x01 /* bNumConfigurations; */
};
const UCHAR ROOTHUB2_CONFIGURATION_DESCRIPTOR [] =
{
/* one configuration */
0x09, /* bLength; */
0x02, /* bDescriptorType; Configuration */
0x19, 0x00, /* wTotalLength; */
0x01, /* bNumInterfaces; (1) */
0x23, /* bConfigurationValue; */
0x00, /* iConfiguration; */
0x40, /* bmAttributes;
Bit 7: must be set,
6: Self-powered,
5: Remote wakeup,
4..0: reserved */
0x00 /* MaxPower; */
};
const UCHAR ROOTHUB2_INTERFACE_DESCRIPTOR [] =
{
/* one interface */
0x09, /* bLength: Interface; */
0x04, /* bDescriptorType; Interface */
0x00, /* bInterfaceNumber; */
0x00, /* bAlternateSetting; */
0x01, /* bNumEndpoints; */
0x09, /* bInterfaceClass; HUB_CLASSCODE */
0x01, /* bInterfaceSubClass; */
0x00, /* bInterfaceProtocol: */
0x00 /* iInterface; */
};
const UCHAR ROOTHUB2_ENDPOINT_DESCRIPTOR [] =
{
/* one endpoint (status change endpoint) */
0x07, /* bLength; */
0x05, /* bDescriptorType; Endpoint */
0x81, /* bEndpointAddress; IN Endpoint 1 */
0x03, /* bmAttributes; Interrupt */
0x08, 0x00, /* wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
0xFF /* bInterval; (255ms -- usb 2.0 spec) */
};
/* FIXME: Do something better */
VOID NTAPI
UrbWorkerThread(PVOID Context)
{
PPDO_DEVICE_EXTENSION PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Context;
NTSTATUS Status;
LARGE_INTEGER DueTime;
PVOID PollEvents[] = { (PVOID) &PdoDeviceExtension->QueueDrainedEvent, (PVOID) &PdoDeviceExtension->Timer };
DueTime.QuadPart = 0;
KeInitializeTimerEx(&PdoDeviceExtension->Timer, SynchronizationTimer);
KeSetTimerEx(&PdoDeviceExtension->Timer, DueTime, 100, NULL);
while (TRUE)
{
Status = KeWaitForMultipleObjects(2, PollEvents, WaitAll, Executive, KernelMode, FALSE, NULL, NULL);
if (!PdoDeviceExtension->HaltQueue)
KeResetEvent(&PdoDeviceExtension->QueueDrainedEvent);
CompletePendingURBRequest(PdoDeviceExtension);
}
DPRINT1("Thread terminated\n");
}
NTSTATUS NTAPI
PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PPDO_DEVICE_EXTENSION PdoDeviceExtension;
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
PIO_STACK_LOCATION Stack = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
ULONG_PTR Information = 0;
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION) PdoDeviceExtension->ControllerFdo->DeviceExtension;
ASSERT(PdoDeviceExtension->Common.IsFdo == FALSE);
Stack = IoGetCurrentIrpStackLocation(Irp);
switch(Stack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_INTERNAL_USB_SUBMIT_URB:
{
PUSB_DEVICE UsbDevice = NULL;
URB *Urb;
ULONG i;
Urb = (PURB) Stack->Parameters.Others.Argument1;
UsbDevice = Urb->UrbHeader.UsbdDeviceHandle;
if (UsbDevice == NULL)
UsbDevice = PdoDeviceExtension->UsbDevices[0];
if ((Urb->UrbHeader.Function == URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) &&
(UsbDevice == PdoDeviceExtension->UsbDevices[0]))
{
if (Urb->UrbBulkOrInterruptTransfer.PipeHandle == &UsbDevice->ActiveInterface->EndPoints[0]->EndPointDescriptor)
{
DPRINT1("PipeHandle doesnt match SCE PipeHandle\n");
}
/* Queue the Irp first */
QueueURBRequest(PdoDeviceExtension, Irp);
/* Check if there is any connected devices */
for (i = 0; i < PdoDeviceExtension->NumberOfPorts; i++)
{
if (PdoDeviceExtension->Ports[i].PortChange == 0x01)
{
DPRINT1("Inform hub driver that port %d has changed\n", i+1);
((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1 << ((i + 1) & 7);
Information = 0;
Status = STATUS_SUCCESS;
/* Assume URB success */
Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
/* Set the DeviceHandle to the Internal Device */
Urb->UrbHeader.UsbdDeviceHandle = UsbDevice;
/* Request handled, Remove it from the queue */
RemoveUrbRequest(PdoDeviceExtension, Irp);
break;
}
}
if (Status == STATUS_SUCCESS) break;
DPRINT1("Queueing IRP\n");
IoMarkIrpPending(Irp);
Status = STATUS_PENDING;
break;
}
Status = HandleUrbRequest(PdoDeviceExtension, Irp);
break;
}
case IOCTL_INTERNAL_USB_CYCLE_PORT:
{
DPRINT1("IOCTL_INTERNAL_USB_CYCLE_PORT\n");
break;
}
case IOCTL_INTERNAL_USB_ENABLE_PORT:
{
DPRINT1("IOCTL_INTERNAL_USB_ENABLE_PORT\n");
Information = 0;
Status = STATUS_SUCCESS;
break;
}
case IOCTL_INTERNAL_USB_GET_BUS_INFO:
{
DPRINT1("IOCTL_INTERNAL_USB_GET_BUS_INFO\n");
break;
}
case IOCTL_INTERNAL_USB_GET_BUSGUID_INFO:
{
DPRINT1("IOCTL_INTERNAL_USB_GET_BUSGUID_INFO\n");
break;
}
case IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME:
{
DPRINT1("IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME\n");
break;
}
case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
{
DPRINT("Ehci: IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %x\n", Stack->Parameters.Others.Argument2);
if (Stack->Parameters.Others.Argument1)
{
/* Return the root hubs devicehandle */
DPRINT("Returning RootHub Handle %x\n", PdoDeviceExtension->UsbDevices[0]);
*(PVOID *)Stack->Parameters.Others.Argument1 = (PVOID)PdoDeviceExtension->UsbDevices[0];
Status = STATUS_SUCCESS;
}
else
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
{
DPRINT("Ehci: IOCTL_INTERNAL_USB_GET_HUB_COUNT %x\n", IOCTL_INTERNAL_USB_GET_HUB_COUNT);
ASSERT(Stack->Parameters.Others.Argument1 != NULL);
if (Stack->Parameters.Others.Argument1)
{
/* FIXME: Determine the number of hubs between the usb device and root hub */
DPRINT1("RootHubCount %x\n", *(PULONG)Stack->Parameters.Others.Argument1);
*(PULONG)Stack->Parameters.Others.Argument1 = 1;
}
Status = STATUS_SUCCESS;
break;
}
case IOCTL_INTERNAL_USB_GET_HUB_NAME:
{
DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_NAME\n");
break;
}
case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO:
{
DPRINT1("IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO\n");
break;
}
case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
{
DPRINT1("IOCTL_INTERNAL_USB_GET_PORT_STATUS\n");
break;
}
case IOCTL_INTERNAL_USB_RESET_PORT:
{
DPRINT1("IOCTL_INTERNAL_USB_RESET_PORT\n");
break;
}
case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
{
DPRINT("Ehci: IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO Arg1 %x, Arg2 %x\n", Stack->Parameters.Others.Argument1, Stack->Parameters.Others.Argument2);
if (Stack->Parameters.Others.Argument1)
*(PVOID *)Stack->Parameters.Others.Argument1 = FdoDeviceExtension->Pdo;
/* Windows usbehci driver gives the Pdo in both Arguments. */
if (Stack->Parameters.Others.Argument2)
//*(PVOID *)Stack->Parameters.Others.Argument2 = IoGetAttachedDeviceReference(FdoDeviceExtension->DeviceObject);
*(PVOID *)Stack->Parameters.Others.Argument2 = FdoDeviceExtension->Pdo;
Information = 0;
Status = STATUS_SUCCESS;
break;
}
case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
{
PUSB_IDLE_CALLBACK_INFO CallBackInfo;
DPRINT1("Ehci: IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION\n");
/* FIXME: Set Callback for safe power down */
CallBackInfo = Stack->Parameters.DeviceIoControl.Type3InputBuffer;
DPRINT1("IdleCallback %x\n", CallBackInfo->IdleCallback);
DPRINT1("IdleContext %x\n", CallBackInfo->IdleContext);
PdoDeviceExtension->IdleCallback = CallBackInfo->IdleCallback;
PdoDeviceExtension->IdleContext = CallBackInfo->IdleContext;
Information = 0;
Status = STATUS_SUCCESS;
break;
}
default:
{
DPRINT1("Unhandled IoControlCode %x\n", Stack->Parameters.DeviceIoControl.IoControlCode);
break;
}
}
Irp->IoStatus.Information = Information;
if (Status != STATUS_PENDING)
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
NTSTATUS
PdoQueryId(PDEVICE_OBJECT DeviceObject, PIRP Irp, ULONG_PTR* Information)
{
WCHAR Buffer[256];
ULONG Index = 0;
ULONG IdType;
UNICODE_STRING SourceString;
UNICODE_STRING String;
NTSTATUS Status;
IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
switch (IdType)
{
case BusQueryDeviceID:
{
RtlInitUnicodeString(&SourceString, L"USB\\ROOT_HUB20");
break;
}
case BusQueryHardwareIDs:
{
Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID8086&PID265C&REV0000") + 1;
Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID8086&PID265C") + 1;
Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20") + 1;
Buffer[Index] = UNICODE_NULL;
SourceString.Length = SourceString.MaximumLength = Index * sizeof(WCHAR);
SourceString.Buffer = Buffer;
break;
}
case BusQueryCompatibleIDs:
{
/* We have none */
return STATUS_SUCCESS;
}
case BusQueryInstanceID:
{
return STATUS_SUCCESS;
}
default:
{
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
return STATUS_NOT_SUPPORTED;
}
}
Status = DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
&SourceString,
&String);
*Information = (ULONG_PTR)String.Buffer;
return Status;
}
NTSTATUS
PdoQueryDeviceRelations(PDEVICE_OBJECT DeviceObject, PDEVICE_RELATIONS* pDeviceRelations)
{
PDEVICE_RELATIONS DeviceRelations;
DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
if (!DeviceRelations)
return STATUS_INSUFFICIENT_RESOURCES;
DeviceRelations->Count = 1;
DeviceRelations->Objects[0] = DeviceObject;
ObReferenceObject(DeviceObject);
*pDeviceRelations = DeviceRelations;
return STATUS_SUCCESS;
}
NTSTATUS NTAPI
PdoDispatchPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
ULONG MinorFunction;
PIO_STACK_LOCATION Stack;
ULONG_PTR Information = Irp->IoStatus.Information;
NTSTATUS Status = Irp->IoStatus.Status;
Stack = IoGetCurrentIrpStackLocation(Irp);
MinorFunction = Stack->MinorFunction;
switch (MinorFunction)
{
case IRP_MN_QUERY_REMOVE_DEVICE:
case IRP_MN_REMOVE_DEVICE:
case IRP_MN_CANCEL_REMOVE_DEVICE:
case IRP_MN_STOP_DEVICE:
case IRP_MN_QUERY_STOP_DEVICE:
case IRP_MN_CANCEL_STOP_DEVICE:
case IRP_MN_QUERY_DEVICE_TEXT:
case IRP_MN_SURPRISE_REMOVAL:
case IRP_MN_QUERY_RESOURCES:
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
{
Status = STATUS_SUCCESS;
break;
}
case IRP_MN_START_DEVICE:
{
PUSB_DEVICE RootHubDevice;
PPDO_DEVICE_EXTENSION PdoDeviceExtension;
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
UNICODE_STRING InterfaceSymLinkName;
LONG i;
DPRINT1("Ehci: PDO StartDevice\n");
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension;
/* Create the root hub */
RootHubDevice = InternalCreateUsbDevice(1, 0, NULL, TRUE);
for (i = 0; i < PdoDeviceExtension->NumberOfPorts; i++)
{
PdoDeviceExtension->Ports[i].PortStatus = USB_PORT_STATUS_HIGH_SPEED | 0x8000;
PdoDeviceExtension->Ports[i].PortChange = 0;
if (!FdoDeviceExtension->ECHICaps.HCSParams.PortPowerControl)
PdoDeviceExtension->Ports[i].PortStatus |= USB_PORT_STATUS_POWER;
}
RtlCopyMemory(&RootHubDevice->DeviceDescriptor,
ROOTHUB2_DEVICE_DESCRIPTOR,
sizeof(ROOTHUB2_DEVICE_DESCRIPTOR));
RootHubDevice->DeviceDescriptor.idVendor = FdoDeviceExtension->VendorId;
RootHubDevice->DeviceDescriptor.idProduct = FdoDeviceExtension->DeviceId;
/* FIXME: Do something better below */
RootHubDevice->Configs = ExAllocatePoolWithTag(NonPagedPool,
sizeof(PVOID) * RootHubDevice->DeviceDescriptor.bNumConfigurations,
USB_POOL_TAG);
RootHubDevice->Configs[0] = ExAllocatePoolWithTag(NonPagedPool,
sizeof(USB_CONFIGURATION) + sizeof(PVOID) * ROOTHUB2_CONFIGURATION_DESCRIPTOR[4],
USB_POOL_TAG);
RootHubDevice->Configs[0]->Interfaces[0] = ExAllocatePoolWithTag(NonPagedPool,
sizeof(USB_INTERFACE) + sizeof(PVOID) * ROOTHUB2_INTERFACE_DESCRIPTOR[4],
USB_POOL_TAG);
RootHubDevice->Configs[0]->Interfaces[0]->EndPoints[0] = ExAllocatePoolWithTag(NonPagedPool,
sizeof(USB_ENDPOINT),
USB_POOL_TAG);
RootHubDevice->ActiveConfig = RootHubDevice->Configs[0];
RootHubDevice->ActiveInterface = RootHubDevice->ActiveConfig->Interfaces[0];
RtlCopyMemory(&RootHubDevice->ActiveConfig->ConfigurationDescriptor,
ROOTHUB2_CONFIGURATION_DESCRIPTOR,
sizeof(ROOTHUB2_CONFIGURATION_DESCRIPTOR));
RtlCopyMemory(&RootHubDevice->ActiveConfig->Interfaces[0]->InterfaceDescriptor,
ROOTHUB2_INTERFACE_DESCRIPTOR,
sizeof(ROOTHUB2_INTERFACE_DESCRIPTOR));
RtlCopyMemory(&RootHubDevice->ActiveConfig->Interfaces[0]->EndPoints[0]->EndPointDescriptor,
ROOTHUB2_ENDPOINT_DESCRIPTOR,
sizeof(ROOTHUB2_ENDPOINT_DESCRIPTOR));
RootHubDevice->DeviceSpeed = UsbHighSpeed;
RootHubDevice->DeviceType = Usb20Device;
PdoDeviceExtension->UsbDevices[0] = RootHubDevice;
/* Create a thread to handle the URB's */
/*
Status = PsCreateSystemThread(&PdoDeviceExtension->ThreadHandle,
THREAD_ALL_ACCESS,
NULL,
NULL,
NULL,
UrbWorkerThread,
(PVOID)PdoDeviceExtension);
if (!NT_SUCCESS(Status))
DPRINT1("Failed Thread Creation with Status: %x\n", Status);
*/
Status = IoRegisterDeviceInterface(DeviceObject, &GUID_DEVINTERFACE_USB_HUB, NULL, &InterfaceSymLinkName);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to register interface\n");
return Status;
}
else
{
Status = IoSetDeviceInterfaceState(&InterfaceSymLinkName, TRUE);
if (!NT_SUCCESS(Status))
return Status;
}
Status = STATUS_SUCCESS;
break;
}
case IRP_MN_QUERY_DEVICE_RELATIONS:
{
DPRINT1("Ehci: PDO QueryDeviceRelations\n");
switch (Stack->Parameters.QueryDeviceRelations.Type)
{
case TargetDeviceRelation:
{
PDEVICE_RELATIONS DeviceRelations = NULL;
Status = PdoQueryDeviceRelations(DeviceObject, &DeviceRelations);
Information = (ULONG_PTR)DeviceRelations;
break;
}
case BusRelations:
{
PPDO_DEVICE_EXTENSION PdoDeviceExtension;
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
DPRINT1("BusRelations!!!!!\n");
/* The hub driver has created the new device object and reported to pnp, as a result the pnp manager
has resent this IRP and type, so leave the next SCE request pending until a new device arrives.
Is there a better way to do this */
ExAcquireFastMutex(&PdoDeviceExtension->ListLock);
PdoDeviceExtension->HaltQueue = TRUE;
ExReleaseFastMutex(&PdoDeviceExtension->ListLock);
}
case RemovalRelations:
case EjectionRelations:
{
/* Ignore the request */
Information = Irp->IoStatus.Information;
Status = Irp->IoStatus.Status;
break;
}
default:
{
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unhandled type 0x%lx\n",
Stack->Parameters.QueryDeviceRelations.Type);
Status = STATUS_NOT_SUPPORTED;
break;
}
}
break;
}
case IRP_MN_QUERY_CAPABILITIES:
{
DPRINT("Ehci: PDO Query Capabilities\n");
PDEVICE_CAPABILITIES DeviceCapabilities;
ULONG i;
DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities;
DeviceCapabilities->LockSupported = FALSE;
DeviceCapabilities->EjectSupported = FALSE;
DeviceCapabilities->Removable = FALSE;
DeviceCapabilities->DockDevice = FALSE;
DeviceCapabilities->UniqueID = FALSE;
DeviceCapabilities->SilentInstall = FALSE;
DeviceCapabilities->RawDeviceOK = FALSE;
DeviceCapabilities->SurpriseRemovalOK = FALSE;
DeviceCapabilities->Address = 0;
DeviceCapabilities->UINumber = 0;
DeviceCapabilities->DeviceD2 = 1;
/* FIXME */
DeviceCapabilities->HardwareDisabled = FALSE;
//DeviceCapabilities->NoDisplayInUI = FALSE;
DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
for (i = 0; i < PowerSystemMaximum; i++)
DeviceCapabilities->DeviceState[i] = PowerDeviceD3;
DeviceCapabilities->DeviceWake = 0;
DeviceCapabilities->D1Latency = 0;
DeviceCapabilities->D2Latency = 0;
DeviceCapabilities->D3Latency = 0;
Information = 0;
Status = STATUS_SUCCESS;
break;
}
/*case IRP_MN_QUERY_DEVICE_TEXT:
{
Status = STATUS_NOT_SUPPORTED;
break;
}*/
case IRP_MN_QUERY_ID:
{
DPRINT("Ehci: PDO Query ID\n");
Status = PdoQueryId(DeviceObject, Irp, &Information);
break;
}
case IRP_MN_QUERY_INTERFACE:
{
UNICODE_STRING GuidString;
PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub;
PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI;
PPDO_DEVICE_EXTENSION PdoDeviceExtension;
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
DPRINT("Ehci: PDO Query Interface\n");
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension;
Status = RtlStringFromGUID(Stack->Parameters.QueryInterface.InterfaceType, &GuidString);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create string from GUID!\n");
}
/* Assume success */
Status = STATUS_SUCCESS;
Information = 0;
if (IsEqualGUIDAligned(Stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_HUB_GUID))
{
InterfaceHub = (PUSB_BUS_INTERFACE_HUB_V5)Stack->Parameters.QueryInterface.Interface;
InterfaceHub->Version = Stack->Parameters.QueryInterface.Version;
if (Stack->Parameters.QueryInterface.Version >= 0)
{
InterfaceHub->Size = Stack->Parameters.QueryInterface.Size;
InterfaceHub->BusContext = PdoDeviceExtension->DeviceObject;
InterfaceHub->InterfaceReference = (PINTERFACE_REFERENCE)InterfaceReference;
InterfaceHub->InterfaceDereference = (PINTERFACE_DEREFERENCE)InterfaceDereference;
}
if (Stack->Parameters.QueryInterface.Version >= 1)
{
InterfaceHub->CreateUsbDevice = CreateUsbDevice;
InterfaceHub->InitializeUsbDevice = InitializeUsbDevice;
InterfaceHub->GetUsbDescriptors = GetUsbDescriptors;
InterfaceHub->RemoveUsbDevice = RemoveUsbDevice;
InterfaceHub->RestoreUsbDevice = RestoreUsbDevice;
InterfaceHub->GetPortHackFlags = GetPortHackFlags;
InterfaceHub->QueryDeviceInformation = QueryDeviceInformation;
}
if (Stack->Parameters.QueryInterface.Version >= 2)
{
InterfaceHub->GetControllerInformation = GetControllerInformation;
InterfaceHub->ControllerSelectiveSuspend = ControllerSelectiveSuspend;
InterfaceHub->GetExtendedHubInformation = GetExtendedHubInformation;
InterfaceHub->GetRootHubSymbolicName = GetRootHubSymbolicName;
InterfaceHub->GetDeviceBusContext = GetDeviceBusContext;
InterfaceHub->Initialize20Hub = Initialize20Hub;
}
if (Stack->Parameters.QueryInterface.Version >= 3)
{
InterfaceHub->RootHubInitNotification = RootHubInitNotification;
}
if (Stack->Parameters.QueryInterface.Version >= 4)
{
InterfaceHub->FlushTransfers = FlushTransfers;
}
if (Stack->Parameters.QueryInterface.Version >= 5)
{
InterfaceHub->SetDeviceHandleData = SetDeviceHandleData;
}
if (Stack->Parameters.QueryInterface.Version >= 6)
{
DPRINT1("USB_BUS_INTERFACE_HUB_GUID version not supported!\n");
}
break;
}
if (IsEqualGUIDAligned(Stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_USBDI_GUID))
{
InterfaceDI = (PUSB_BUS_INTERFACE_USBDI_V2) Stack->Parameters.QueryInterface.Interface;
InterfaceDI->Version = Stack->Parameters.QueryInterface.Version;
if (Stack->Parameters.QueryInterface.Version >= 0)
{
//InterfaceDI->Size = sizeof(USB_BUS_INTERFACE_USBDI_V2);
InterfaceDI->Size = Stack->Parameters.QueryInterface.Size;
InterfaceDI->BusContext = PdoDeviceExtension->DeviceObject;
InterfaceDI->InterfaceReference = (PINTERFACE_REFERENCE)InterfaceReference;
InterfaceDI->InterfaceDereference = (PINTERFACE_DEREFERENCE)InterfaceDereference;
InterfaceDI->GetUSBDIVersion = GetUSBDIVersion;
InterfaceDI->QueryBusTime = QueryBusTime;
InterfaceDI->SubmitIsoOutUrb = SubmitIsoOutUrb;
InterfaceDI->QueryBusInformation = QueryBusInformation;
}
if (Stack->Parameters.QueryInterface.Version >= 1)
{
InterfaceDI->IsDeviceHighSpeed = IsDeviceHighSpeed;
}
if (Stack->Parameters.QueryInterface.Version >= 2)
{
InterfaceDI->EnumLogEntry = EnumLogEntry;
}
if (Stack->Parameters.QueryInterface.Version >= 3)
{
DPRINT1("SB_BUS_INTERFACE_USBDI_GUID version not supported!\n");
}
break;
}
DPRINT1("GUID Not Supported\n");
Status = Irp->IoStatus.Status;
Information = Irp->IoStatus.Information;
break;
}
case IRP_MN_QUERY_BUS_INFORMATION:
{
PPNP_BUS_INFORMATION BusInfo;
BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
if (!BusInfo)
Status = STATUS_INSUFFICIENT_RESOURCES;
else
{
/* FIXME */
/*RtlCopyMemory(
&BusInfo->BusTypeGuid,
&GUID_DEVINTERFACE_XXX,
sizeof(GUID));*/
BusInfo->LegacyBusType = PNPBus;
BusInfo->BusNumber = 0;
Information = (ULONG_PTR)BusInfo;
Status = STATUS_SUCCESS;
}
break;
}
default:
{
/* We are the PDO. So ignore */
DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", MinorFunction);
break;
}
}
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}