reactos/drivers/usb/usbhub_new/fdo.c

1013 lines
33 KiB
C
Raw Normal View History

/*
* PROJECT: ReactOS Universal Serial Bus Hub Driver
* LICENSE: GPL - See COPYING in the top level directory
* FILE: drivers/usb/usbhub/fdo.c
* PURPOSE: Handle FDO
* PROGRAMMERS:
* Michael Martin (michael.martin@reactos.org)
* Johannes Anderwald (johannes.anderwald@reactos.org)
*/
#define INITGUID
#define NDEBUG
#include "usbhub.h"
NTSTATUS
QueryStatusChangeEndpoint(
IN PDEVICE_OBJECT DeviceObject);
NTSTATUS
SubmitRequestToRootHub(
IN PDEVICE_OBJECT RootHubDeviceObject,
IN ULONG IoControlCode,
OUT PVOID OutParameter1,
OUT PVOID OutParameter2)
{
KEVENT Event;
PIRP Irp;
IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
PIO_STACK_LOCATION Stack = NULL;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
//
// Build Control Request
//
Irp = IoBuildDeviceIoControlRequest(IoControlCode,
RootHubDeviceObject,
NULL, 0,
NULL, 0,
TRUE,
&Event,
&IoStatus);
if (Irp == NULL)
{
DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Initialize the status block before sending the IRP
//
IoStatus.Status = STATUS_NOT_SUPPORTED;
IoStatus.Information = 0;
//
// Get Next Stack Location and Initialize it
//
Stack = IoGetNextIrpStackLocation(Irp);
Stack->Parameters.Others.Argument1 = OutParameter1;
Stack->Parameters.Others.Argument2 = OutParameter2;
//
// Call RootHub
//
Status = IoCallDriver(RootHubDeviceObject, Irp);
if (Status == STATUS_PENDING)
{
DPRINT1("USBHUB: Operation pending\n");
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
return Status;
}
NTSTATUS
GetPortStatusAndChange(
IN PDEVICE_OBJECT RootHubDeviceObject,
IN ULONG PortId,
OUT PPORT_STATUS_CHANGE StatusChange)
{
NTSTATUS Status;
PURB Urb;
//
// Allocate URB
//
Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
if (!Urb)
{
DPRINT1("Failed to allocate memory for URB!\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Zero it
//
RtlZeroMemory(Urb, sizeof(URB));
//
// Create URB for getting Port Status
//
UsbBuildVendorRequest(Urb,
URB_FUNCTION_CLASS_OTHER,
sizeof(Urb->UrbControlVendorClassRequest),
USBD_TRANSFER_DIRECTION_OUT,
0,
USB_REQUEST_GET_STATUS,
0,
PortId,
StatusChange,
0,
sizeof(PORT_STATUS_CHANGE),
0);
//
// Query the Root Hub
//
Status = SubmitRequestToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
//
// Free URB
//
ExFreePool(Urb);
return Status;
}
NTSTATUS
SetPortFeature(
IN PDEVICE_OBJECT RootHubDeviceObject,
IN ULONG PortId,
IN ULONG Feature)
{
NTSTATUS Status;
PURB Urb;
//
// Allocate URB
//
Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
if (!Urb)
{
DPRINT1("Failed to allocate memory for URB!\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Zero it
//
RtlZeroMemory(Urb, sizeof(URB));
//
// Create URB for Clearing Port Reset
//
UsbBuildVendorRequest(Urb,
URB_FUNCTION_CLASS_OTHER,
sizeof(Urb->UrbControlVendorClassRequest),
USBD_TRANSFER_DIRECTION_IN,
0,
USB_REQUEST_SET_FEATURE,
Feature,
PortId,
NULL,
0,
0,
0);
//
// Query the Root Hub
//
Status = SubmitRequestToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
//
// Free URB
//
ExFreePool(Urb);
return Status;
}
NTSTATUS
ClearPortFeature(
IN PDEVICE_OBJECT RootHubDeviceObject,
IN ULONG PortId,
IN ULONG Feature)
{
NTSTATUS Status;
PURB Urb;
//
// Allocate a URB
//
Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
if (!Urb)
{
DPRINT1("Failed to allocate memory for URB!\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Zero it
//
RtlZeroMemory(Urb, sizeof(URB));
//
// Create URB for Clearing Port Reset
//
UsbBuildVendorRequest(Urb,
URB_FUNCTION_CLASS_OTHER,
sizeof(Urb->UrbControlVendorClassRequest),
USBD_TRANSFER_DIRECTION_IN,
0,
USB_REQUEST_CLEAR_FEATURE,
Feature,
PortId,
NULL,
0,
0,
0);
//
// Query the Root Hub
//
Status = SubmitRequestToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
//
// Free URB
//
ExFreePool(Urb);
return Status;
}
VOID NTAPI
DeviceStatusChangeThread(
IN PVOID Context)
{
NTSTATUS Status;
PDEVICE_OBJECT DeviceObject;
PHUB_DEVICE_EXTENSION HubDeviceExtension;
PWORK_ITEM_DATA WorkItemData;
PORT_STATUS_CHANGE PortStatus;
LONG PortId, i;
WorkItemData = (PWORK_ITEM_DATA)Context;
DeviceObject = (PDEVICE_OBJECT)WorkItemData->Context;
HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
//
// Itterate all ports
//
for (PortId = 1; PortId <= HubDeviceExtension->UsbExtHubInfo.NumberOfPorts; PortId++)
{
PortStatus.Change = 0;
PortStatus.Status = 0;
//
// Get Port Status
//
Status = GetPortStatusAndChange(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, &PortStatus);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get port status for port %d, Status %x\n", PortId, Status);
// FIXME: Do we really want to halt further SCE requests?
return;
}
//
// Check for new device connection
//
if (PortStatus.Change == USB_PORT_STATUS_CONNECT)
{
//
// Clear Connection Status
//
Status = ClearPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, C_PORT_CONNECTION);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to clear connection change for port %d\n", PortId);
// FIXME: Do we really want to halt further SCE requests?
return;
}
//
// Get Port Status and ensure it updated
//
Status = GetPortStatusAndChange(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, &PortStatus);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get port status for port %d, Status %x\n", PortId, Status);
// FIXME: Do we really want to halt further SCE requests?
return;
}
if (PortStatus.Change != 0)
{
DPRINT1("Port %d did not clear Connection Change!\n");
// FIXME: Do we really want to halt further SCE requests?
return;
}
//
// FIXME: Create the device object and enable the port
//
//CreateUsbChildDeviceObject
}
}
//
// Send another SCE Request
//
QueryStatusChangeEndpoint(DeviceObject);
ExFreePool(WorkItemData);
}
NTSTATUS
StatusChangeEndpointCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
PDEVICE_OBJECT RealDeviceObject;
PHUB_DEVICE_EXTENSION HubDeviceExtension;
PWORK_ITEM_DATA WorkItemData;
LONG i;
RealDeviceObject = (PDEVICE_OBJECT)Context;
HubDeviceExtension = (PHUB_DEVICE_EXTENSION)RealDeviceObject->DeviceExtension;
//
// Determine which port has changed
//
for (i=0; i < HubDeviceExtension->UsbExtHubInfo.NumberOfPorts; i++)
{
DPRINT1("Port %x HubDeviceExtension->PortStatus %x\n",i+1, HubDeviceExtension->PortStatusChange[i].Status);
DPRINT1("Port %x HubDeviceExtension->PortChange %x\n",i+1, HubDeviceExtension->PortStatusChange[i].Change);
}
//
// Free the Irp and return more processing required so the IO Manger doesnt try to free it
//
IoFreeIrp(Irp);
//
// Create and initialize work item data
//
WorkItemData = ExAllocatePoolWithTag(NonPagedPool, sizeof(WORK_ITEM_DATA), USB_HUB_TAG);
if (!WorkItemData)
{
DPRINT1("Failed to allocate memory!n");
return STATUS_INSUFFICIENT_RESOURCES;
}
WorkItemData->Context = RealDeviceObject;
ExInitializeWorkItem(&WorkItemData->WorkItem, (PWORKER_THREAD_ROUTINE)DeviceStatusChangeThread, (PVOID)WorkItemData);
//
// Queue the work item to handle initializing the device
//
ExQueueWorkItem(&WorkItemData->WorkItem, DelayedWorkQueue);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
QueryStatusChangeEndpoint(
IN PDEVICE_OBJECT DeviceObject)
{
NTSTATUS Status;
PIO_STACK_LOCATION Stack;
PHUB_DEVICE_EXTENSION HubDeviceExtension;
HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
//
// Initialize URB for Status Change Endpoint request
//
UsbBuildInterruptOrBulkTransferRequest(&HubDeviceExtension->PendingSCEUrb,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
HubDeviceExtension->PipeHandle,
HubDeviceExtension->PortStatusChange,
NULL,
sizeof(USHORT) * 2 * HubDeviceExtension->UsbExtHubInfo.NumberOfPorts,
USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
NULL);
//
// Set the device handle to null for roothub
//
HubDeviceExtension->PendingSCEUrb.UrbHeader.UsbdDeviceHandle = NULL;
//
// Allocate an Irp
//
HubDeviceExtension->PendingSCEIrp = IoAllocateIrp(HubDeviceExtension->RootHubPhysicalDeviceObject->StackSize,
FALSE);
if (!HubDeviceExtension->PendingSCEIrp)
{
DPRINT1("USBHUB: Failed to allocate IRP for SCE request!\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Initialize the IRP
//
HubDeviceExtension->PendingSCEIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
HubDeviceExtension->PendingSCEIrp->IoStatus.Information = 0;
HubDeviceExtension->PendingSCEIrp->Flags = 0;
HubDeviceExtension->PendingSCEIrp->UserBuffer = NULL;
//
// Get the Next Stack Location and Initialize it
//
Stack = IoGetNextIrpStackLocation(HubDeviceExtension->PendingSCEIrp);
Stack->DeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
Stack->Parameters.Others.Argument1 = &HubDeviceExtension->PendingSCEUrb;
Stack->Parameters.Others.Argument2 = NULL;
Stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
Stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
//
// Set the completion routine for when device is connected to root hub
//
IoSetCompletionRoutine(HubDeviceExtension->PendingSCEIrp,
(PIO_COMPLETION_ROUTINE) StatusChangeEndpointCompletion,
DeviceObject,
TRUE,
TRUE,
TRUE);
//
// Send to RootHub
//
Status = IoCallDriver(HubDeviceExtension->RootHubPhysicalDeviceObject, HubDeviceExtension->PendingSCEIrp);
return STATUS_PENDING;
}
NTSTATUS
QueryInterface(
IN PDEVICE_OBJECT DeviceObject,
IN CONST GUID InterfaceType,
IN LONG Size,
IN LONG Version,
OUT PVOID Interface)
{
KEVENT Event;
PIRP Irp;
IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
PIO_STACK_LOCATION Stack = NULL;
//
// Initialize the Event used to wait for Irp completion
//
KeInitializeEvent(&Event, NotificationEvent, FALSE);
//
// Build Control Request
//
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
DeviceObject,
NULL,
0,
NULL,
&Event,
&IoStatus);
//
// Get Next Stack Location and Initialize it.
//
Stack = IoGetNextIrpStackLocation(Irp);
Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
Stack->Parameters.QueryInterface.InterfaceType= &InterfaceType;//USB_BUS_INTERFACE_HUB_GUID;
Stack->Parameters.QueryInterface.Size = Size;
Stack->Parameters.QueryInterface.Version = Version;
Stack->Parameters.QueryInterface.Interface = Interface;
Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
DPRINT("Operation pending\n");
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
return Status;
}
NTSTATUS
GetUsbDeviceDescriptor(
IN PDEVICE_OBJECT ChildDeviceObject,
IN UCHAR DescriptorType,
IN UCHAR Index,
IN USHORT LangId,
OUT PVOID TransferBuffer,
IN ULONG TransferBufferLength)
{
NTSTATUS Status;
PURB Urb;
PHUB_DEVICE_EXTENSION HubDeviceExtension;
PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
PMDL BufferMdl;
//
// Get the Hubs Device Extension
//
ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)ChildDeviceObject->DeviceExtension;
HubDeviceExtension = (PHUB_DEVICE_EXTENSION) ChildDeviceExtension->ParentDeviceObject->DeviceExtension;
//
// Allocate a URB
//
Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
if (!Urb)
{
DPRINT1("Failed to allocate memory for URB!\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Zero it
//
RtlZeroMemory(Urb, sizeof(URB));
//
// Create a MDL for buffer
//
BufferMdl = IoAllocateMdl(TransferBuffer,
TransferBufferLength,
FALSE,
FALSE,
NULL);
//
// Lock the Mdl
//
_SEH2_TRY
{
MmProbeAndLockPages(BufferMdl, KernelMode, IoWriteAccess);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
DPRINT1("MmProbeAndLockPages Failed!\n");
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
//
// Create URB for getting device descriptor
//
UsbBuildGetDescriptorRequest(Urb,
sizeof(Urb->UrbControlDescriptorRequest),
DescriptorType,
Index,
LangId,
NULL,
BufferMdl,
TransferBufferLength,
NULL);
//
// Set the device handle
//
Urb->UrbHeader.UsbdDeviceHandle = (PVOID)ChildDeviceObject;
//
// Query the Root Hub
//
Status = SubmitRequestToRootHub(HubDeviceExtension->RootHubPhysicalDeviceObject,
IOCTL_INTERNAL_USB_SUBMIT_URB,
Urb,
NULL);
//
// Free Mdl
//
IoFreeMdl(BufferMdl);
return Status;
}
NTSTATUS
CreateUsbChildDeviceObject(
IN PDEVICE_OBJECT UsbHubDeviceObject,
IN LONG PortId,
OUT PDEVICE_OBJECT *UsbChildDeviceObject)
{
//NTSTATUS Status;
//PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
return STATUS_SUCCESS;
}
NTSTATUS
USBHUB_FdoQueryBusRelations(
IN PDEVICE_OBJECT DeviceObject,
OUT PDEVICE_RELATIONS* pDeviceRelations)
{
PHUB_DEVICE_EXTENSION HubDeviceExtension;
PDEVICE_RELATIONS DeviceRelations;
ULONG i;
ULONG Children = 0;
ULONG NeededSize;
HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
//
// Count the number of children
//
for (i = 0; i < USB_MAXCHILDREN; i++)
{
if (HubDeviceExtension->ChildDeviceObject[i] == NULL)
{
continue;
}
Children++;
}
NeededSize = sizeof(DEVICE_RELATIONS);
if (Children > 1)
NeededSize += (Children - 1) * sizeof(PDEVICE_OBJECT);
//
// Allocate DeviceRelations
//
DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool,
NeededSize);
if (!DeviceRelations)
return STATUS_INSUFFICIENT_RESOURCES;
DeviceRelations->Count = Children;
Children = 0;
//
// Fill in return structure
//
for (i = 0; i < USB_MAXCHILDREN; i++)
{
if (HubDeviceExtension->ChildDeviceObject[i])
{
ObReferenceObject(HubDeviceExtension->ChildDeviceObject[i]);
DeviceRelations->Objects[Children++] = HubDeviceExtension->ChildDeviceObject[i];
}
}
ASSERT(Children == DeviceRelations->Count);
*pDeviceRelations = DeviceRelations;
//
// Send the first SCE Request
//
QueryStatusChangeEndpoint(DeviceObject);
return STATUS_SUCCESS;
}
NTSTATUS
USBHUB_FdoHandlePnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION Stack;
NTSTATUS Status = STATUS_SUCCESS;
ULONG_PTR Information = 0;
PHUB_DEVICE_EXTENSION HubDeviceExtension;
HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
Stack = IoGetCurrentIrpStackLocation(Irp);
switch (Stack->MinorFunction)
{
case IRP_MN_START_DEVICE:
{
PURB Urb;
ULONG Result = 0;
PUSB_INTERFACE_DESCRIPTOR Pid;
ULONG PortId;
USBD_INTERFACE_LIST_ENTRY InterfaceList[2] = {{NULL, NULL}, {NULL, NULL}};
PURB ConfigUrb = NULL;
DPRINT1("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
//
// Allocated size including the sizeof USBD_INTERFACE_LIST_ENTRY
//
Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY), USB_HUB_TAG);
RtlZeroMemory(Urb, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY));
//
// Get the Root Hub Pdo
//
SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject,
IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO,
&HubDeviceExtension->RootHubPhysicalDeviceObject,
&HubDeviceExtension->RootHubFunctionalDeviceObject);
ASSERT(HubDeviceExtension->RootHubPhysicalDeviceObject);
ASSERT(HubDeviceExtension->RootHubFunctionalDeviceObject);
DPRINT1("RootPdo %x, RootFdo %x\n",
HubDeviceExtension->RootHubPhysicalDeviceObject,
HubDeviceExtension->RootHubFunctionalDeviceObject);
//
// Send the StartDevice to RootHub
//
Status = ForwardIrpAndWait(HubDeviceExtension->RootHubPhysicalDeviceObject, Irp);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to start the RootHub PDO\n");
ASSERT(FALSE);
}
//
// Get the current number of hubs
//
Status = SubmitRequestToRootHub(HubDeviceExtension->RootHubPhysicalDeviceObject,
IOCTL_INTERNAL_USB_GET_HUB_COUNT,
&HubDeviceExtension->NumberOfHubs, NULL);
//
// Get the Hub Interface
//
Status = QueryInterface(HubDeviceExtension->RootHubPhysicalDeviceObject,
USB_BUS_INTERFACE_HUB_GUID,
sizeof(USB_BUS_INTERFACE_HUB_V5),
5,
(PVOID)&HubDeviceExtension->HubInterface);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status);
return STATUS_UNSUCCESSFUL;
}
//
// Get the USBDI Interface
//
Status = QueryInterface(HubDeviceExtension->RootHubPhysicalDeviceObject,
USB_BUS_INTERFACE_USBDI_GUID,
sizeof(USB_BUS_INTERFACE_USBDI_V2),
2,
(PVOID)&HubDeviceExtension->UsbDInterface);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status);
return Status;
}
//
// Get Root Hub Device Handle
//
Status = SubmitRequestToRootHub(HubDeviceExtension->RootHubPhysicalDeviceObject,
IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE,
&HubDeviceExtension->RootHubHandle,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("GetRootHubDeviceHandle failed with status 0x%08lx\n", Status);
return Status;
}
//
// Get Hub Device Information
//
Status = HubDeviceExtension->HubInterface.QueryDeviceInformation(HubDeviceExtension->RootHubPhysicalDeviceObject,
HubDeviceExtension->RootHubHandle,
&HubDeviceExtension->DeviceInformation,
sizeof(USB_DEVICE_INFORMATION_0),
&Result);
DPRINT1("Status %x, Result 0x%08lx\n", Status, Result);
DPRINT1("InformationLevel %x\n", HubDeviceExtension->DeviceInformation.InformationLevel);
DPRINT1("ActualLength %x\n", HubDeviceExtension->DeviceInformation.ActualLength);
DPRINT1("PortNumber %x\n", HubDeviceExtension->DeviceInformation.PortNumber);
DPRINT1("DeviceDescriptor %x\n", HubDeviceExtension->DeviceInformation.DeviceDescriptor);
DPRINT1("HubAddress %x\n", HubDeviceExtension->DeviceInformation.HubAddress);
DPRINT1("NumberofPipes %x\n", HubDeviceExtension->DeviceInformation.NumberOfOpenPipes);
//
// Get Root Hubs Device Descriptor
//
UsbBuildGetDescriptorRequest(Urb,
sizeof(Urb->UrbControlDescriptorRequest),
USB_DEVICE_DESCRIPTOR_TYPE,
0,
0,
&HubDeviceExtension->HubDeviceDescriptor,
NULL,
sizeof(USB_DEVICE_DESCRIPTOR),
NULL);
Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle;
Status = SubmitRequestToRootHub(HubDeviceExtension->RootHubPhysicalDeviceObject,
IOCTL_INTERNAL_USB_SUBMIT_URB,
Urb,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get HubDeviceDescriptor!\n");
}
DumpDeviceDescriptor(&HubDeviceExtension->HubDeviceDescriptor);
//
// Get Root Hubs Configuration Descriptor
//
UsbBuildGetDescriptorRequest(Urb,
sizeof(Urb->UrbControlDescriptorRequest),
USB_CONFIGURATION_DESCRIPTOR_TYPE,
0,
0,
&HubDeviceExtension->HubConfigDescriptor,
NULL,
sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR),
NULL);
Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle;
Status = SubmitRequestToRootHub(HubDeviceExtension->RootHubPhysicalDeviceObject,
IOCTL_INTERNAL_USB_SUBMIT_URB,
Urb,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get RootHub Configuration with status %x\n", Status);
ASSERT(FALSE);
}
ASSERT(HubDeviceExtension->HubConfigDescriptor.wTotalLength);
DumpConfigurationDescriptor(&HubDeviceExtension->HubConfigDescriptor);
Status = HubDeviceExtension->HubInterface.GetExtendedHubInformation(HubDeviceExtension->RootHubPhysicalDeviceObject,
HubDeviceExtension->RootHubPhysicalDeviceObject,
&HubDeviceExtension->UsbExtHubInfo,
sizeof(USB_EXTHUB_INFORMATION_0),
&Result);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n");
ASSERT(FALSE);
}
DPRINT1("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension->UsbExtHubInfo.NumberOfPorts);
//
// Get the Hub Descriptor
//
UsbBuildVendorRequest(Urb,
URB_FUNCTION_CLASS_DEVICE,
sizeof(Urb->UrbControlVendorClassRequest),
USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
0,
USB_DEVICE_CLASS_RESERVED,
0,
0,
&HubDeviceExtension->HubDescriptor,
NULL,
sizeof(USB_HUB_DESCRIPTOR),
NULL);
Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle;
Status = SubmitRequestToRootHub(HubDeviceExtension->RootHubPhysicalDeviceObject,
IOCTL_INTERNAL_USB_SUBMIT_URB,
Urb,
NULL);
//
// FIXME: This is returning nothing.
//
DPRINT1("bDescriptorType %x\n", HubDeviceExtension->HubDescriptor.bDescriptorType);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get Hub Descriptor!\n");
ExFreePool(Urb);
return STATUS_UNSUCCESSFUL;
}
//
// Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub
//
HubDeviceExtension->PortStatusChange = ExAllocatePoolWithTag(NonPagedPool,
sizeof(ULONG) * HubDeviceExtension->UsbExtHubInfo.NumberOfPorts,
USB_HUB_TAG);
//
// Initialize the Hub
//
Status = HubDeviceExtension->HubInterface.Initialize20Hub(HubDeviceExtension->RootHubPhysicalDeviceObject,
HubDeviceExtension->RootHubHandle, 1);
DPRINT1("Status %x\n", Status);
//
// Get the first Configuration Descriptor
//
Pid = USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension->HubConfigDescriptor,
&HubDeviceExtension->HubConfigDescriptor,
-1, -1, -1, -1, -1);
ASSERT(Pid != NULL);
InterfaceList[0].InterfaceDescriptor = Pid;
ConfigUrb = USBD_CreateConfigurationRequestEx(&HubDeviceExtension->HubConfigDescriptor,
(PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList);
ASSERT(ConfigUrb != NULL);
Status = SubmitRequestToRootHub(HubDeviceExtension->RootHubPhysicalDeviceObject,
IOCTL_INTERNAL_USB_SUBMIT_URB,
ConfigUrb,
NULL);
HubDeviceExtension->ConfigurationHandle = ConfigUrb->UrbSelectConfiguration.ConfigurationHandle;
HubDeviceExtension->PipeHandle = ConfigUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle;
DPRINT1("Configuration Handle %x\n", HubDeviceExtension->ConfigurationHandle);
ExFreePool(ConfigUrb);
//
// Enable power on all ports
//
for (PortId = 1; PortId <= HubDeviceExtension->HubDescriptor.bNumberOfPorts; PortId++)
{
Status = SetPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, PORT_POWER);
if (!NT_SUCCESS(Status))
DPRINT1("Failed to power on port %d\n", PortId);
}
ExFreePool(Urb);
break;
}
case IRP_MN_QUERY_DEVICE_RELATIONS:
{
switch (Stack->Parameters.QueryDeviceRelations.Type)
{
case BusRelations:
{
PDEVICE_RELATIONS DeviceRelations = NULL;
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
Status = USBHUB_FdoQueryBusRelations(DeviceObject, &DeviceRelations);
Information = (ULONG_PTR)DeviceRelations;
break;
}
case RemovalRelations:
{
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
return ForwardIrpAndForget(DeviceObject, Irp);
}
default:
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
Stack->Parameters.QueryDeviceRelations.Type);
return ForwardIrpAndForget(DeviceObject, Irp);
}
break;
}
case IRP_MN_QUERY_BUS_INFORMATION:
{
DPRINT1("IRP_MN_QUERY_BUS_INFORMATION\n");
break;
}
case IRP_MN_QUERY_ID:
{
DPRINT1("IRP_MN_QUERY_ID\n");
break;
}
case IRP_MN_QUERY_CAPABILITIES:
{
DPRINT1("IRP_MN_QUERY_CAPABILITIES\n");
break;
}
default:
{
DPRINT1(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack->MinorFunction);
return ForwardIrpAndForget(DeviceObject, Irp);
}
}
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
NTSTATUS
USBHUB_FdoHandleDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT1("FdoHandleDeviceControl\n");
UNIMPLEMENTED
return STATUS_NOT_IMPLEMENTED;
}